svn merge -r 12294:12347 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Mon, 22 Oct 2007 23:05:09 +0000 (23:05 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Mon, 22 Oct 2007 23:05:09 +0000 (23:05 +0000)
102 files changed:
intern/bmfont/BMF_Api.h
intern/bmfont/intern/BMF_Api.cpp
intern/bmfont/intern/BMF_BitmapFont.cpp
intern/bmfont/intern/BMF_BitmapFont.h
projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj
release/scripts/console.py
release/scripts/export_obj.py
release/scripts/scripttemplate_pyconstraint.py
source/blender/avi/intern/options.c
source/blender/blenkernel/BKE_action.h
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/BKE_bad_level_calls.h
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_constraint.h
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/SConscript
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/Makefile
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/writeavi.c
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenlib/intern/storage.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/blenpluginapi/iff.h
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/intern/IMB_imginfo.h
source/blender/imbuf/intern/imginfo.c
source/blender/imbuf/intern/png.c
source/blender/imbuf/intern/rectop.c
source/blender/imbuf/intern/thumbs.c
source/blender/include/BIF_editconstraint.h
source/blender/include/BIF_editsound.h
source/blender/include/BSE_time.h
source/blender/include/blendef.h
source/blender/include/butspace.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/python/BPY_extern.h
source/blender/python/BPY_interface.c
source/blender/python/api2_2x/Constraint.c
source/blender/python/api2_2x/Pose.c
source/blender/python/api2_2x/doc/Pose.py
source/blender/python/api2_2x/euler.c
source/blender/python/api2_2x/quat.c
source/blender/python/api2_2x/sceneRender.c
source/blender/python/api2_2x/sceneSequence.c
source/blender/python/api2_2x/vector.c
source/blender/quicktime/apple/quicktime_export.c
source/blender/src/buttons_object.c
source/blender/src/buttons_scene.c
source/blender/src/buttons_shading.c
source/blender/src/drawipo.c
source/blender/src/drawmesh.c
source/blender/src/drawobject.c
source/blender/src/drawseq.c
source/blender/src/drawsound.c
source/blender/src/drawtime.c
source/blender/src/drawview.c
source/blender/src/editarmature.c
source/blender/src/editconstraint.c
source/blender/src/editipo.c
source/blender/src/editipo_mods.c
source/blender/src/editmesh_tools.c
source/blender/src/editnla.c
source/blender/src/editobject.c
source/blender/src/editscreen.c
source/blender/src/editseq.c
source/blender/src/editsima.c
source/blender/src/edittime.c
source/blender/src/filesel.c
source/blender/src/hddaudio.c
source/blender/src/header_action.c
source/blender/src/header_filesel.c
source/blender/src/header_nla.c
source/blender/src/header_text.c
source/blender/src/header_time.c
source/blender/src/header_view3d.c
source/blender/src/outliner.c
source/blender/src/poseobject.c
source/blender/src/seqaudio.c
source/blender/src/seqeffects.c
source/blender/src/space.c
source/blender/src/toolbox.c
source/blender/src/transform.c
source/blender/src/transform_constraints.c
source/blender/src/usiblender.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/nan_definitions.mk

index 5900ea85ec79d9c6c4c46bcdb7b70b1cb017caee..1b4a4ee3129ff0aa7596865b56ac97bc9b75fca6 100644 (file)
@@ -109,6 +109,11 @@ void BMF_GetStringBoundingBox(BMF_Font* font, char* str, float*llx, float *lly,
  */
 void BMF_GetFontBoundingBox(BMF_Font* font, int *xmin_r, int *ymin_r, int *xmax_r, int *ymax_r);
 
+/**
+ * Same as GetFontBoundingBox but only returns the height
+ */
+int BMF_GetFontHeight(BMF_Font* font);
+
 /**
  * Convert the given @a font to a texture, and return the GL texture
  * ID of the texture. If the texture ID is bound, text can
@@ -134,6 +139,23 @@ int BMF_GetFontTexture(BMF_Font* font);
  */
 void BMF_DrawStringTexture(BMF_Font* font, char* string, float x, float y, float z);
 
+       /**
+ * Draw the given @a string at the point @a xpos, @a ypos using
+ * char and float buffers.
+ * 
+ * @param string The c-string to draw.
+ * @param xpos The x coordinate to start drawing at.
+ * @param ypos The y coordinate to start drawing at.
+ * @param fgcol The forground color.
+ * @param bgcol The background color.
+ * @param buf Unsigned char image buffer, when NULL to not operate on it.
+ * @param fbuf float image buffer, when NULL to not operate on it.
+ * @param w image buffer width.
+ * @param h image buffer height.
+        */
+void BMF_DrawStringBuf(BMF_Font* font, char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h);
+
+
 #ifdef __cplusplus
 }
 #endif
index 176ef452fdc2465d0dbfa30e828e519e6d5f13d9..eaa8ffb939d624cca906263556f6dba9cba3fc9b 100644 (file)
@@ -164,6 +164,12 @@ void BMF_GetFontBoundingBox(BMF_Font* font, int *xmin_r, int *ymin_r, int *xmax_
        ((BMF_BitmapFont*)font)->GetFontBoundingBox(*xmin_r, *ymin_r, *xmax_r, *ymax_r);
 }
 
+int BMF_GetFontHeight(BMF_Font* font)
+{
+       if (!font) return -1;
+       return ((BMF_BitmapFont*)font)->GetFontHeight();
+}
+
 int BMF_GetFontTexture(BMF_Font* font) {
        if (!font) return -1;
        return ((BMF_BitmapFont*)font)->GetTexture();
@@ -173,3 +179,8 @@ void BMF_DrawStringTexture(BMF_Font* font, char *string, float x, float y, float
        if (!font) return;
        ((BMF_BitmapFont*)font)->DrawStringTexture(string, x, y, z);
 }
+
+void BMF_DrawStringBuf(BMF_Font* font, char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h) {
+       if (!font) return;
+       ((BMF_BitmapFont*)font)->DrawStringBuf(str, posx, posy, col, buf, fbuf, w, h);
+}
index 8be4ff19a4f1fa7bb7d4a99d90298aa49abb2a46..99ded41007f39f86daaed7c4c6358f9215c80155 100644 (file)
  * Copyright (C) 2001 NaN Technologies B.V.
  */
 
+
+#include <stdio.h>
+
+
+
 #include <string.h>
 
 #ifdef HAVE_CONFIG_H
@@ -115,6 +120,11 @@ void BMF_BitmapFont::GetFontBoundingBox(int & xMin, int & yMin, int & xMax, int
        yMax = m_fontData->ymax;
 }
 
+int BMF_BitmapFont::GetFontHeight( void )
+{
+       return m_fontData->ymax - m_fontData->ymin;
+}
+
 void BMF_BitmapFont::GetStringBoundingBox(char* str, float*llx, float *lly, float *urx, float *ury)
 {
        unsigned char c;
@@ -229,3 +239,83 @@ void BMF_BitmapFont::DrawStringTexture(char *str, float x, float y, float z)
        }
        glEnd();
 }
+
+#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
+
+
+void BMF_BitmapFont::DrawStringBuf(char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h)
+{
+       int x, y;
+       
+       if (buf==0 && fbuf==0)
+               return;
+
+       /*offset for font*/
+       posx -= m_fontData->xmin;
+       posy -= m_fontData->ymin;
+       
+       if (buf) {
+               unsigned char colch[3];
+               unsigned char *max, *pixel;
+               unsigned char c;
+               
+               for (x=0; x<3; x++) {
+                       colch[x] = FTOCHAR(col[x]);
+               }
+               
+               max = buf + (4 * (w * h));
+               while ((c = (unsigned char) *str++)) {
+                       BMF_CharData & cd = m_fontData->chars[c];
+                       if (cd.data_offset != -1) { 
+                               for (y = 0; y < cd.height; y++) {
+                                       unsigned char* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y];
+                                       for (x = cd.xorig; x < cd.width; x++) {
+                                               pixel = buf + 4 * (((posy + y) * w) + (posx + x));
+                                               if ((pixel < max) && (pixel > buf)) {
+                                                       int byteIdx = x/8;
+                                                       int bitIdx = 7 - (x%8);
+                                                       
+                                                       if (chrRow[byteIdx]&(1<<bitIdx)) {
+                                                               pixel[0] = colch[0];
+                                                               pixel[1] = colch[1];
+                                                               pixel[2] = colch[2];
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       posx += cd.advance;
+               }
+       }
+       
+       if (fbuf) {
+               float *pixel, *max;
+               unsigned char c;
+               int x, y;
+               
+               max = fbuf + (4 * (w * h));
+               
+               while ((c = (unsigned char) *str++)) {
+                       BMF_CharData & cd = m_fontData->chars[c];
+                       if (cd.data_offset != -1) { 
+                               for (y = 0; y < cd.height; y++) {
+                                       unsigned char* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y];
+                                       for (x = cd.xorig; x < cd.width; x++) {
+                                               pixel = fbuf + 4 * (((posy + y - cd.yorig) * w) + (posx + x));
+                                               if ((pixel < max) && (pixel > fbuf)) {
+                                                       int byteIdx = x/8;
+                                                       int bitIdx = 7 - (x%8);
+                                                       
+                                                       if (chrRow[byteIdx]&(1<<bitIdx)) {
+                                                               pixel[0] = col[0];
+                                                               pixel[1] = col[1];
+                                                               pixel[2] = col[2];
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       posx += cd.advance;
+               }
+       }
+}
index e8e0abc0561d09b79b03810f2909ca43cdcaee42..986de2bb399debfc38e830bb2ac871881d2cf286 100644 (file)
@@ -78,6 +78,11 @@ public:
         */
        void GetFontBoundingBox(int & xMin, int & yMin, int & xMax, int & yMax);
        
+       /**
+        * Return the bounding box height of the font.
+        */
+       int GetFontHeight(void);
+       
        /**
         * Returns the bounding box of a string of characters.
         * @param font  The font to use.
@@ -113,6 +118,21 @@ public:
         */
        void DrawStringTexture(char* string, float x, float y, float z);
        
+       /**
+        * Draw the given @a string at the point @a xpos, @a ypos using
+        * char and float buffers.
+        * 
+        * @param string The c-string to draw.
+        * @param xpos The x coordinate to start drawing at.
+        * @param ypos The y coordinate to start drawing at.
+        * @param col The forground color.
+        * @param buf Unsigned char image buffer, when NULL to not operate on it.
+        * @param fbuf float image buffer, when NULL to not operate on it.
+        * @param w image buffer width.
+        * @param h image buffer height.
+        */
+       void DrawStringBuf(char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h);
+       
 protected:
        /** Pointer to the font data. */
         BMF_FontData* m_fontData;
index 55732a1dda75731e7f2fe740675040a575ad6b4d..1a9d45fc7b5f756c1340c5fc178810acf951fb3b 100644 (file)
@@ -73,7 +73,7 @@
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include"
+                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include"
                                PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_FREETYPE2;WITH_VERSE;WITH_OPENEXR"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="1"
                        <Tool
                                Name="VCCLCompilerTool"
                                InlineFunctionExpansion="1"
-                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include"
+                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include"
                                PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_FREETYPE2;UNWRAPPER;WITH_VERSE;WITH_OPENEXR"
                                StringPooling="TRUE"
                                RuntimeLibrary="0"
index 25aafbc1f87334a7c585927172bb5d8d3c391a98..7d9d8be5e9e2c0123feffd82c119f4f9b7d9b2a8 100644 (file)
@@ -285,6 +285,8 @@ def runUserCode(__USER_CODE_STRING__):
        # Try and run the user entered line(s)
        try:
                # Load all variabls from global dict to local space.
+               __TMP_VAR_NAME__ = __TMP_VAR__ = '' # so as not to raise an error when del'ing
+
                for __TMP_VAR_NAME__, __TMP_VAR__ in __CONSOLE_VAR_DICT__.items():
                        exec('%s%s' % (__TMP_VAR_NAME__,'=__TMP_VAR__'))
                del __TMP_VAR_NAME__
@@ -295,7 +297,8 @@ def runUserCode(__USER_CODE_STRING__):
                
                # Flush global dict, allow the user to remove items.
                __CONSOLE_VAR_DICT__ = {}
-               
+
+               __TMP_VAR_NAME__ = '' # so as not to raise an error when del'ing        
                # Write local veriables to global __CONSOLE_VAR_DICT__
                for __TMP_VAR_NAME__ in dir():
                        if      __TMP_VAR_NAME__ != '__FILE_LIKE_STRING__' and\
@@ -715,6 +718,15 @@ def draw_gui():
                else:  
                        BGL.glColor3f(1, 1, 0)
                
+               if consoleLineIdx == 1: # user input
+                       BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
+                       Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])             
+               else:
+                       BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
+                       Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
+
+               # Wrapping is totally slow, can even hang blender - dont do it!
+               '''
                if consoleLineIdx == 1: # NEVER WRAP THE USER INPUT
                        BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
                        # BUG, LARGE TEXT DOSENT DISPLAY
@@ -751,7 +763,7 @@ def draw_gui():
                                
                                BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
                                Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
-               
+               '''
                consoleLineIdx += 1
                        
 
@@ -806,7 +818,8 @@ def include_console(includeFile):
        
        # Execute an external py file as if local
        exec(include(includeFile))
-       
+
+def standard_imports():
        # Write local to global __CONSOLE_VAR_DICT__ for reuse,
        for ls in (dir(), dir(Blender)):
                for __TMP_VAR_NAME__ in ls:
@@ -814,10 +827,12 @@ def include_console(includeFile):
                        exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__))
        
        exec('%s%s' % ('__CONSOLE_VAR_DICT__["bpy"]=', 'bpy'))
-       
+
 if scriptDir and console_autoexec:
        include_console(console_autoexec) # pass the blender module
 
+standard_imports() # import Blender and bpy
+
 #-end autoexec-----------------------------------------------------------------#
 
 
@@ -831,4 +846,4 @@ def main():
        Draw.Register(draw_gui, handle_event, handle_button_event)
 
 if __name__ == '__main__':
-       main()
\ No newline at end of file
+       main()
index ded29af1924f41a043f33d691b4be16358f25df9..101a1ab1e84d10849a75561da320a7ca4d37b6aa 100644 (file)
@@ -629,14 +629,14 @@ def write_ui(filename):
                        
                        full_path= ''.join(context_name)
                        
-                       if BPyMessages.Warning_SaveOver(full_path):
-                               # EXPORT THE FILE.
-                               write(full_path, export_objects,\
-                               EXPORT_TRI, EXPORT_EDGES, EXPORT_NORMALS,\
-                               EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\
-                               EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\
-                               EXPORT_ROTX90, EXPORT_BLEN_OBS,\
-                               EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_MORPH_TARGET)
+                       # erm... bit of a problem here, this can overwrite files when exporting frames. not too bad.
+                       # EXPORT THE FILE.
+                       write(full_path, export_objects,\
+                       EXPORT_TRI, EXPORT_EDGES, EXPORT_NORMALS,\
+                       EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\
+                       EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\
+                       EXPORT_ROTX90, EXPORT_BLEN_OBS,\
+                       EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_MORPH_TARGET)
                
                Blender.Set('curframe', orig_frame)
        
index 8dcc04360d0d9117401d96ea9a590b6323dd248d..68aa9194435e5dbb80846a890f881ec071185465 100644 (file)
@@ -21,17 +21,21 @@ from Blender import Draw
 from Blender import Mathutils
 import math
 
-USE_TARGET = True
+'''
+ This variable specifies the number of targets 
+ that this constraint can use
+'''
+NUM_TARGETS = 1
 
 
 '''
  This function is called to evaluate the constraint
-       obmatrix:               (Matrix) copy of owner's worldspace matrix
-       targetmatrix:   (Matrix) copy of target's worldspace matrix (where applicable)
+       obmatrix:               (Matrix) copy of owner's 'ownerspace' matrix
+       targetmatrices: (List) list of copies of the 'targetspace' matrices of the targets (where applicable)
        idprop:                 (IDProperties) wrapped data referring to this 
                                        constraint instance's idproperties
 '''
-def doConstraint(obmatrix, targetmatrix, idprop):
+def doConstraint(obmatrix, targetmatrices, idprop):
        # Separate out the tranformation components for easy access.
        obloc = obmatrix.translationPart()      # Translation
        obrot = obmatrix.toEuler()                      # Rotation
@@ -60,9 +64,9 @@ def doConstraint(obmatrix, targetmatrix, idprop):
 
 
 '''
- This function manipulates the target matrix prior to sending it to doConstraint()
+ This function manipulates the matrix of a target prior to sending it to doConstraint()
        target_object:                                  wrapped data, representing the target object
-       subtarget_bone:                                 wrapped data, representing the subtarget pose-bone (where applicable)
+       subtarget_bone:                                 wrapped data, representing the subtarget pose-bone/vertex-group (where applicable)
        target_matrix:                                  (Matrix) the transformation matrix of the target
        id_properties_of_constraint:    (IDProperties) wrapped idproperties
 '''
@@ -72,8 +76,8 @@ def doTarget(target_object, subtarget_bone, target_matrix, id_properties_of_cons
 
 '''
  This function draws a pupblock that lets the user set
      the values of custom settings the constraint defines.
      This function is called when the user presses the settings button.
+ the values of custom settings the constraint defines.
+ This function is called when the user presses the settings button.
        idprop: (IDProperties) wrapped data referring to this 
                        constraint instance's idproperties
 '''
index a46688c8263cb6b433b965d11b3945f1e0b5ced4..08c8cb254f05a6d376a5037fefc2863c115f0970 100644 (file)
@@ -99,8 +99,8 @@ AviError AVI_set_compress_option (AviMovie *movie, int option_type, int stream,
                                break;
                                
                        case AVI_OPTION_FRAMERATE:
-                               if (1000000/(*((int *) opt_data)))
-                                       movie->header->MicroSecPerFrame = 1000000/(*((int *) opt_data));                                        
+                               if (1000000/(*((double *) opt_data)))
+                                       movie->header->MicroSecPerFrame = 1000000/(*((double *) opt_data));                                     
 
                                for (i=0; i < movie->header->Streams; i++) {
                                        if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
index 68a6be047351d36d8f6efd4a9cec2bac50157241..cbec4cf04fba9212c8884fffd814b94801322e5b 100644 (file)
@@ -119,8 +119,12 @@ void calc_action_range(const struct bAction *act, float *start, float *end, int
 /**
  * Set the pose channels from the given action.
  */
-void extract_pose_from_action(struct bPose *pose, struct bAction *act,
-                                                  float ctime);
+void extract_pose_from_action(struct bPose *pose, struct bAction *act, float ctime);
+
+/**
+ * Get the effects of the given action using a workob 
+ */
+void what_does_obaction(struct Object *ob, struct bAction *act, float cframe);
 
 /**
  * Iterate through the action channels of the action
index 0e3857603b66e1a934348070af533f1be7135662..fb527051a0d76771c64a39d3ade6bdda61a459da 100644 (file)
@@ -80,7 +80,7 @@ void make_local_armature(struct bArmature *arm);
 struct bArmature *copy_armature(struct bArmature *arm);
 void bone_flip_name (char *name, int strip_number);
 
-struct bArmature* get_armature (struct Object* ob);
+struct bArmature *get_armature (struct Object *ob);
 struct Bone *get_named_bone (struct bArmature *arm, const char *name);
 
 float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, float rad2, float rdist);
index 296fd5837b57c923b3b96313afe1e7c2016ddc18..32128c68af5fc569f4c91ba9bb7acca3ebf412c9 100644 (file)
@@ -65,6 +65,7 @@ struct IpoDriver; /* DNA_curve_types.h */
 struct Object;
 struct bPythonConstraint;
 struct bConstraintOb;
+struct bConstraintTarget;
 void BPY_do_pyscript (struct ID *id, short int event);
 void BPY_clear_script (struct Script *script);
 void BPY_free_compiled_text (struct Text *text);
@@ -74,9 +75,9 @@ float BPY_pydriver_eval(struct IpoDriver *driver);
 void BPY_pydriver_update(void);
 /* button python evaluation */
 int BPY_button_eval(char *expr, double *value);
-void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4]);
-void BPY_pyconstraint_driver(struct bPythonConstraint *con, struct bConstraintOb *cob, struct Object *target, char subtarget[]);
-int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4]);
+/* pyconstraints */
+void BPY_pyconstraint_eval(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
+void BPY_pyconstraint_targets(struct bPythonConstraint *con, struct bConstraintTarget *ct);
 
 
 /* writefile.c */
index 328d9775deb3ca4bf18f8271f8fc39c54b3bf354..55a542f51d54ab9eb30874acde34be9dea7eac40 100644 (file)
@@ -44,7 +44,7 @@ struct ListBase;
 struct MemFile;
 
 #define BLENDER_VERSION                        245
-#define BLENDER_SUBVERSION             4
+#define BLENDER_SUBVERSION             7
 
 #define BLENDER_MINVERSION             240
 #define BLENDER_MINSUBVERSION  0
index 39a3cf13087724102189d4c36ed9feddbaf7c783..40fd8c5ed1848c440d3bc401e8245de75ac090da 100644 (file)
 #ifndef BKE_CONSTRAINT_H
 #define BKE_CONSTRAINT_H
 
-
 struct bConstraint;
+struct bConstraintTarget;
 struct ListBase;
 struct Object;
 struct bConstraintChannel;
 struct bPoseChannel;
-struct bAction;
-struct bArmature;
-
-/* ---------------------------------------------------------------------------- */
-
-/* Constraint target/owner types */
-#define TARGET_OBJECT                  1       /*      string is ""                            */
-#define TARGET_BONE                            2       /*      string is bone-name             */
-#define TARGET_VERT                            3       /*      string is vertex-group name     */
-#define TARGET_CV                              4       /*      string is vertex-group name - is not available until curves get vgroups */
 
 /* ---------------------------------------------------------------------------- */
 
@@ -63,28 +53,79 @@ typedef struct bConstraintOb {
        short type;                                     /* type of owner  */
 } bConstraintOb;
 
+/* ---------------------------------------------------------------------------- */
+
+/* Constraint Type-Info (shorthand in code = cti):
+ *  This struct provides function pointers for runtime, so that functions can be
+ *  written more generally (with fewer/no special exceptions for various constraints).
+ *
+ *  Callers of these functions must check that they actually point to something useful,
+ *  as some constraints don't define some of these.
+ *
+ *  Warning: it is not too advisable to reorder order of members of this struct,
+ *                     as you'll have to edit quite a few ($NUM_CONSTRAINT_TYPES) of these
+ *                     structs.
+ */
+typedef struct bConstraintTypeInfo {
+       /* admin/ident */
+       short type;                             /* CONSTRAINT_TYPE_### */
+       short size;                             /* size in bytes of the struct */
+       char name[32];                  /* name constraint in interface */
+       char structName[32];    /* name of struct for SDNA */
+       
+       /* data management function pointers - special handling */
+               /* free any data that is allocated separately (optional) */
+       void (*free_data)(struct bConstraint *con);
+               /* adjust pointer to other ID-data using ID_NEW(), but not to targets (optional) */
+       void (*relink_data)(struct bConstraint *con);
+               /* copy any special data that is allocated separately (optional) */
+       void (*copy_data)(struct bConstraint *con, struct bConstraint *src);
+               /* set settings for data that will be used for bConstraint.data (memory already allocated) */
+       void (*new_data)(void *cdata);
+       
+       /* target handling function pointers */
+               /* for multi-target constraints: return that list; otherwise make a temporary list */
+       void (*get_constraint_targets)(struct bConstraint *con, struct ListBase *list);
+               /* for single-target constraints only: flush data back to source data, and the free memory used */
+       void (*flush_constraint_targets)(struct bConstraint *con, struct ListBase *list, short nocopy);
+       
+       /* evaluation */
+               /* set the ct->matrix for the given constraint target (at the given ctime) */
+       void (*get_target_matrix)(struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime);
+               /* evaluate the constraint for the given time */
+       void (*evaluate_constraint)(struct bConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
+} bConstraintTypeInfo;
+
+/* Function Prototypes for bConstraintTypeInfo's */
+bConstraintTypeInfo *constraint_get_typeinfo(struct bConstraint *con);
+bConstraintTypeInfo *get_constraint_typeinfo(int type);
+
+/* ---------------------------------------------------------------------------- */
+/* Useful macros for testing various common flag combinations */
+
+/* Constraint Target Macros */
+#define VALID_CONS_TARGET(ct) ((ct) && (ct->tar))
+
+
 /* ---------------------------------------------------------------------------- */
 
 /* Constraint function prototypes */
 void unique_constraint_name(struct bConstraint *con, struct ListBase *list);
-void *new_constraint_data(short type);
+
 void free_constraints(struct ListBase *conlist);
 void copy_constraints(struct ListBase *dst, struct ListBase *src);
 void relink_constraints(struct ListBase *list);
 void free_constraint_data(struct bConstraint *con);
 
+
 /* Constraint Channel function prototypes */
-struct bConstraintChannel *get_constraint_channel(ListBase *list, const char *name);
-struct bConstraintChannel *verify_constraint_channel(ListBase *list, const char *name);
-void do_constraint_channels(struct ListBase *conbase, struct ListBase *chanbase, float ctime, int onlydrivers);
-void copy_constraint_channels(ListBase *dst, ListBase *src);
+struct bConstraintChannel *get_constraint_channel(struct ListBase *list, const char *name);
+struct bConstraintChannel *verify_constraint_channel(struct ListBase *list, const char *name);
+void do_constraint_channels(struct ListBase *conbase, struct ListBase *chanbase, float ctime, short onlydrivers);
+void copy_constraint_channels(struct ListBase *dst, struct ListBase *src);
 void clone_constraint_channels(struct ListBase *dst, struct ListBase *src);
-void free_constraint_channels(ListBase *chanbase);
+void free_constraint_channels(struct ListBase *chanbase);
 
-/* Target function prototypes  */
-char constraint_has_target(struct bConstraint *con);
-struct Object *get_constraint_target(struct bConstraint *con, char **subtarget);
-void set_constraint_target(struct bConstraint *con, struct Object *ob, char *subtarget);
 
 /* Constraint Evaluation function prototypes */
 struct bConstraintOb *constraints_make_evalob(struct Object *ob, void *subdata, short datatype);
@@ -92,8 +133,8 @@ void constraints_clear_evalob(struct bConstraintOb *cob);
 
 void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[][4], short from, short to);
 
-short get_constraint_target_matrix(struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float time);
-void solve_constraints (struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
+void get_constraint_target_matrix(struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime);
+void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
 
 
 #endif
index 58f96491a1bec90ac103bc5dd921dc76f2c39192..204e956dbc8bedab5965b50089996ad5b6f27cc0 100644 (file)
@@ -46,6 +46,7 @@ struct anim;
 /* call from library */
 void   free_image(struct Image *me);
 
+void   BKE_stamp(struct ImBuf *ibuf);
 int            BKE_write_ibuf(struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality);
 void   BKE_makepicstring(char *string, char *base, int frame, int imtype);
 void   BKE_add_image_extension(char *string, int imtype);
index b834116f11d6ad2aed1e0c0df8a155c9f61e670f..6e363515f4195b140f985e6d17752f2f7c5dedca 100644 (file)
@@ -45,6 +45,7 @@ struct BoundBox;
 struct View3D;
 struct SoftBody;
 struct Group;
+struct bAction;
 
 void clear_workob(void);
 void copy_baseflags(void);
@@ -98,6 +99,7 @@ void where_is_object(struct Object *ob);
 void where_is_object_simul(struct Object *ob);
 
 void what_does_parent(struct Object *ob);
+
 struct BoundBox *unit_boundbox(void);
 void boundbox_set_from_min_max(struct BoundBox *bb, float min[3], float max[3]);
 struct BoundBox *object_get_boundbox(struct Object *ob);
index b8c23a6517d4501b5df515d4575fa2cd4698327d..c0776583a0407a7550bad5180d6f130a6afc93a0 100644 (file)
@@ -34,6 +34,7 @@ SET(INC
   ../python ../render/extern/include ../../../intern/decimation/extern
   ../imbuf ../avi ../../../intern/elbeem/extern
   ../../../intern/iksolver/extern ../blenloader ../quicktime
+  ../../../intern/bmfont
   ../nodes
   ${SDL_INC}
   ${ZLIB_INC}
index 3403490b7789014b7a495f88eee26ba73a9cf884..c83e9f7fbe13574d8c0bbad59740b84b397bc7ec 100644 (file)
@@ -8,6 +8,7 @@ incs += ' ../python ../render/extern/include #/intern/decimation/extern'
 incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes'
 incs += ' #/intern/iksolver/extern ../blenloader ../quicktime'
 incs += ' #/extern/bullet2/src '
+incs += ' #/intern/bmfont'
 
 incs += ' ' + env['BF_OPENGL_INC']
 incs += ' ' + env['BF_ZLIB_INC']
index 2524a804e530794d811cff3310bb4e7552d600c3..12b99780b6064dc52620c032390d9da85616a91d 100644 (file)
@@ -57,6 +57,8 @@ struct RenderResult;
 struct Object;
 struct bPythonConstraint;
 struct bConstraintOb;
+struct bConstraintTarget;
+struct ListBase;
 
 char *getIpoCurveName( struct IpoCurve * icu );
 void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast);
@@ -128,16 +130,12 @@ int BPY_button_eval(char *expr, double *value)
 }
 
 /* PyConstraints - BPY_interface.c */
-void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4])
+void BPY_pyconstraint_eval(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets)
 {
 }
-void BPY_pyconstraint_driver(struct bPythonConstraint *con, struct bConstraintOb *cob, struct Object *target, char subtarget[])
+void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct)
 {
 }
-int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4])
-{
-       return 0;
-}
 
 
 /* writefile.c */
@@ -328,3 +326,6 @@ void update_for_newframe() {}
 struct FileList;
 void BIF_filelist_freelib(struct FileList* filelist) {};
 
+/* edittime.c stub */
+TimeMarker *get_frame_marker(int frame){return 0;};
+
index e87eb2a3e3f597fe3dfa2c61640561b91f119eba..b3bc6c72996fb990805df891369f1c18964ed68c 100644 (file)
@@ -60,6 +60,8 @@ CPPFLAGS += -I../../include
 # to include the render stuff:
 CPPFLAGS += -I../../render/extern/include
 
+# for image stamping
+CPPFLAGS += -I$(NAN_BMFONT)/include
 # for sound
 #CPPFLAGS += -I../../../kernel/gen_system
 CPPFLAGS +=  $(NAN_SDLCFLAGS)
index 22e621a27e2b83b05ed55834b8ca9755409dfcba..d202178fc0a4002d883f17cd093c7fc58e64ff8b 100644 (file)
@@ -819,7 +819,7 @@ static void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act,
                        
                        if(conchan && conchan->ipo) {
                                calc_ipo(conchan->ipo, ctime);
-
+                               
                                icu= conchan->ipo->curve.first; // only one ipo now
                                if(icu) {
                                        nic= MEM_callocN(sizeof(NlaIpoChannel), "NlaIpoChannel constr");
@@ -1061,6 +1061,46 @@ static Object *get_parent_path(Object *ob)
 
 /* ************** do the action ************ */
 
+/* For the calculation of the effects of an action at the given frame on an object 
+ * This is currently only used for the action constraint 
+ */
+void what_does_obaction (Object *ob, bAction *act, float cframe)
+{
+       ListBase tchanbase= {NULL, NULL};
+       
+       clear_workob();
+       Mat4CpyMat4(workob.obmat, ob->obmat);
+       Mat4CpyMat4(workob.parentinv, ob->parentinv);
+       Mat4CpyMat4(workob.constinv, ob->constinv);
+       workob.parent= ob->parent;
+       workob.track= ob->track;
+
+       workob.trackflag= ob->trackflag;
+       workob.upflag= ob->upflag;
+       
+       workob.partype= ob->partype;
+       workob.par1= ob->par1;
+       workob.par2= ob->par2;
+       workob.par3= ob->par3;
+
+       workob.constraints.first = ob->constraints.first;
+       workob.constraints.last = ob->constraints.last;
+
+       strcpy(workob.parsubstr, ob->parsubstr); 
+       
+       /* extract_ipochannels_from_action needs id's! */
+       workob.action= act;
+       
+       extract_ipochannels_from_action(&tchanbase, &ob->id, act, "Object", bsystem_time(&workob, cframe, 0.0));
+       
+       if (tchanbase.first) {
+               execute_ipochannels(&tchanbase);
+               BLI_freelistN(&tchanbase);
+       }
+}
+
+/* ----- nla, etc. --------- */
+
 static void do_nla(Object *ob, int blocktype)
 {
        bPose *tpose= NULL;
@@ -1331,5 +1371,3 @@ void do_all_object_actions(Object *ob)
                do_nla(ob, ID_OB);
        }
 }
-
-
index 10b2a3648271148f6350a2861c5a5df71233233f..2030859000f3cc444762c7dc642abe71edb070e0 100644 (file)
@@ -1239,7 +1239,6 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
        bPose *pose= ob->pose, *frompose= from->pose;
        bPoseChannel *pchan, *pchanp, pchanw;
        bConstraint *con;
-       char *str;
        
        if(frompose==NULL) return;
        
@@ -1267,8 +1266,23 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
                        copy_constraints(&pchanw.constraints, &pchanp->constraints);
 
                        for(con= pchanw.constraints.first; con; con= con->next) {
-                               if(from==get_constraint_target(con, &str))
-                                       set_constraint_target(con, ob, NULL);
+                               bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+                               ListBase targets = {NULL, NULL};
+                               bConstraintTarget *ct;
+                               
+                               if (cti && cti->get_constraint_targets) {
+                                       cti->get_constraint_targets(con, &targets);
+                                       
+                                       for (ct= targets.first; ct; ct= ct->next) {
+                                               if (ct->tar == from) {
+                                                       ct->tar = ob;
+                                                       strcpy(ct->subtarget, "");
+                                               }
+                                       }
+                                       
+                                       if (cti->flush_constraint_targets)
+                                               cti->flush_constraint_targets(con, &targets, 0);
+                               }
                        }
                        
                        /* free stuff from current channel */
@@ -1609,45 +1623,47 @@ static void execute_posetree(Object *ob, PoseTree *tree)
        Mat4MulMat4 (imat, rootmat, ob->obmat);
        Mat4Invert (goalinv, imat);
        
-       for(target=tree->targets.first; target; target=target->next) {
+       for (target=tree->targets.first; target; target=target->next) {
                data= (bKinematicConstraint*)target->con->data;
-
-               /* 1.0=ctime, we pass on object for auto-ik */
-               get_constraint_target_matrix(target->con, TARGET_BONE, ob, rootmat, 1.0);
-
+               
+               /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
+                * strictly speaking, it is a posechannel)
+                */
+               get_constraint_target_matrix(target->con, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+               
                /* and set and transform goal */
                Mat4MulMat4(goal, rootmat, goalinv);
-
+               
                VECCOPY(goalpos, goal[3]);
                Mat3CpyMat4(goalrot, goal);
-
+               
                /* do we need blending? */
-               if(target->con->enforce!=1.0) {
+               if (target->con->enforce!=1.0) {
                        float q1[4], q2[4], q[4];
                        float fac= target->con->enforce;
                        float mfac= 1.0-fac;
                        
                        pchan= tree->pchan[target->tip];
-
+                       
                        /* end effector in world space */
                        Mat4CpyMat4(end_pose, pchan->pose_mat);
                        VECCOPY(end_pose[3], pchan->pose_tail);
                        Mat4MulSerie(world_pose, goalinv, ob->obmat, end_pose, 0, 0, 0, 0, 0);
-
+                       
                        /* blend position */
                        goalpos[0]= fac*goalpos[0] + mfac*world_pose[3][0];
                        goalpos[1]= fac*goalpos[1] + mfac*world_pose[3][1];
                        goalpos[2]= fac*goalpos[2] + mfac*world_pose[3][2];
-
+                       
                        /* blend rotation */
                        Mat3ToQuat(goalrot, q1);
                        Mat4ToQuat(world_pose, q2);
                        QuatInterpol(q, q1, q2, mfac);
                        QuatToMat3(q, goalrot);
                }
-
+               
                iktarget= iktree[target->tip];
-
+               
                if(data->weight != 0.0)
                        IK_SolverAddGoal(solver, iktarget, goalpos, data->weight);
                if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0) && (data->flag & CONSTRAINT_IK_AUTO)==0)
@@ -1932,7 +1948,7 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
                /* prepare PoseChannel for Constraint solving 
                 * - makes a copy of matrix, and creates temporary struct to use 
                 */
-               cob= constraints_make_evalob(ob, pchan, TARGET_BONE);
+               cob= constraints_make_evalob(ob, pchan, CONSTRAINT_OBTYPE_BONE);
                
                /* Solve PoseChannel's Constraints */
                solve_constraints(&pchan->constraints, cob, ctime);     // ctime doesnt alter objects
index 020350d9e6f1864f6067147c306d9d41ab1c82c4..c9fb21d4333ab5e7445e6307c87e4a4f45665076 100644 (file)
@@ -48,6 +48,7 @@
 #include "DNA_meshdata_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_text_types.h"
 
 #include "BKE_utildefines.h"
 #include "BKE_action.h"
 #endif
 
 
-/* ********************* Data level ****************** */
-
-void free_constraint_data (bConstraint *con)
-{
-       if (con->data) {
-               /* any constraint-type specific stuff here */
-               switch (con->type) {
-                       case CONSTRAINT_TYPE_PYTHON:
-                       {
-                               bPythonConstraint *data= con->data;
-                               IDP_FreeProperty(data->prop);
-                               MEM_freeN(data->prop);
-                       }
-                               break;
-               }
-               
-               MEM_freeN(con->data);
-       }
-}
-
-void free_constraints (ListBase *conlist)
-{
-       bConstraint *con;
-       
-       /* Do any specific freeing */
-       for (con=conlist->first; con; con=con->next) {
-               free_constraint_data(con);
-       }
-       
-       /* Free the whole list */
-       BLI_freelistN(conlist);
-}
+/* ******************* Constraint Channels ********************** */
+/* Constraint Channels exist in one of two places:
+ *     - Under Action Channels in an Action  (act->chanbase->achan->constraintChannels)
+ *     - Under Object without object-level action yet (ob->constraintChannels)
+ * 
+ * The main purpose that constraint channels serve is to act as a link
+ * between an IPO-block which 
+ */
 
+/* ------------ Data Management ----------- */
+/* Free constraint channels, and reduce the number of users of the related ipo-blocks */
 void free_constraint_channels (ListBase *chanbase)
 {
        bConstraintChannel *chan;
@@ -125,27 +105,14 @@ void free_constraint_channels (ListBase *chanbase)
        BLI_freelistN(chanbase);
 }
 
-void relink_constraints (struct ListBase *list)
-{
-       bConstraint *con;
-       
-       for (con = list->first; con; con=con->next) {
-               /* check if constraint has a target that needs relinking */
-               if (constraint_has_target(con)) {
-                       Object *tar;
-                       char *subtarget;
-                       
-                       tar = get_constraint_target(con, &subtarget);
-                       ID_NEW(tar);
-               }
-       }
-}
-
+/* Make a copy of the constraint channels from dst to src, and also give the
+ * new constraint channels their own copy of the original's IPO.
+ */
 void copy_constraint_channels (ListBase *dst, ListBase *src)
 {
        bConstraintChannel *dchan, *schan;
        
-       dst->first=dst->last=NULL;
+       dst->first = dst->last = NULL;
        duplicatelist(dst, src);
        
        for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
@@ -153,11 +120,14 @@ void copy_constraint_channels (ListBase *dst, ListBase *src)
        }
 }
 
+/* Make a copy of the constraint channels from dst to src, but make the
+ * new constraint channels use the same IPO-data as their twin.
+ */
 void clone_constraint_channels (ListBase *dst, ListBase *src)
 {
        bConstraintChannel *dchan, *schan;
        
-       dst->first=dst->last=NULL;
+       dst->first = dst->last = NULL;
        duplicatelist(dst, src);
        
        for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
@@ -165,354 +135,81 @@ void clone_constraint_channels (ListBase *dst, ListBase *src)
        }
 }
 
-void copy_constraints (ListBase *dst, ListBase *src)
-{
-       bConstraint *con, *srccon;
-       
-       dst->first= dst->last= NULL;
-       duplicatelist (dst, src);
-       
-       for (con = dst->first, srccon=src->first; con; srccon=srccon->next, con=con->next) {
-               con->data = MEM_dupallocN (con->data);
-               
-               /* only do specific constraints if required */
-               if (con->type == CONSTRAINT_TYPE_PYTHON) {
-                       bPythonConstraint *pycon = (bPythonConstraint *)con->data;
-                       bPythonConstraint *opycon = (bPythonConstraint *)srccon->data;
-                       
-                       pycon->prop = IDP_CopyProperty(opycon->prop);
-               }
-       }
-}
-
-/* **************** Editor Functions **************** */
+/* ------------- Constraint Channel Tools ------------ */
 
-char constraint_has_target (bConstraint *con) 
+/* Find the constraint channel with a given name */
+bConstraintChannel *get_constraint_channel (ListBase *list, const char name[])
 {
-       switch (con->type) {
-       case CONSTRAINT_TYPE_PYTHON:
-               {
-                       bPythonConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_KINEMATIC:
-               {
-                       bKinematicConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_FOLLOWPATH:
-               {
-                       bFollowPathConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_SIZELIKE:
-               {
-                       bSizeLikeConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_MINMAX:
-               {
-                       bMinMaxConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_ACTION:
-               {
-                       bActionConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCKTRACK:
-               {
-                       bLockTrackConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-       case CONSTRAINT_TYPE_STRETCHTO:
-               {
-                       bStretchToConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_RIGIDBODYJOINT:
-               {
-                       bRigidBodyJointConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_CLAMPTO:
-               {
-                       bClampToConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-                       break;
-       case CONSTRAINT_TYPE_CHILDOF:
-               {
-                       bChildOfConstraint *data = con->data;
-                       if (data->tar) return 1;
-               }
-               break;
-       case CONSTRAINT_TYPE_TRANSFORM:
-               {
-                       bTransformConstraint *data = con->data;
-                       if (data->tar) return 1;
+       bConstraintChannel *chan;
+
+       for (chan = list->first; chan; chan=chan->next) {
+               if (!strcmp(name, chan->name)) {
+                       return chan;
                }
-               break;
        }
        
-       /* Unknown types or CONSTRAINT_TYPE_NULL or no target */
-       return 0;
+       return NULL;
 }
 
-Object *get_constraint_target(bConstraint *con, char **subtarget)
+/* Find or create a new constraint channel */
+bConstraintChannel *verify_constraint_channel (ListBase *list, const char name[])
 {
-       /* If the target for this constraint is target, return a pointer 
-        * to the name for this constraints subtarget ... NULL otherwise
-        */
-       switch (con->type) {
-       case CONSTRAINT_TYPE_PYTHON:
-               {
-                       bPythonConstraint *data=con->data;
-                       *subtarget = data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_ACTION:
-               {
-                       bActionConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_SIZELIKE:
-               {
-                       bSizeLikeConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_KINEMATIC:
-               {
-                       bKinematicConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_MINMAX:
-               {
-                       bMinMaxConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCKTRACK:
-               {
-                       bLockTrackConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_FOLLOWPATH: 
-               {
-                       bFollowPathConstraint *data = con->data;
-                       *subtarget= NULL;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_STRETCHTO:
-               {
-                       bStretchToConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_RIGIDBODYJOINT: 
-               {
-                       bRigidBodyJointConstraint *data = con->data;
-                       *subtarget= NULL;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_CLAMPTO:
-               {
-                       bClampToConstraint *data = con->data;
-                       *subtarget= NULL;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_CHILDOF:   
-               {
-                       bChildOfConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       case CONSTRAINT_TYPE_TRANSFORM: 
-               {
-                       bTransformConstraint *data = con->data;
-                       *subtarget= data->subtarget;
-                       return data->tar;
-               }
-               break;
-       default:
-               *subtarget= NULL;
-               break;
+       bConstraintChannel *chan;
+       
+       chan= get_constraint_channel(list, name);
+       
+       if (chan == NULL) {
+               chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint channel");
+               BLI_addtail(list, chan);
+               strcpy(chan->name, name);
        }
        
-       return NULL;  
+       return chan;
 }
 
-void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
+/* --------- Constraint Channel Evaluation/Execution --------- */
+
+/* IPO-system call: calculate IPO-block for constraint channels, and flush that
+ * info onto the corresponding constraint.
+ */
+void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime, short onlydrivers)
 {
-       /* Set the target for this constraint */
-       switch (con->type) {
-               case CONSTRAINT_TYPE_PYTHON:
-               {
-                       bPythonConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;          
-               case CONSTRAINT_TYPE_ACTION:
-               {
-                       bActionConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_SIZELIKE:
-               {
-                       bSizeLikeConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_KINEMATIC:
-               {
-                       bKinematicConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_LOCKTRACK:
-               {
-                       bLockTrackConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_FOLLOWPATH: 
-               {
-                       bFollowPathConstraint *data = con->data;
-                       data->tar= ob;
-               }
-                       break;
-               case CONSTRAINT_TYPE_STRETCHTO:
-               {
-                       bStretchToConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_RIGIDBODYJOINT: 
-               {
-                       bRigidBodyJointConstraint *data = con->data;
-                       data->tar= ob;
-               }
-                       break;
-               case CONSTRAINT_TYPE_MINMAX:
-               {
-                       bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_CLAMPTO: 
-               {
-                       bClampToConstraint *data = con->data;
-                       data->tar= ob;
-               }
-                       break;
-               case CONSTRAINT_TYPE_CHILDOF:
-               {
-                       bChildOfConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
-               }
-                       break;
-               case CONSTRAINT_TYPE_TRANSFORM:
-               {
-                       bTransformConstraint *data = con->data;
-                       data->tar= ob;
-                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+       bConstraint *con;
+       bConstraintChannel *chan;
+       IpoCurve *icu= NULL;
+       
+       /* for each Constraint, calculate its Influence from the corresponding ConstraintChannel */
+       for (con=conbase->first; con; con=con->next) {
+               chan = get_constraint_channel(chanbase, con->name);
+               
+               if (chan && chan->ipo) {
+                       calc_ipo(chan->ipo, ctime);
+                       
+                       for (icu=chan->ipo->curve.first; icu; icu=icu->next) {
+                               if (!onlydrivers || icu->driver) {
+                                       switch (icu->adrcode) {
+                                               case CO_ENFORCE:
+                                               {
+                                                       /* Influence is clamped to 0.0f -> 1.0f range */
+                                                       con->enforce = CLAMPIS(icu->curval, 0.0f, 1.0f);
+                                               }
+                                                       break;
+                                       }
+                               }
+                       }
                }
-                       break;
        }
 }
 
+/* ************************ Constraints - General Utilities *************************** */
+/* These functions here don't act on any specific constraints, and are therefore should/will
+ * not require any of the special function-pointers afforded by the relevant constraint 
+ * type-info structs.
+ */
+
+/* -------------- Naming -------------- */
+
+/* Find the first available, non-duplicate name for a given constraint */
 void unique_constraint_name (bConstraint *con, ListBase *list)
 {
        bConstraint *curcon;
@@ -536,11 +233,11 @@ void unique_constraint_name (bConstraint *con, ListBase *list)
                }
        }
        
-       if (!exists)
+       if (exists == 0)
                return;
 
        /*      Strip off the suffix */
-       dot=strchr(con->name, '.');
+       dot = strchr(con->name, '.');
        if (dot)
                *dot=0;
        
@@ -549,332 +246,111 @@ void unique_constraint_name (bConstraint *con, ListBase *list)
                
                exists = 0;
                for (curcon=list->first; curcon; curcon=curcon->next) {
-                       if (con!=curcon) {
-                               if (!strcmp(curcon->name, tempname)) {
+                       if (con != curcon) {
+                               if (strcmp(curcon->name, tempname)==0) {
                                        exists = 1;
                                        break;
                                }
                        }
                }
-               if (!exists) {
+               if (exists == 0) {
                        strcpy(con->name, tempname);
                        return;
                }
        }
 }
 
-void *new_constraint_data (short type)
+/* ----------------- Evaluation Loop Preparation --------------- */
+
+/* package an object/bone for use in constraint evaluation */
+/* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */
+bConstraintOb *constraints_make_evalob (Object *ob, void *subdata, short datatype)
 {
-       void *result;
+       bConstraintOb *cob;
+       
+       /* create regardless of whether we have any data! */
+       cob= MEM_callocN(sizeof(bConstraintOb), "bConstraintOb");
        
-       switch (type) {
-       case CONSTRAINT_TYPE_PYTHON:
+       /* based on type of available data */
+       switch (datatype) {
+               case CONSTRAINT_OBTYPE_OBJECT:
                {
-                       bPythonConstraint *data;
-                       data = MEM_callocN(sizeof(bPythonConstraint), "pythonConstraint");
-                       
-                       /* everything should be set correctly by calloc, except for the prop->type constant.*/
-                       data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps");
-                       data->prop->type = IDP_GROUP;
+                       /* disregard subdata... calloc should set other values right */
+                       if (ob) {
+                               cob->ob = ob;
+                               cob->type = datatype;
+                               Mat4CpyMat4(cob->matrix, ob->obmat);
+                       }
+                       else
+                               Mat4One(cob->matrix);
                        
-                       result = data;
+                       Mat4CpyMat4(cob->startmat, cob->matrix);
                }
-               break;          
-       case CONSTRAINT_TYPE_KINEMATIC:
+                       break;
+               case CONSTRAINT_OBTYPE_BONE:
                {
-                       bKinematicConstraint *data;
-                       data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
-
-                       data->weight= (float)1.0;
-                       data->orientweight= (float)1.0;
-                       data->iterations = 500;
-                       data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS;
-                       
-                       result = data;
+                       /* only set if we have valid bone, otherwise default */
+                       if (ob && subdata) {
+                               cob->ob = ob;
+                               cob->pchan = (bPoseChannel *)subdata;
+                               cob->type = datatype;
+                               
+                               /* matrix in world-space */
+                               Mat4MulMat4(cob->matrix, cob->pchan->pose_mat, ob->obmat);
+                       }
+                       else
+                               Mat4One(cob->matrix);
+                               
+                       Mat4CpyMat4(cob->startmat, cob->matrix);
                }
-               break;
-       case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data;
-                       data = MEM_callocN(sizeof(bTrackToConstraint), "tracktoConstraint");
-                       
-                       data->reserved1 = TRACK_Y;
-                       data->reserved2 = UP_Z;
+                       break;
                        
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_MINMAX:
+               default: /* other types not yet handled */
+                       Mat4One(cob->matrix);
+                       Mat4One(cob->startmat);
+                       break;
+       }
+       
+       return cob;
+}
+
+/* cleanup after constraint evaluation */
+void constraints_clear_evalob (bConstraintOb *cob)
+{
+       float delta[4][4], imat[4][4];
+       
+       /* prevent crashes */
+       if (cob == NULL) 
+               return;
+       
+       /* calculate delta of constraints evaluation */
+       Mat4Invert(imat, cob->startmat);
+       Mat4MulMat4(delta, cob->matrix, imat);
+       
+       /* copy matrices back to source */
+       switch (cob->type) {
+               case CONSTRAINT_OBTYPE_OBJECT:
                {
-                       bMinMaxConstraint *data;
-                       data = MEM_callocN(sizeof(bMinMaxConstraint), "minmaxConstraint");
-                       
-                       data->minmaxflag = TRACK_Z;
-                       data->offset = 0.0f;
-                       data->cache[0] = data->cache[1] = data->cache[2] = 0.0f;
-                       data->flag = 0;
-                       
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data;
-                       data = MEM_callocN(sizeof(bLocateLikeConstraint), "LocLikeConstraint");
-                       data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data;
-                       data = MEM_callocN(sizeof(bRotateLikeConstraint), "RotLikeConstraint");
-                       data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_SIZELIKE:
-               {
-                       bSizeLikeConstraint *data;
-                       data = MEM_callocN(sizeof(bLocateLikeConstraint), "SizeLikeConstraint");
-                       data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_ACTION:
-               {
-                       bActionConstraint *data;
-                       data = MEM_callocN(sizeof(bActionConstraint), "ActionConstraint");
-                       
-                       /* set type to 20 (Loc X), as 0 is Rot X for backwards compatability */
-                       data->type = 20;
-                       
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCKTRACK:
-               {
-                       bLockTrackConstraint *data;
-                       data = MEM_callocN(sizeof(bLockTrackConstraint), "locktrackConstraint");
-                       
-                       data->trackflag = TRACK_Y;
-                       data->lockflag = LOCK_Z;
-                       
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_FOLLOWPATH:
-               {
-                       bFollowPathConstraint *data;
-                       data = MEM_callocN(sizeof(bFollowPathConstraint), "followpathConstraint");
-
-                       data->trackflag = TRACK_Y;
-                       data->upflag = UP_Z;
-                       data->offset = 0;
-                       data->followflag = 0;
-
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_STRETCHTO:
-               {
-                       bStretchToConstraint *data;
-                       data = MEM_callocN(sizeof(bStretchToConstraint), "StretchToConstraint");
-
-                       data->volmode = 0;
-                       data->plane = 0;
-                       data->orglength = 0.0; 
-                       data->bulge = 1.0;
-                       result = data;
-               }
-               break; 
-       case CONSTRAINT_TYPE_LOCLIMIT:
-               {
-                       bLocLimitConstraint *data;
-                       data = MEM_callocN(sizeof(bLocLimitConstraint), "LocLimitConstraint");
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_ROTLIMIT:
-               {
-                       bRotLimitConstraint *data;
-                       data = MEM_callocN(sizeof(bRotLimitConstraint), "RotLimitConstraint");
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_SIZELIMIT:
-               {
-                       bSizeLimitConstraint *data;
-                       data = MEM_callocN(sizeof(bSizeLimitConstraint), "SizeLimitConstraint");
-                       result = data;
-               }
-               break;
-    case CONSTRAINT_TYPE_RIGIDBODYJOINT:
-               {
-                       bRigidBodyJointConstraint *data;
-                       data = MEM_callocN(sizeof(bRigidBodyJointConstraint), "RigidBodyToConstraint");
-                       
-                       // removed code which set target of this constraint  
-            data->type=1;
-                       
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_CLAMPTO:
-               {
-                       bClampToConstraint *data;
-                       data = MEM_callocN(sizeof(bClampToConstraint), "ClampToConstraint");
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_CHILDOF:
-               {
-                       bChildOfConstraint *data;
-                       data = MEM_callocN(sizeof(bChildOfConstraint), "ChildOfConstraint");
-                       
-                       data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ |
-                                                       CHILDOF_ROTX |CHILDOF_ROTY | CHILDOF_ROTZ |
-                                                       CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ);
-                       Mat4One(data->invmat);
-                       
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_TRANSFORM:
-               {
-                       bTransformConstraint *data;
-                       data = MEM_callocN(sizeof(bTransformConstraint), "TransformationConstraint");
-                       
-                       data->map[0]= 0;
-                       data->map[1]= 1;
-                       data->map[2]= 2;
-                       
-                       result = data;
-               }
-               break;
-  
-       default:
-               result = NULL;
-               break;
-       }
-
-       return result;
-}
-
-bConstraintChannel *get_constraint_channel (ListBase *list, const char *name)
-{
-       bConstraintChannel *chan;
-
-       for (chan = list->first; chan; chan=chan->next) {
-               if (!strcmp(name, chan->name)) {
-                       return chan;
-               }
-       }
-       return NULL;
-}
-
-/* finds or creates new constraint channel */
-bConstraintChannel *verify_constraint_channel (ListBase *list, const char *name)
-{
-       bConstraintChannel *chan;
-       
-       chan= get_constraint_channel(list, name);
-       
-       if(chan == NULL) {
-               chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint chan");
-               BLI_addtail(list, chan);
-               strcpy(chan->name, name);
-       }
-       
-       return chan;
-}
-
-
-/* ***************** Evaluating ********************* */
-
-/* package an object/bone for use in constraint evaluation */
-/* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */
-bConstraintOb *constraints_make_evalob (Object *ob, void *subdata, short datatype)
-{
-       bConstraintOb *cob;
-       
-       /* create regardless of whether we have any data! */
-       cob= MEM_callocN(sizeof(bConstraintOb), "bConstraintOb");
-       
-       /* based on type of available data */
-       switch (datatype) {
-               case TARGET_OBJECT:
-               {
-                       /* disregard subdata... calloc should set other values right */
-                       if (ob) {
-                               cob->ob = ob;
-                               cob->type = datatype;
-                               Mat4CpyMat4(cob->matrix, ob->obmat);
+                       /* cob->ob might not exist! */
+                       if (cob->ob) {
+                               /* copy new ob-matrix back to owner */
+                               Mat4CpyMat4(cob->ob->obmat, cob->matrix);
+                               
+                               /* copy inverse of delta back to owner */
+                               Mat4Invert(cob->ob->constinv, delta);
                        }
-                       else
-                               Mat4One(cob->matrix);
-                       
-                       Mat4CpyMat4(cob->startmat, cob->matrix);
                }
                        break;
-               case TARGET_BONE:
+               case CONSTRAINT_OBTYPE_BONE:
                {
-                       /* only set if we have valid bone, otherwise default */
-                       if (ob && subdata) {
-                               cob->ob = ob;
-                               cob->pchan = (bPoseChannel *)subdata;
-                               cob->type = datatype;
+                       /* cob->ob or cob->pchan might not exist */
+                       if (cob->ob && cob->pchan) {
+                               /* copy new pose-matrix back to owner */
+                               Mat4MulMat4(cob->pchan->pose_mat, cob->matrix, cob->ob->imat);
                                
-                               /* matrix in world-space */
-                               Mat4MulMat4(cob->matrix, cob->pchan->pose_mat, ob->obmat);
+                               /* copy inverse of delta back to owner */
+                               Mat4Invert(cob->pchan->constinv, delta);
                        }
-                       else
-                               Mat4One(cob->matrix);
-                               
-                       Mat4CpyMat4(cob->startmat, cob->matrix);
-               }
-                       break;
-                       
-               default: // other types not yet handled
-                       Mat4One(cob->matrix);
-                       Mat4One(cob->startmat);
-                       break;
-       }
-       
-       return cob;
-}
-
-/* cleanup after constraint evaluation */
-void constraints_clear_evalob (bConstraintOb *cob)
-{
-       float delta[4][4], imat[4][4];
-       
-       /* prevent crashes */
-       if (cob == NULL) 
-               return;
-       
-       /* calculate delta of constraints evaluation */
-       Mat4Invert(imat, cob->startmat);
-       Mat4MulMat4(delta, cob->matrix, imat);
-       
-       /* copy matrices back to source */
-       switch (cob->type) {
-               case TARGET_OBJECT:
-               {
-                       /* copy new ob-matrix back to owner */
-                       Mat4CpyMat4(cob->ob->obmat, cob->matrix);
-                       
-                       /* copy inverse of delta back to owner */
-                       Mat4Invert(cob->ob->constinv, delta);
-               }
-                       break;
-               case TARGET_BONE:
-               {
-                       /* copy new pose-matrix back to owner */
-                       Mat4MulMat4(cob->pchan->pose_mat, cob->matrix, cob->ob->imat);
-                       
-                       /* copy inverse of delta back to owner */
-                       Mat4Invert(cob->pchan->constinv, delta);
                }
                        break;
        }
@@ -883,40 +359,7 @@ void constraints_clear_evalob (bConstraintOb *cob)
        MEM_freeN(cob);
 }
 
-/* -------------------------------- Constraint Channels ---------------------------- */
-
-/* does IPO's of constraint channels only */
-void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime, int onlydrivers)
-{
-       bConstraint *con;
-       bConstraintChannel *chan;
-       IpoCurve *icu= NULL;
-       
-       /* for each Constraint, calculate its Influence from the corresponding ConstraintChannel */
-       for (con=conbase->first; con; con=con->next) {
-               
-               chan = get_constraint_channel(chanbase, con->name);
-               
-               if (chan && chan->ipo) {
-                       calc_ipo(chan->ipo, ctime);
-                       
-                       for (icu=chan->ipo->curve.first; icu; icu=icu->next) {
-                               if(!onlydrivers || icu->driver) {
-                                       switch (icu->adrcode) {
-                                               case CO_ENFORCE:
-                                               {
-                                                       /* Influence is clamped to 0.0f -> 1.0f range */
-                                                       con->enforce = CLAMPIS(icu->curval, 0.0f, 1.0f);
-                                               }
-                                                       break;
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-/* ------------------------------- Space-Conversion API ---------------------------- */
+/* -------------- Space-Conversion API -------------- */
 
 /* This function is responsible for the correct transformations/conversions 
  * of a matrix from one space to another for constraint evaluation.
@@ -1112,7 +555,7 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
        }
 }
 
-/* ------------------------------- Target ---------------------------- */
+/* ------------ General Target Matrix Tools ---------- */
 
 /* function that sets the given matrix based on given vertex group in mesh */
 static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
@@ -1311,18 +754,277 @@ static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][
        }
 }
 
+/* ************************* Specific Constraints ***************************** */
+/* Each constraint defines a set of functions, which will be called at the appropriate
+ * times. In addition to this, each constraint should have a type-info struct, where
+ * its functions are attached for use. 
+ */
+/* Template for type-info data:
+ *     - make a copy of this when creating new constraints, and just change the functions
+ *       pointed to as necessary
+ *     - although the naming of functions doesn't matter, it would help for code
+ *       readability, to follow the same naming convention as is presented here
+ *     - any functions that a constraint doesn't need to define, don't define
+ *       for such cases, just use NULL 
+ *     - these should be defined after all the functions have been defined, so that
+ *       forward-definitions/prototypes don't need to be used!
+ *     - keep this copy #if-def'd so that future constraints can get based off this
+ */
+#if 0
+static bConstraintTypeInfo CTI_CONSTRNAME = {
+       CONSTRAINT_TYPE_CONSTRNAME, /* type */
+       sizeof(bConstrNameConstraint), /* size */
+       "ConstrName", /* name */
+       "bConstrNameConstraint", /* struct name */
+       constrname_free, /* free data */
+       constrname_relink, /* relink data */
+       constrname_copy, /* copy data */
+       constrname_new_data, /* new data */
+       constrname_get_tars, /* get constraint targets */
+       constrname_flush_tars, /* flush constraint targets */
+       constrname_get_tarmat, /* get target matrix */
+       constrname_evaluate /* evaluate */
+};
+#endif
+
+/* This function should be used for the get_target_matrix member of all 
+ * constraints that are not picky about what happens to their target matrix.
+ */
+static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       if (VALID_CONS_TARGET(ct))
+               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
+       else if (ct)
+               Mat4One(ct->matrix);
+}
+
+/* This following macro should be used for all standard single-target *_get_tars functions 
+ * to save typing and reduce maintainance woes.
+ * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
+ *  really just to help this code easier to read)
+ */
+#define SINGLETARGET_GET_TARS(con, data, ct, list) \
+       { \
+               ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
+                \
+               ct->tar= data->tar; \
+               strcpy(ct->subtarget, data->subtarget); \
+               ct->space= con->tarspace; \
+               ct->flag= CONSTRAINT_TAR_TEMP; \
+                \
+               if (ct->tar) { \
+                       if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_BONE; \
+                       else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_VERT; \
+                       else ct->type = CONSTRAINT_OBTYPE_OBJECT; \
+               } \
+                \
+               BLI_addtail(list, ct); \
+       }
+       
+/* This following macro should be used for all standard single-target *_get_tars functions 
+ * to save typing and reduce maintainance woes. It does not do the subtarget related operations
+ * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
+ *  really just to help this code easier to read)
+ */
+#define SINGLETARGETNS_GET_TARS(con, data, ct, list) \
+       { \
+               ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
+                \
+               ct->tar= data->tar; \
+               ct->space= con->tarspace; \
+               ct->flag= CONSTRAINT_TAR_TEMP; \
+                \
+               if (ct->tar) ct->type = CONSTRAINT_OBTYPE_OBJECT; \
+                \
+               BLI_addtail(list, ct); \
+       }
+
+/* This following macro should be used for all standard single-target *_flush_tars functions
+ * to save typing and reduce maintainance woes.
+ * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
+ *  really just to help this code easier to read)
+ */
+#define SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) \
+       { \
+               if (ct) { \
+                       if (nocopy == 0) { \
+                               data->tar= ct->tar; \
+                               strcpy(data->subtarget, ct->subtarget); \
+                               con->tarspace= ct->space; \
+                       } \
+                        \
+                       BLI_freelistN(list); \
+               } \
+       }
+       
+/* This following macro should be used for all standard single-target *_flush_tars functions
+ * to save typing and reduce maintainance woes. It does not do the subtarget related operations
+ * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
+ *  really just to help this code easier to read)
+ */
+#define SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy) \
+       { \
+               if (ct) { \
+                       if (nocopy == 0) { \
+                               data->tar= ct->tar; \
+                               con->tarspace= ct->space; \
+                       } \
+                        \
+                       BLI_freelistN(list); \
+               } \
+       }
+/* --------- ChildOf Constraint ------------ */
+
+static void childof_new_data (void *cdata)
+{
+       bChildOfConstraint *data= (bChildOfConstraint *)cdata;
+       
+       data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ |
+                                       CHILDOF_ROTX |CHILDOF_ROTY | CHILDOF_ROTZ |
+                                       CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ);
+       Mat4One(data->invmat);
+}
+
+static void childof_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bChildOfConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void childof_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bChildOfConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bChildOfConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target */
+       if (VALID_CONS_TARGET(ct)) {
+               float parmat[4][4], invmat[4][4], tempmat[4][4];
+               float loc[3], eul[3], size[3];
+               float loco[3], eulo[3], sizo[3];
+               
+               /* get offset (parent-inverse) matrix */
+               Mat4CpyMat4(invmat, data->invmat);
+               
+               /* extract components of both matrices */
+               VECCOPY(loc, ct->matrix[3]);
+               Mat4ToEul(ct->matrix, eul);
+               Mat4ToSize(ct->matrix, size);
+               
+               VECCOPY(loco, invmat[3]);
+               Mat4ToEul(invmat, eulo);
+               Mat4ToSize(invmat, sizo);
+               
+               /* disable channels not enabled */
+               if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f;
+               if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f;
+               if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f;
+               if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f;
+               if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f;
+               if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f;
+               if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f;
+               if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f;
+               if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f;
+               
+               /* make new target mat and offset mat */
+               LocEulSizeToMat4(ct->matrix, loc, eul, size);
+               LocEulSizeToMat4(invmat, loco, eulo, sizo);
+               
+               /* multiply target (parent matrix) by offset (parent inverse) to get 
+                * the effect of the parent that will be exherted on the owner
+                */
+               Mat4MulMat4(parmat, invmat, ct->matrix);
+               
+               /* now multiply the parent matrix by the owner matrix to get the 
+                * the effect of this constraint (i.e.  owner is 'parented' to parent)
+                */
+               Mat4CpyMat4(tempmat, cob->matrix);
+               Mat4MulMat4(cob->matrix, tempmat, parmat); 
+       }
+}
+
+static bConstraintTypeInfo CTI_CHILDOF = {
+       CONSTRAINT_TYPE_CHILDOF, /* type */
+       sizeof(bChildOfConstraint), /* size */
+       "ChildOf", /* name */
+       "bChildOfConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       childof_new_data, /* new data */
+       childof_get_tars, /* get constraint targets */
+       childof_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get a target matrix */
+       childof_evaluate /* evaluate */
+};
+
+/* -------- TrackTo Constraint ------- */
+
+static void trackto_new_data (void *cdata)
+{
+       bTrackToConstraint *data= (bTrackToConstraint *)cdata;
+       
+       data->reserved1 = TRACK_Y;
+       data->reserved2 = UP_Z;
+}      
+
+static void trackto_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bTrackToConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void trackto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bTrackToConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
 
-/* stupid little cross product function, 0:x, 1:y, 2:z axes */
-static int basis_cross(int n, int m)
+static int basis_cross (int n, int m)
 {
-       if(n-m == 1) return 1;
-       if(n-m == -1) return -1;
-       if(n-m == 2) return -1;
-       if(n-m == -2) return 1;
-       else return 0;
+       switch (n-m) {
+               case 1: 
+               case -2:
+                       return 1;
+                       
+               case -1: 
+               case 2:
+                       return -1;
+                       
+               default:
+                       return 0;
+       }
 }
 
-static void vectomat(float *vec, float *target_up, short axis, short upflag, short flags, float m[][3])
+static void vectomat (float *vec, float *target_up, short axis, short upflag, short flags, float m[][3])
 {
        float n[3];
        float u[3]; /* vector specifying the up axis */
@@ -1332,17 +1034,16 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
        int right_index;
        
        VecCopyf(n, vec);
-       if(Normalize(n) == 0.0) { 
+       if (Normalize(n) == 0.0) { 
                n[0] = 0.0;
                n[1] = 0.0;
                n[2] = 1.0;
        }
-       if(axis > 2) axis -= 3;
+       if (axis > 2) axis -= 3;
        else VecMulf(n,-1);
 
        /* n specifies the transformation of the track axis */
-
-       if(flags & TARGET_Z_UP) { 
+       if (flags & TARGET_Z_UP) { 
                /* target Z axis is the global up axis */
                u[0] = target_up[0];
                u[1] = target_up[1];
@@ -1360,7 +1061,7 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
        VecSubf(proj, u, proj); /* then onto the plane */
        /* proj specifies the transformation of the up axis */
 
-       if(Normalize(proj) == 0.0) { /* degenerate projection */
+       if (Normalize(proj) == 0.0) { /* degenerate projection */
                proj[0] = 0.0;
                proj[1] = 1.0;
                proj[2] = 0.0;
@@ -1370,19 +1071,19 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
        Crossf(right, proj, n);
        Normalize(right);
 
-       if(axis != upflag) {
+       if (axis != upflag) {
                right_index = 3 - axis - upflag;
-               neg = (float) basis_cross(axis, upflag);
-
+               neg = (float)basis_cross(axis, upflag);
+               
                /* account for up direction, track direction */
                m[right_index][0] = neg * right[0];
                m[right_index][1] = neg * right[1];
                m[right_index][2] = neg * right[2];
-
+               
                m[upflag][0] = proj[0];
                m[upflag][1] = proj[1];
                m[upflag][2] = proj[2];
-
+               
                m[axis][0] = n[0];
                m[axis][1] = n[1];
                m[axis][2] = n[2];
@@ -1397,1449 +1098,2212 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
 }
 
 
-/* called during solve_constraints */
-/* also for make_parent, to find correct inverse of "follow path" */
-/* warning: ownerdata is PoseChannel or Object */
-/* ctime is global time, uncorrected for local bsystem_time */
-short get_constraint_target_matrix (bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime)
+static void trackto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
 {
-       short valid=0;
+       bTrackToConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               float size[3], vec[3];
+               float totmat[3][3];
+               float tmat[4][4];
+               
+               /* Get size property, since ob->size is only the object's own relative size, not its global one */
+               Mat4ToSize(cob->matrix, size);
+               
+               /* Clear the object's rotation */       
+               cob->matrix[0][0]=size[0];
+               cob->matrix[0][1]=0;
+               cob->matrix[0][2]=0;
+               cob->matrix[1][0]=0;
+               cob->matrix[1][1]=size[1];
+               cob->matrix[1][2]=0;
+               cob->matrix[2][0]=0;
+               cob->matrix[2][1]=0;
+               cob->matrix[2][2]=size[2];
+               
+               /* targetmat[2] instead of ownermat[2] is passed to vectomat
+                * for backwards compatability it seems... (Aligorith)
+                */
+               VecSubf(vec, cob->matrix[3], ct->matrix[3]);
+               vectomat(vec, ct->matrix[2], 
+                               (short)data->reserved1, (short)data->reserved2, 
+                               data->flags, totmat);
+               
+               Mat4CpyMat4(tmat, cob->matrix);
+               Mat4MulMat34(cob->matrix, totmat, tmat);
+       }
+}
 
-       switch (con->type) {
-       case CONSTRAINT_TYPE_NULL:
-               {
-                       Mat4One(mat);
-               }
-               break;
-       case CONSTRAINT_TYPE_ACTION:
-               {
-                       if (ownertype == TARGET_BONE) {
-                               extern void chan_calc_mat(bPoseChannel *chan);
-                               bActionConstraint *data = (bActionConstraint*)con->data;
-                               bPose *pose;
-                               bPoseChannel *pchan, *tchan;
-                               float tempmat[4][4], vec[3];
-                               float s, t;
-                               short axis;
-                               
-                               /* initialise return matrix */
-                               Mat4One(mat);
-                               
-                               /* only continue if there is a target  */
-                               if (data->tar==NULL) return 0;
-                               
-                               /* get the transform matrix of the target */
-                               constraint_target_to_mat4(data->tar, data->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, con->tarspace); // FIXME: change these spaces 
-                               
-                               /* determine where in transform range target is */
-                               /* data->type is mapped as follows for backwards compatability:
-                                *      00,01,02        - rotation (it used to be like this)
-                                *      10,11,12        - scaling
-                                *      20,21,22        - location
-                                */
-                               if (data->type < 10) {
-                                       /* extract rotation (is in whatever space target should be in) */
-                                       Mat4ToEul(tempmat, vec);
-                                       vec[0] *= (float)(180.0/M_PI);
-                                       vec[1] *= (float)(180.0/M_PI);
-                                       vec[2] *= (float)(180.0/M_PI);
-                                       axis= data->type;
-                               }
-                               else if (data->type < 20) {
-                                       /* extract scaling (is in whatever space target should be in) */
-                                       Mat4ToSize(tempmat, vec);
-                                       axis= data->type - 10;
-                               }
-                               else {
-                                       /* extract location */
-                                       VECCOPY(vec, tempmat[3]);
-                                       axis= data->type - 20;
-                               }
-                               
-                               /* Target defines the animation */
-                               s = (vec[axis]-data->min) / (data->max-data->min);
-                               CLAMP(s, 0, 1);
-                               t = ( s * (data->end-data->start)) + data->start;
-                               
-                               /* Get the appropriate information from the action, we make temp pose */
-                               pose = MEM_callocN(sizeof(bPose), "pose");
-                               
-                               pchan = ownerdata;
-                               tchan= verify_pose_channel(pose, pchan->name);
-                               extract_pose_from_action(pose, data->act, t);
-                               
-                               chan_calc_mat(tchan);
-                               
-                               Mat4CpyMat4(mat, tchan->chan_mat);
-                               
-                               /* Clean up */
-                               free_pose_channels(pose);
-                               MEM_freeN(pose);
-                       }
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data;
-                       Object *ob= data->tar;
-                       
-                       if (data->tar) {
-                               if (data->tar->type==OB_ARMATURE && strlen(data->subtarget)) {
-                                       /* Pose-Channels for the CopyLoc target are handled specially, so that
-                                        * we can support using the bone-tip as an option.
-                                        */
-                                       bPoseChannel *pchan;
-                                       float tmat[4][4];
-                                       
-                                       pchan = get_pose_channel(ob->pose, data->subtarget);
-                                       if (pchan) {
-                                               Mat4CpyMat4(tmat, pchan->pose_mat);
-                                               
-                                               if (data->flag & LOCLIKE_TIP) { 
-                                                       VECCOPY(tmat[3], pchan->pose_tail);
-                                               }
-                                                       
-                                               Mat4MulMat4(mat, tmat, ob->obmat);
-                                       }
-                                       else 
-                                               Mat4CpyMat4(mat, ob->obmat);
-                                               
-                                       /* convert matrix space as required  */
-                                       constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               }
-                               else {
-                                       /* get target matrix as is done normally for other constraints */
-                                       constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               }
-                               valid=1;
-                       }
-                       else
-                               Mat4One(mat);
-               } 
-               break;
-       case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data;
-                       data = (bRotateLikeConstraint*)con->data;
-                       
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               valid=1;
-                       }
-                       else
-                               Mat4One(mat);
-               } 
-               break;
-       case CONSTRAINT_TYPE_SIZELIKE:
-               {
-                       bSizeLikeConstraint *data;
-                       data = (bSizeLikeConstraint*)con->data;
-                       
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               valid=1;
-                       }
-                       else
-                               Mat4One(mat);
-               } 
-               break;
-       case CONSTRAINT_TYPE_MINMAX:
-               {
-                       bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
-                       
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               valid=1;
+static bConstraintTypeInfo CTI_TRACKTO = {
+       CONSTRAINT_TYPE_TRACKTO, /* type */
+       sizeof(bTrackToConstraint), /* size */
+       "TrackTo", /* name */
+       "bTrackToConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       trackto_new_data, /* new data */
+       trackto_get_tars, /* get constraint targets */
+       trackto_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get target matrix */
+       trackto_evaluate /* evaluate */
+};
+
+/* --------- Inverse-Kinemetics --------- */
+
+static void kinematic_new_data (void *cdata)
+{
+       bKinematicConstraint *data= (bKinematicConstraint *)cdata;
+       
+       data->weight= (float)1.0;
+       data->orientweight= (float)1.0;
+       data->iterations = 500;
+       data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS;
+}
+
+static void kinematic_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bKinematicConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bKinematicConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       bKinematicConstraint *data= con->data;
+       
+       if (VALID_CONS_TARGET(ct)) 
+               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
+       else if (ct) {
+               if (data->flag & CONSTRAINT_IK_AUTO) {
+                       Object *ob= cob->ob;
+                       
+                       if (ob == NULL) {
+                               Mat4One(ct->matrix);
                        }
-                       else
-                               Mat4One(mat);
-               } 
-               break;
-       case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data;
-                       data = (bTrackToConstraint*)con->data;
-                       
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               valid=1;
+                       else {
+                               float vec[3];
+                               /* move grabtarget into world space */
+                               VECCOPY(vec, data->grabtarget);
+                               Mat4MulVecfl(ob->obmat, vec);
+                               Mat4CpyMat4(ct->matrix, ob->obmat);
+                               VECCOPY(ct->matrix[3], vec);
                        }
-                       else
-                               Mat4One (mat);
                }
-               break;
-       case CONSTRAINT_TYPE_KINEMATIC:
-               {
-                       bKinematicConstraint *data;
-                       data = (bKinematicConstraint*)con->data;
-                       
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               valid=1;
-                       }
-                       else if (data->flag & CONSTRAINT_IK_AUTO) {
-                               Object *ob= (Object *)ownerdata;
-                               
-                               if (ob==NULL)
-                                       Mat4One(mat);
-                               else {
-                                       float vec[3];
-                                       /* move grabtarget into world space */
-                                       VECCOPY(vec, data->grabtarget);
-                                       Mat4MulVecfl(ob->obmat, vec);
-                                       Mat4CpyMat4(mat, ob->obmat);
-                                       VECCOPY(mat[3], vec);
-                               }
-                       }
-                       else
-                               Mat4One(mat);
-               } 
-               break;
-       case CONSTRAINT_TYPE_LOCKTRACK:
-               {
-                       bLockTrackConstraint *data;
-                       data = (bLockTrackConstraint*)con->data;
+               else
+                       Mat4One(ct->matrix);
+       }
+}
+
+static bConstraintTypeInfo CTI_KINEMATIC = {
+       CONSTRAINT_TYPE_KINEMATIC, /* type */
+       sizeof(bKinematicConstraint), /* size */
+       "IK", /* name */
+       "bKinematicConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       kinematic_new_data, /* new data */
+       kinematic_get_tars, /* get constraint targets */
+       kinematic_flush_tars, /* flush constraint targets */
+       kinematic_get_tarmat, /* get target matrix */
+       NULL /* evaluate - solved as separate loop */
+};
+
+/* -------- Follow-Path Constraint ---------- */
+
+static void followpath_new_data (void *cdata)
+{
+       bFollowPathConstraint *data= (bFollowPathConstraint *)cdata;
+       
+       data->trackflag = TRACK_Y;
+       data->upflag = UP_Z;
+       data->offset = 0;
+       data->followflag = 0;
+}
+
+static void followpath_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bFollowPathConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints without subtargets */
+               SINGLETARGETNS_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void followpath_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bFollowPathConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       bFollowPathConstraint *data= con->data;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               Curve *cu= ct->tar->data;
+               float q[4], vec[4], dir[3], *quat, x1;
+               float totmat[4][4];
+               float curvetime;
+               
+               Mat4One(totmat);
+               Mat4One(ct->matrix);
+               
+               /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
+                *              currently for paths to work it needs to go through the bevlist/displist system (ton) 
+                */
+               
+               /* only happens on reload file, but violates depsgraph still... fix! */
+               if (cu->path==NULL || cu->path->data==NULL) 
+                       makeDispListCurveTypes(ct->tar, 0);
+               
+               if (cu->path && cu->path->data) {
+                       curvetime= bsystem_time(ct->tar, (float)ctime, 0.0) - data->offset;
                        
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace); 
-                               valid=1;
+                       if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
+                               curvetime /= cu->pathlen;
+                               CLAMP(curvetime, 0.0, 1.0);
                        }
-                       else
-                               Mat4One(mat);
-               } 
-               break;
-       case CONSTRAINT_TYPE_FOLLOWPATH:
-               {
-                       bFollowPathConstraint *data;
-                       data = (bFollowPathConstraint*)con->data;
                        
-                       if (data->tar) {
-                               Curve *cu;
-                               float q[4], vec[4], dir[3], *quat, x1;
-                               float totmat[4][4];
-                               float curvetime;
-                               
-                               Mat4One(totmat);
-                               Mat4One(mat);
-                               
-                               cu= data->tar->data;
-                               
-                               /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
-                                       currently for paths to work it needs to go through the bevlist/displist system (ton) */
-                               
-                               if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
-                                       makeDispListCurveTypes(data->tar, 0);
-                               if (cu->path && cu->path->data) {
-                                       curvetime= bsystem_time(data->tar, (float)ctime, 0.0) - data->offset;
+                       if ( where_on_path(ct->tar, curvetime, vec, dir) ) {
+                               if (data->followflag) {
+                                       quat= vectoquat(dir, (short) data->trackflag, (short) data->upflag);
                                        
-                                       if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
-                                               curvetime /= cu->pathlen;
-                                               CLAMP(curvetime, 0.0, 1.0);
-                                       }
+                                       Normalize(dir);
+                                       q[0]= (float)cos(0.5*vec[3]);
+                                       x1= (float)sin(0.5*vec[3]);
+                                       q[1]= -x1*dir[0];
+                                       q[2]= -x1*dir[1];
+                                       q[3]= -x1*dir[2];
+                                       QuatMul(quat, q, quat);
                                        
-                                       if (where_on_path(data->tar, curvetime, vec, dir) ) {
-                                               if (data->followflag) {
-                                                       quat= vectoquat(dir, (short) data->trackflag, (short) data->upflag);
-                                                       
-                                                       Normalize(dir);
-                                                       q[0]= (float)cos(0.5*vec[3]);
-                                                       x1= (float)sin(0.5*vec[3]);
-                                                       q[1]= -x1*dir[0];
-                                                       q[2]= -x1*dir[1];
-                                                       q[3]= -x1*dir[2];
-                                                       QuatMul(quat, q, quat);
-                                                       
-                                                       QuatToMat4(quat, totmat);
-                                               }
-                                               VECCOPY(totmat[3], vec);
-                                               
-                                               Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
-                                       }
+                                       QuatToMat4(quat, totmat);
                                }
-                               valid=1;
-                       }
-                       else
-                               Mat4One(mat);
-               }
-               break;
-       case CONSTRAINT_TYPE_STRETCHTO:
-               {
-                       bStretchToConstraint *data;
-                       data = (bStretchToConstraint*)con->data;
-                       
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               valid = 1;
-                       }
-                       else
-                               Mat4One(mat);
-               }
-               break;
-       case CONSTRAINT_TYPE_PYTHON:
-               {
-                       bPythonConstraint *data;
-                       data = (bPythonConstraint*)con->data;
-                       
-                       /* special exception for curves - depsgraph issues */
-                       if (data->tar && data->tar->type == OB_CURVE) {
-                               Curve *cu= data->tar->data;
+                               VECCOPY(totmat[3], vec);
                                
-                               /* this check is to make sure curve objects get updated on file load correctly.*/
-                               if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
-                                       makeDispListCurveTypes(data->tar, 0);                           
+                               Mat4MulSerie(ct->matrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
                        }
-                       
-                       /* if the script doesn't set the target matrix for any reason, fall back to standard methods */
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               if (BPY_pyconstraint_targets(data, mat) >= 1) {
-                                       valid = 1;
-                               }
-                       }
-                       if (!valid)
-                               Mat4One(mat);
                }
-               break;
-       case CONSTRAINT_TYPE_CLAMPTO:
-               {
-                       bClampToConstraint *data;
-                       data = (bClampToConstraint*)con->data;
-                       
-                       if (data->tar) {
-                               Curve *cu= data->tar->data;
-                               
-                               /* note; when creating constraints that follow path, the curve gets the CU_PATH set now,
-                                       currently for paths to work it needs to go through the bevlist/displist system (ton) */
-                               
-                               if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
-                                       makeDispListCurveTypes(data->tar, 0);
-                               
-                               valid = 1;
-                       }
+       }
+       else if (ct)
+               Mat4One(ct->matrix);
+}
+
+static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target */
+       if (VALID_CONS_TARGET(ct)) {
+               float obmat[4][4];
+               float size[3], obsize[3];
+               
+               /* get Object local transform (loc/rot/size) to determine transformation from path */
+               //object_to_mat4(ob, obmat);
+               Mat4CpyMat4(obmat, cob->matrix); // FIXME!!!
+               
+               /* get scaling of object before applying constraint */
+               Mat4ToSize(cob->matrix, size);
+               
+               /* apply targetmat - containing location on path, and rotation */
+               Mat4MulSerie(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
+               
+               /* un-apply scaling caused by path */
+               Mat4ToSize(cob->matrix, obsize);
+               if (obsize[0])
+                       VecMulf(cob->matrix[0], size[0] / obsize[0]);
+               if (obsize[1])
+                       VecMulf(cob->matrix[1], size[1] / obsize[1]);
+               if (obsize[2])
+                       VecMulf(cob->matrix[2], size[2] / obsize[2]);
+       }
+}
+
+static bConstraintTypeInfo CTI_FOLLOWPATH = {
+       CONSTRAINT_TYPE_FOLLOWPATH, /* type */
+       sizeof(bFollowPathConstraint), /* size */
+       "Follow Path", /* name */
+       "bFollowPathConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       followpath_new_data, /* new data */
+       followpath_get_tars, /* get constraint targets */
+       followpath_flush_tars, /* flush constraint targets */
+       followpath_get_tarmat, /* get target matrix */
+       followpath_evaluate /* evaluate */
+};
+
+/* --------- Limit Location --------- */
+
+
+static void loclimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bLocLimitConstraint *data = con->data;
+       
+       if (data->flag & LIMIT_XMIN) {
+               if (cob->matrix[3][0] < data->xmin)
+                       cob->matrix[3][0] = data->xmin;
+       }
+       if (data->flag & LIMIT_XMAX) {
+               if (cob->matrix[3][0] > data->xmax)
+                       cob->matrix[3][0] = data->xmax;
+       }
+       if (data->flag & LIMIT_YMIN) {
+               if (cob->matrix[3][1] < data->ymin)
+                       cob->matrix[3][1] = data->ymin;
+       }
+       if (data->flag & LIMIT_YMAX) {
+               if (cob->matrix[3][1] > data->ymax)
+                       cob->matrix[3][1] = data->ymax;
+       }
+       if (data->flag & LIMIT_ZMIN) {
+               if (cob->matrix[3][2] < data->zmin) 
+                       cob->matrix[3][2] = data->zmin;
+       }
+       if (data->flag & LIMIT_ZMAX) {
+               if (cob->matrix[3][2] > data->zmax)
+                       cob->matrix[3][2] = data->zmax;
+       }
+}
+
+static bConstraintTypeInfo CTI_LOCLIMIT = {
+       CONSTRAINT_TYPE_LOCLIMIT, /* type */
+       sizeof(bLocLimitConstraint), /* size */
+       "Limit Location", /* name */
+       "bLocLimitConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       NULL, /* new data */
+       NULL, /* get constraint targets */
+       NULL, /* flush constraint targets */
+       NULL, /* get target matrix */
+       loclimit_evaluate /* evaluate */
+};
+
+/* -------- Limit Rotation --------- */
+
+static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bRotLimitConstraint *data = con->data;
+       float loc[3];
+       float eul[3];
+       float size[3];
+       
+       VECCOPY(loc, cob->matrix[3]);
+       Mat4ToSize(cob->matrix, size);
+       
+       Mat4ToEul(cob->matrix, eul);
+       
+       /* eulers: radians to degrees! */
+       eul[0] = (eul[0] / M_PI * 180);
+       eul[1] = (eul[1] / M_PI * 180);
+       eul[2] = (eul[2] / M_PI * 180);
+       
+       /* limiting of euler values... */
+       if (data->flag & LIMIT_XROT) {
+               if (eul[0] < data->xmin) 
+                       eul[0] = data->xmin;
                        
-                       Mat4One(mat);
-               }
-               break;
-       case CONSTRAINT_TYPE_CHILDOF:
-               {
-                       bChildOfConstraint *data;
-                       data= (bChildOfConstraint *)con->data;
+               if (eul[0] > data->xmax)
+                       eul[0] = data->xmax;
+       }
+       if (data->flag & LIMIT_YROT) {
+               if (eul[1] < data->ymin)
+                       eul[1] = data->ymin;
                        
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               valid = 1;
-                       }
-                       else
-                               Mat4One(mat);
-               }
-               break;
-       case CONSTRAINT_TYPE_TRANSFORM:
-               {
-                       bTransformConstraint *data;
-                       data= (bTransformConstraint *)con->data;
+               if (eul[1] > data->ymax)
+                       eul[1] = data->ymax;
+       }
+       if (data->flag & LIMIT_ZROT) {
+               if (eul[2] < data->zmin)
+                       eul[2] = data->zmin;
                        
-                       if (data->tar) {
-                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
-                               valid = 1;
-                       }
-                       else
-                               Mat4One(mat);
-               }
-               break;
+               if (eul[2] > data->zmax)
+                       eul[2] = data->zmax;
+       }
+               
+       /* eulers: degrees to radians ! */
+       eul[0] = (eul[0] / 180 * M_PI); 
+       eul[1] = (eul[1] / 180 * M_PI);
+       eul[2] = (eul[2] / 180 * M_PI);
+       
+       LocEulSizeToMat4(cob->matrix, loc, eul, size);
+}
 
-       default:
-               Mat4One(mat);
-               break;
+static bConstraintTypeInfo CTI_ROTLIMIT = {
+       CONSTRAINT_TYPE_ROTLIMIT, /* type */
+       sizeof(bRotLimitConstraint), /* size */
+       "Limit Rotation", /* name */
+       "bRotLimitConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       NULL, /* new data */
+       NULL, /* get constraint targets */
+       NULL, /* flush constraint targets */
+       NULL, /* get target matrix */
+       rotlimit_evaluate /* evaluate */
+};
+
+/* --------- Limit Scaling --------- */
+
+
+static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bSizeLimitConstraint *data = con->data;
+       float obsize[3], size[3];
+       
+       Mat4ToSize(cob->matrix, size);
+       Mat4ToSize(cob->matrix, obsize);
+       
+       if (data->flag & LIMIT_XMIN) {
+               if (size[0] < data->xmin) 
+                       size[0] = data->xmin;   
+       }
+       if (data->flag & LIMIT_XMAX) {
+               if (size[0] > data->xmax) 
+                       size[0] = data->xmax;
        }
+       if (data->flag & LIMIT_YMIN) {
+               if (size[1] < data->ymin) 
+                       size[1] = data->ymin;   
+       }
+       if (data->flag & LIMIT_YMAX) {
+               if (size[1] > data->ymax) 
+                       size[1] = data->ymax;
+       }
+       if (data->flag & LIMIT_ZMIN) {
+               if (size[2] < data->zmin) 
+                       size[2] = data->zmin;   
+       }
+       if (data->flag & LIMIT_ZMAX) {
+               if (size[2] > data->zmax) 
+                       size[2] = data->zmax;
+       }
+       
+       if (obsize[0]) 
+               VecMulf(cob->matrix[0], size[0]/obsize[0]);
+       if (obsize[1]) 
+               VecMulf(cob->matrix[1], size[1]/obsize[1]);
+       if (obsize[2]) 
+               VecMulf(cob->matrix[2], size[2]/obsize[2]);
+}
 
-       return valid;
+static bConstraintTypeInfo CTI_SIZELIMIT = {
+       CONSTRAINT_TYPE_SIZELIMIT, /* type */
+       sizeof(bSizeLimitConstraint), /* size */
+       "Limit Scaling", /* name */
+       "bSizeLimitConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       NULL, /* new data */
+       NULL, /* get constraint targets */
+       NULL, /* flush constraint targets */
+       NULL, /* get target matrix */
+       sizelimit_evaluate /* evaluate */
+};
+
+/* ----------- Copy Location ------------- */
+
+static void loclike_new_data (void *cdata)
+{
+       bLocateLikeConstraint *data= (bLocateLikeConstraint *)cdata;
+       
+       data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
 }
 
-/* ---------------------------------------------- Constraint Evaluation ------------------------------------------------- */
+static void loclike_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bLocateLikeConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
 
-/* This is only called during solve_constraints to solve a particular constraint.
- * It works on ownermat, and uses targetmat to help accomplish its tasks.
- */
-static void evaluate_constraint (bConstraint *constraint, float ownermat[][4], float targetmat[][4])
+static void loclike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
 {
-       if (constraint == NULL || constraint->data == NULL)
-               return;
+       if (con && list) {
+               bLocateLikeConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
                
-       switch (constraint->type) {
-       case CONSTRAINT_TYPE_NULL:
-       case CONSTRAINT_TYPE_KINEMATIC: /* removed */
-               break;
-       case CONSTRAINT_TYPE_PYTHON:
-               {
-                       bPythonConstraint *data;
-                       
-                       data = constraint->data;
-                       BPY_pyconstraint_eval(data, ownermat, targetmat);
-               } 
-               break;
-       case CONSTRAINT_TYPE_ACTION:
-               {
-                       bActionConstraint *data;
-                       float temp[4][4];
-                       
-                       data = constraint->data;
-                       Mat4CpyMat4(temp, ownermat);
-                       
-                       Mat4MulMat4(ownermat, targetmat, temp);
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data;
-                       float offset[3] = {0.0f, 0.0f, 0.0f};
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
 
-                       data = constraint->data;
-                       
-                       if (data->flag & LOCLIKE_OFFSET)
-                               VECCOPY(offset, ownermat[3]);
+static void loclike_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       bLocateLikeConstraint *data = con->data;
+
+       if (VALID_CONS_TARGET(ct)) {
+               if (ct->tar->type==OB_ARMATURE && strlen(ct->subtarget)) {
+                       /* Pose-Channels for the CopyLoc target are handled specially, so that
+                        * we can support using the bone-tip as an option.
+                        */
+                       bPoseChannel *pchan;
+                       float tmat[4][4];
                        
-                       if (data->flag & LOCLIKE_X) {
-                               ownermat[3][0] = targetmat[3][0];
-                               
-                               if(data->flag & LOCLIKE_X_INVERT) ownermat[3][0] *= -1;
-                               ownermat[3][0] += offset[0];
-                       }
-                       if (data->flag & LOCLIKE_Y) {
-                               ownermat[3][1] = targetmat[3][1];
+                       pchan = get_pose_channel(ct->tar->pose, ct->subtarget);
+                       if (pchan) {
+                               Mat4CpyMat4(tmat, pchan->pose_mat);
                                
-                               if(data->flag & LOCLIKE_Y_INVERT) ownermat[3][1] *= -1;
-                               ownermat[3][1] += offset[1];
+                               if (data->flag & LOCLIKE_TIP) { 
+                                       VECCOPY(tmat[3], pchan->pose_tail);
+                               }
+                                       
+                               Mat4MulMat4(ct->matrix, tmat, ct->tar->obmat);
                        }
-                       if (data->flag & LOCLIKE_Z) {
-                               ownermat[3][2] = targetmat[3][2];
+                       else 
+                               Mat4CpyMat4(ct->matrix, ct->tar->obmat);
                                
-                               if(data->flag & LOCLIKE_Z_INVERT) ownermat[3][2] *= -1;
-                               ownermat[3][2] += offset[2];
-                       }
+                       /* convert matrix space as required  */
+                       constraint_mat_convertspace(ct->tar, pchan, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
                }
-               break;
-       case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data;
-                       float   loc[3];
-                       float   eul[3], obeul[3];
-                       float   size[3];
-                       
-                       data = constraint->data;
-                       
-                       VECCOPY(loc, ownermat[3]);
-                       Mat4ToSize(ownermat, size);
-                       
-                       Mat4ToEul(targetmat, eul);
-                       Mat4ToEul(ownermat, obeul);
-                       
-                       if ((data->flag & ROTLIKE_X)==0) {
-                               eul[0] = obeul[0];
-                       }
-                       else if (data->flag & ROTLIKE_X_INVERT) {
-                               eul[0] *= -1;
-                       }       
-                       
-                       if ((data->flag & ROTLIKE_Y)==0) {
-                               eul[1] = obeul[1];
-                       }
-                       else if (data->flag & ROTLIKE_Y_INVERT) {
-                               eul[1] *= -1;
-                       }
-                       
-                       if ((data->flag & ROTLIKE_Z)==0) {
-                               eul[2] = obeul[2];
-                       }
-                       else if (data->flag & ROTLIKE_Z_INVERT) {
-                               eul[2] *= -1;
-                       }
-                       
-                       compatible_eul(eul, obeul);
-                       LocEulSizeToMat4(ownermat, loc, eul, size);
+               else {
+                       /* get target matrix as is done normally for other constraints */
+                       constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
                }
-               break;
-       case CONSTRAINT_TYPE_SIZELIKE:
-               {
-                       bSizeLikeConstraint *data;
-                       float obsize[3], size[3];
-                       
-                       data = constraint->data;
-                       Mat4ToSize(targetmat, size);
-                       Mat4ToSize(ownermat, obsize);
-                       
-                       if ((data->flag & SIZELIKE_X) && obsize[0] != 0)
-                               VecMulf(ownermat[0], size[0] / obsize[0]);
-                       if ((data->flag & SIZELIKE_Y) && obsize[1] != 0)
-                               VecMulf(ownermat[1], size[1] / obsize[1]);
-                       if ((data->flag & SIZELIKE_Z) && obsize[2] != 0)
-                               VecMulf(ownermat[2], size[2] / obsize[2]);
-               }
-               break;
-       case CONSTRAINT_TYPE_MINMAX:
-               {
-                       bMinMaxConstraint *data;
-                       float obmat[4][4], imat[4][4], tarmat[4][4], tmat[4][4];
-                       float val1, val2;
-                       int index;
-                       
-                       data = constraint->data;
+       }
+       else if (ct)
+               Mat4One(ct->matrix);
+}
+
+static void loclike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bLocateLikeConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               float offset[3] = {0.0f, 0.0f, 0.0f};
+               
+               if (data->flag & LOCLIKE_OFFSET)
+                       VECCOPY(offset, cob->matrix[3]);
                        
-                       Mat4CpyMat4(obmat, ownermat);
-                       Mat4CpyMat4(tarmat, targetmat);
+               if (data->flag & LOCLIKE_X) {
+                       cob->matrix[3][0] = ct->matrix[3][0];
                        
-                       if (data->flag & MINMAX_USEROT) {
-                               /* take rotation of target into account by doing the transaction in target's localspace */
-                               Mat4Invert(imat, tarmat);
-                               Mat4MulMat4(tmat, obmat, imat);
-                               Mat4CpyMat4(obmat, tmat);
-                               Mat4One(tarmat);
-                       }
+                       if (data->flag & LOCLIKE_X_INVERT) cob->matrix[3][0] *= -1;
+                       cob->matrix[3][0] += offset[0];
+               }
+               if (data->flag & LOCLIKE_Y) {
+                       cob->matrix[3][1] = ct->matrix[3][1];
                        
-                       switch (data->minmaxflag) {
-                       case TRACK_Z:
-                               val1 = tarmat[3][2];
-                               val2 = obmat[3][2]-data->offset;
-                               index = 2;
-                               break;
-                       case TRACK_Y:
-                               val1 = tarmat[3][1];
-                               val2 = obmat[3][1]-data->offset;
-                               index = 1;
-                               break;
-                       case TRACK_X:
-                               val1 = tarmat[3][0];
-                               val2 = obmat[3][0]-data->offset;
-                               index = 0;
-                               break;
-                       case TRACK_nZ:
-                               val2 = tarmat[3][2];
-                               val1 = obmat[3][2]-data->offset;
-                               index = 2;
-                               break;
-                       case TRACK_nY:
-                               val2 = tarmat[3][1];
-                               val1 = obmat[3][1]-data->offset;
-                               index = 1;
-                               break;
-                       case TRACK_nX:
-                               val2 = tarmat[3][0];
-                               val1 = obmat[3][0]-data->offset;
-                               index = 0;
-                               break;
-                       default:
-                               return;
-                       }
+                       if (data->flag & LOCLIKE_Y_INVERT) cob->matrix[3][1] *= -1;
+                       cob->matrix[3][1] += offset[1];
+               }
+               if (data->flag & LOCLIKE_Z) {
+                       cob->matrix[3][2] = ct->matrix[3][2];
                        
-                       if (val1 > val2) {
-                               obmat[3][index] = tarmat[3][index] + data->offset;
-                               if (data->flag & MINMAX_STICKY) {
-                                       if (data->flag & MINMAX_STUCK) {
-                                               VECCOPY(obmat[3], data->cache);
-                                       } 
-                                       else {
-                                               VECCOPY(data->cache, obmat[3]);
-                                               data->flag |= MINMAX_STUCK;
-                                       }
-                               }
-                               if (data->flag & MINMAX_USEROT) {
-                                       /* get out of localspace */
-                                       Mat4MulMat4(tmat, obmat, targetmat);
-                                       Mat4CpyMat4(ownermat, tmat);
-                               } 
-                               else {                  
-                                       VECCOPY(ownermat[3], obmat[3]);
-                               }
-                       } 
-                       else {
-                               data->flag &= ~MINMAX_STUCK;
-                       }
+                       if (data->flag & LOCLIKE_Z_INVERT) cob->matrix[3][2] *= -1;
+                       cob->matrix[3][2] += offset[2];
                }
-               break;
-       case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data;
-                       float size[3], vec[3];
-                       float totmat[3][3];
-                       float tmat[4][4];
+       }
+}
 
-                       data = constraint->data;                        
+static bConstraintTypeInfo CTI_LOCLIKE = {
+       CONSTRAINT_TYPE_LOCLIKE, /* type */
+       sizeof(bLocateLikeConstraint), /* size */
+       "Copy Location", /* name */
+       "bLocateLikeConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       loclike_new_data, /* new data */
+       loclike_get_tars, /* get constraint targets */
+       loclike_flush_tars, /* flush constraint targets */
+       loclike_get_tarmat, /* get target matrix */
+       loclike_evaluate /* evaluate */
+};
+
+/* ----------- Copy Rotation ------------- */
+
+static void rotlike_new_data (void *cdata)
+{
+       bRotateLikeConstraint *data= (bRotateLikeConstraint *)cdata;
+       
+       data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
+}
+
+static void rotlike_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bRotateLikeConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void rotlike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bRotateLikeConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bRotateLikeConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               float   loc[3];
+               float   eul[3], obeul[3];
+               float   size[3];
+               
+               VECCOPY(loc, cob->matrix[3]);
+               Mat4ToSize(cob->matrix, size);
+               
+               Mat4ToEul(ct->matrix, eul);
+               Mat4ToEul(cob->matrix, obeul);
+               
+               if ((data->flag & ROTLIKE_X)==0) {
+                       eul[0] = obeul[0];
+               }
+               else if (data->flag & ROTLIKE_X_INVERT) {
+                       eul[0] *= -1;
+               }       
+               
+               if ((data->flag & ROTLIKE_Y)==0) {
+                       eul[1] = obeul[1];
+               }
+               else if (data->flag & ROTLIKE_Y_INVERT) {
+                       eul[1] *= -1;
+               }
+               
+               if ((data->flag & ROTLIKE_Z)==0) {
+                       eul[2] = obeul[2];
+               }
+               else if (data->flag & ROTLIKE_Z_INVERT) {
+                       eul[2] *= -1;
+               }
+               
+               compatible_eul(eul, obeul);
+               LocEulSizeToMat4(cob->matrix, loc, eul, size);
+       }
+}
+
+static bConstraintTypeInfo CTI_ROTLIKE = {
+       CONSTRAINT_TYPE_ROTLIKE, /* type */
+       sizeof(bRotateLikeConstraint), /* size */
+       "Copy Rotation", /* name */
+       "bRotateLikeConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       rotlike_new_data, /* new data */
+       rotlike_get_tars, /* get constraint targets */
+       rotlike_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get target matrix */
+       rotlike_evaluate /* evaluate */
+};
+
+/* ---------- Copy Scaling ---------- */
+
+static void sizelike_new_data (void *cdata)
+{
+       bSizeLikeConstraint *data= (bSizeLikeConstraint *)cdata;
+       
+       data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
+}
+
+static void sizelike_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bSizeLikeConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void sizelike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bSizeLikeConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void sizelike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bSizeLikeConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               float obsize[3], size[3];
+               
+               Mat4ToSize(ct->matrix, size);
+               Mat4ToSize(cob->matrix, obsize);
+               
+               if ((data->flag & SIZELIKE_X) && obsize[0] != 0)
+                       VecMulf(cob->matrix[0], size[0] / obsize[0]);
+               if ((data->flag & SIZELIKE_Y) && obsize[1] != 0)
+                       VecMulf(cob->matrix[1], size[1] / obsize[1]);
+               if ((data->flag & SIZELIKE_Z) && obsize[2] != 0)
+                       VecMulf(cob->matrix[2], size[2] / obsize[2]);
+       }
+}
+
+static bConstraintTypeInfo CTI_SIZELIKE = {
+       CONSTRAINT_TYPE_SIZELIKE, /* type */
+       sizeof(bSizeLikeConstraint), /* size */
+       "Copy Scale", /* name */
+       "bSizeLikeConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       sizelike_new_data, /* new data */
+       sizelike_get_tars, /* get constraint targets */
+       sizelike_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get target matrix */
+       sizelike_evaluate /* evaluate */
+};
+
+/* ----------- Python Constraint -------------- */
+
+static void pycon_free (bConstraint *con)
+{
+       bPythonConstraint *data= con->data;
+       bConstraintTarget *ct;
+       
+       /* id-properties */
+       IDP_FreeProperty(data->prop);
+       MEM_freeN(data->prop);
+       
+       /* multiple targets */
+       while ( (ct = data->targets.first) ) 
+               MEM_freeN(ct);
+}      
+
+static void pycon_relink (bConstraint *con)
+{
+       bPythonConstraint *data= con->data;
+       
+       ID_NEW(data->text);
+}
+
+static void pycon_copy (bConstraint *con, bConstraint *srccon)
+{
+       bPythonConstraint *pycon = (bPythonConstraint *)con->data;
+       bPythonConstraint *opycon = (bPythonConstraint *)srccon->data;
+       
+       pycon->prop = IDP_CopyProperty(opycon->prop);
+       duplicatelist(&pycon->targets, &opycon->targets);
+}
+
+static void pycon_new_data (void *cdata)
+{
+       bPythonConstraint *data= (bPythonConstraint *)cdata;
+       
+       /* everything should be set correctly by calloc, except for the prop->type constant.*/
+       data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps");
+       data->prop->type = IDP_GROUP;
+}
+
+static void pycon_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bPythonConstraint *data= con->data;
+               
+               list->first = data->targets.first;
+               list->last = data->targets.last;
+       }
+}
+
+/* Whether this approach is maintained remains to be seen (aligorith) */
+static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       bPythonConstraint *data= con->data;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               /* special exception for curves - depsgraph issues */
+               if (ct->tar->type == OB_CURVE) {
+                       Curve *cu= ct->tar->data;
                        
-                       if (data->tar) {
-                               /* Get size property, since ob->size is only the object's own relative size, not its global one */
-                               Mat4ToSize(ownermat, size);
-                               
-                               /* Clear the object's rotation */       
-                               ownermat[0][0]=size[0];
-                               ownermat[0][1]=0;
-                               ownermat[0][2]=0;
-                               ownermat[1][0]=0;
-                               ownermat[1][1]=size[1];
-                               ownermat[1][2]=0;
-                               ownermat[2][0]=0;
-                               ownermat[2][1]=0;
-                               ownermat[2][2]=size[2];
-                               
-                               /* targetmat[2] instead of ownermat[2] is passed to vectomat
-                                * for backwards compatability it seems... (Aligorith)
-                                */
-                               VecSubf(vec, ownermat[3], targetmat[3]);
-                               vectomat(vec, targetmat[2], 
-                                               (short)data->reserved1, (short)data->reserved2, 
-                                               data->flags, totmat);
-                               
-                               Mat4CpyMat4(tmat, ownermat);
-                               Mat4MulMat34(ownermat, totmat, tmat);
-                       }
+                       /* this check is to make sure curve objects get updated on file load correctly.*/
+                       if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+                               makeDispListCurveTypes(ct->tar, 0);                             
                }
-               break;
-       case CONSTRAINT_TYPE_LOCKTRACK:
-               {
-                       bLockTrackConstraint *data;
-                       float vec[3],vec2[3];
-                       float totmat[3][3];
-                       float tmpmat[3][3];
-                       float invmat[3][3];
-                       float tmat[4][4];
-                       float mdet;
+               
+               /* firstly calculate the matrix the normal way, then let the py-function override
+                * this matrix if it needs to do so
+                */
+               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
+               BPY_pyconstraint_target(data, ct);
+       }
+       else if (ct)
+               Mat4One(ct->matrix);
+}
+
+static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bPythonConstraint *data= con->data;
+       
+/* currently removed, until I this can be re-implemented for multiple targets */
+#if 0
+       /* Firstly, run the 'driver' function which has direct access to the objects involved 
+        * Technically, this is potentially dangerous as users may abuse this and cause dependency-problems,
+        * but it also allows certain 'clever' rigging hacks to work.
+        */
+       BPY_pyconstraint_driver(data, cob, targets);
+#endif
+       
+       /* Now, run the actual 'constraint' function, which should only access the matrices */
+       BPY_pyconstraint_eval(data, cob, targets);
+}
+
+static bConstraintTypeInfo CTI_PYTHON = {
+       CONSTRAINT_TYPE_PYTHON, /* type */
+       sizeof(bPythonConstraint), /* size */
+       "Script", /* name */
+       "bPythonConstraint", /* struct name */
+       pycon_free, /* free data */
+       pycon_relink, /* relink data */
+       pycon_copy, /* copy data */
+       pycon_new_data, /* new data */
+       pycon_get_tars, /* get constraint targets */
+       NULL, /* flush constraint targets */
+       pycon_get_tarmat, /* get target matrix */
+       pycon_evaluate /* evaluate */
+};
+
+/* -------- Action Constraint ----------- */
+
+static void actcon_relink (bConstraint *con)
+{
+       bActionConstraint *data= con->data;
+       ID_NEW(data->act);
+}
+
+static void actcon_new_data (void *cdata)
+{
+       bActionConstraint *data= (bActionConstraint *)cdata;
+       
+       /* set type to 20 (Loc X), as 0 is Rot X for backwards compatability */
+       data->type = 20;
+}
+
+static void actcon_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bActionConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void actcon_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bActionConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
 
-                       data = constraint->data;                        
+static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       extern void chan_calc_mat(bPoseChannel *chan);
+       bActionConstraint *data = con->data;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               float tempmat[4][4], vec[3];
+               float s, t;
+               short axis;
+               
+               /* initialise return matrix */
+               Mat4One(ct->matrix);
+               
+               /* get the transform matrix of the target */
+               constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space);
+               
+               /* determine where in transform range target is */
+               /* data->type is mapped as follows for backwards compatability:
+                *      00,01,02        - rotation (it used to be like this)
+                *      10,11,12        - scaling
+                *      20,21,22        - location
+                */
+               if (data->type < 10) {
+                       /* extract rotation (is in whatever space target should be in) */
+                       Mat4ToEul(tempmat, vec);
+                       vec[0] *= (float)(180.0/M_PI);
+                       vec[1] *= (float)(180.0/M_PI);
+                       vec[2] *= (float)(180.0/M_PI);
+                       axis= data->type;
+               }
+               else if (data->type < 20) {
+                       /* extract scaling (is in whatever space target should be in) */
+                       Mat4ToSize(tempmat, vec);
+                       axis= data->type - 10;
+               }
+               else {
+                       /* extract location */
+                       VECCOPY(vec, tempmat[3]);
+                       axis= data->type - 20;
+               }
+               
+               /* Target defines the animation */
+               s = (vec[axis]-data->min) / (data->max-data->min);
+               CLAMP(s, 0, 1);
+               t = ( s * (data->end-data->start)) + data->start;
+               
+               /* Get the appropriate information from the action */
+               if (cob->type == CONSTRAINT_OBTYPE_BONE) {
+                       bPose *pose;
+                       bPoseChannel *pchan, *tchan;
+                       
+                       /* make a temporary pose and evaluate using that */
+                       pose = MEM_callocN(sizeof(bPose), "pose");
+                       
+                       pchan = cob->pchan;
+                       tchan= verify_pose_channel(pose, pchan->name);
+                       extract_pose_from_action(pose, data->act, t);
+                       
+                       chan_calc_mat(tchan);
+                       
+                       Mat4CpyMat4(ct->matrix, tchan->chan_mat);
                        
-                       if (data->tar) {
-                               /* Vector object -> target */
-                               VecSubf(vec, targetmat[3], ownermat[3]);
-                               switch (data->lockflag){
-                               case LOCK_X: /* LOCK X */
+                       /* Clean up */
+                       free_pose_channels(pose);
+                       MEM_freeN(pose);
+               }
+               else if (cob->type == CONSTRAINT_OBTYPE_OBJECT) {
+                       /* evaluate using workob */
+                       what_does_obaction(cob->ob, data->act, t);
+                       object_to_mat4(&workob, ct->matrix);
+               }
+               else {
+                       /* behaviour undefined... */
+                       puts("Error: unknown owner type for Action Constraint");
+               }
+       }
+}
+
+static void actcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bConstraintTarget *ct= targets->first;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               float temp[4][4];
+               
+               /* Nice and simple... we just need to multiply the matrices, as the get_target_matrix
+                * function has already taken care of everything else.
+                */
+               Mat4CpyMat4(temp, cob->matrix);
+               Mat4MulMat4(cob->matrix, ct->matrix, temp);
+       }
+}
+
+static bConstraintTypeInfo CTI_ACTION = {
+       CONSTRAINT_TYPE_ACTION, /* type */
+       sizeof(bActionConstraint), /* size */
+       "Action", /* name */
+       "bActionConstraint", /* struct name */
+       NULL, /* free data */
+       actcon_relink, /* relink data */
+       NULL, /* copy data */
+       actcon_new_data, /* new data */
+       actcon_get_tars, /* get constraint targets */
+       actcon_flush_tars, /* flush constraint targets */
+       actcon_get_tarmat, /* get target matrix */
+       actcon_evaluate /* evaluate */
+};
+
+/* --------- Locked Track ---------- */
+
+static void locktrack_new_data (void *cdata)
+{
+       bLockTrackConstraint *data= (bLockTrackConstraint *)cdata;
+       
+       data->trackflag = TRACK_Y;
+                       data->lockflag = LOCK_Z;
+}      
+
+static void locktrack_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bLockTrackConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void locktrack_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bLockTrackConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bLockTrackConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       if (VALID_CONS_TARGET(ct)) {
+               float vec[3],vec2[3];
+               float totmat[3][3];
+               float tmpmat[3][3];
+               float invmat[3][3];
+               float tmat[4][4];
+               float mdet;
+               
+               /* Vector object -> target */
+               VecSubf(vec, ct->matrix[3], cob->matrix[3]);
+               switch (data->lockflag){
+               case LOCK_X: /* LOCK X */
+               {
+                       switch (data->trackflag) {
+                               case TRACK_Y: /* LOCK X TRACK Y */
                                {
-                                       switch (data->trackflag) {
-                                               case TRACK_Y: /* LOCK X TRACK Y */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[0]);
-                                                       VecSubf(totmat[1], vec, vec2);
-                                                       Normalize(totmat[1]);
-                                                       
-                                                       /* the x axis is fixed */
-                                                       totmat[0][0] = ownermat[0][0];
-                                                       totmat[0][1] = ownermat[0][1];
-                                                       totmat[0][2] = ownermat[0][2];
-                                                       Normalize(totmat[0]);
-                                                       
-                                                       /* the z axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[2], totmat[0], totmat[1]);
-                                               }
-                                                       break;
-                                               case TRACK_Z: /* LOCK X TRACK Z */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[0]);
-                                                       VecSubf(totmat[2], vec, vec2);
-                                                       Normalize(totmat[2]);
-
-                                                       /* the x axis is fixed */
-                                                       totmat[0][0] = ownermat[0][0];
-                                                       totmat[0][1] = ownermat[0][1];
-                                                       totmat[0][2] = ownermat[0][2];
-                                                       Normalize(totmat[0]);
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[0]);
+                                       VecSubf(totmat[1], vec, vec2);
+                                       Normalize(totmat[1]);
                                        
-                                                       /* the z axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[1], totmat[2], totmat[0]);
-                                               }
-                                                       break;
-                                               case TRACK_nY: /* LOCK X TRACK -Y */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[0]);
-                                                       VecSubf(totmat[1], vec, vec2);
-                                                       Normalize(totmat[1]);
-                                                       VecMulf(totmat[1],-1);
-                                                       
-                                                       /* the x axis is fixed */
-                                                       totmat[0][0] = ownermat[0][0];
-                                                       totmat[0][1] = ownermat[0][1];
-                                                       totmat[0][2] = ownermat[0][2];
-                                                       Normalize(totmat[0]);
-                                                       
-                                                       /* the z axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[2], totmat[0], totmat[1]);
-                                               }
-                                                       break;
-                                               case TRACK_nZ: /* LOCK X TRACK -Z */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[0]);
-                                                       VecSubf(totmat[2], vec, vec2);
-                                                       Normalize(totmat[2]);
-                                                       VecMulf(totmat[2],-1);
-                                                               
-                                                       /* the x axis is fixed */
-                                                       totmat[0][0] = ownermat[0][0];
-                                                       totmat[0][1] = ownermat[0][1];
-                                                       totmat[0][2] = ownermat[0][2];
-                                                       Normalize(totmat[0]);
-                                                               
-                                                       /* the z axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[1], totmat[2], totmat[0]);
-                                               }
-                                                       break;
-                                               default:
-                                               {
-                                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
-                                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
-                                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
-                                               }
-                                                       break;
-                                       }
+                                       /* the x axis is fixed */
+                                       totmat[0][0] = cob->matrix[0][0];
+                                       totmat[0][1] = cob->matrix[0][1];
+                                       totmat[0][2] = cob->matrix[0][2];
+                                       Normalize(totmat[0]);
+                                       
+                                       /* the z axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[2], totmat[0], totmat[1]);
                                }
                                        break;
-                               case LOCK_Y: /* LOCK Y */
+                               case TRACK_Z: /* LOCK X TRACK Z */
                                {
-                                       switch (data->trackflag) {
-                                               case TRACK_X: /* LOCK Y TRACK X */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[1]);
-                                                       VecSubf(totmat[0], vec, vec2);
-                                                       Normalize(totmat[0]);
-                                                       
-                                                       /* the y axis is fixed */
-                                                       totmat[1][0] = ownermat[1][0];
-                                                       totmat[1][1] = ownermat[1][1];
-                                                       totmat[1][2] = ownermat[1][2];
-                                                       Normalize(totmat[1]);
-                                                       
-                                                       /* the z axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[2], totmat[0], totmat[1]);
-                                               }
-                                                       break;
-                                               case TRACK_Z: /* LOCK Y TRACK Z */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[1]);
-                                                       VecSubf(totmat[2], vec, vec2);
-                                                       Normalize(totmat[2]);
-
-                                                       /* the y axis is fixed */
-                                                       totmat[1][0] = ownermat[1][0];
-                                                       totmat[1][1] = ownermat[1][1];
-                                                       totmat[1][2] = ownermat[1][2];
-                                                       Normalize(totmat[1]);
-                                                       
-                                                       /* the z axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[0], totmat[1], totmat[2]);
-                                               }
-                                                       break;
-                                               case TRACK_nX: /* LOCK Y TRACK -X */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[1]);
-                                                       VecSubf(totmat[0], vec, vec2);
-                                                       Normalize(totmat[0]);
-                                                       VecMulf(totmat[0],-1);
-                                                       
-                                                       /* the y axis is fixed */
-                                                       totmat[1][0] = ownermat[1][0];
-                                                       totmat[1][1] = ownermat[1][1];
-                                                       totmat[1][2] = ownermat[1][2];
-                                                       Normalize(totmat[1]);
-                                                       
-                                                       /* the z axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[2], totmat[0], totmat[1]);
-                                               }
-                                                       break;
-                                               case TRACK_nZ: /* LOCK Y TRACK -Z */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[1]);
-                                                       VecSubf(totmat[2], vec, vec2);
-                                                       Normalize(totmat[2]);
-                                                       VecMulf(totmat[2],-1);
-                                                       
-                                                       /* the y axis is fixed */
-                                                       totmat[1][0] = ownermat[1][0];
-                                                       totmat[1][1] = ownermat[1][1];
-                                                       totmat[1][2] = ownermat[1][2];
-                                                       Normalize(totmat[1]);
-                                                       
-                                                       /* the z axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[0], totmat[1], totmat[2]);
-                                               }
-                                                       break;
-                                               default:
-                                               {
-                                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
-                                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
-                                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
-                                               }
-                                                       break;
-                                       }
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[0]);
+                                       VecSubf(totmat[2], vec, vec2);
+                                       Normalize(totmat[2]);
+
+                                       /* the x axis is fixed */
+                                       totmat[0][0] = cob->matrix[0][0];
+                                       totmat[0][1] = cob->matrix[0][1];
+                                       totmat[0][2] = cob->matrix[0][2];
+                                       Normalize(totmat[0]);
+                       
+                                       /* the z axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[1], totmat[2], totmat[0]);
                                }
                                        break;
-                               case LOCK_Z: /* LOCK Z */
+                               case TRACK_nY: /* LOCK X TRACK -Y */
                                {
-                                       switch (data->trackflag) {
-                                               case TRACK_X: /* LOCK Z TRACK X */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[2]);
-                                                       VecSubf(totmat[0], vec, vec2);
-                                                       Normalize(totmat[0]);
-                                                       
-                                                       /* the z axis is fixed */
-                                                       totmat[2][0] = ownermat[2][0];
-                                                       totmat[2][1] = ownermat[2][1];
-                                                       totmat[2][2] = ownermat[2][2];
-                                                       Normalize(totmat[2]);
-                                                       
-                                                       /* the x axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[1], totmat[2], totmat[0]);
-                                               }
-                                                       break;
-                                               case TRACK_Y: /* LOCK Z TRACK Y */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[2]);
-                                                       VecSubf(totmat[1], vec, vec2);
-                                                       Normalize(totmat[1]);
-                                                       
-                                                       /* the z axis is fixed */
-                                                       totmat[2][0] = ownermat[2][0];
-                                                       totmat[2][1] = ownermat[2][1];
-                                                       totmat[2][2] = ownermat[2][2];
-                                                       Normalize(totmat[2]);
-                                                               
-                                                       /* the x axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[0], totmat[1], totmat[2]);
-                                               }
-                                                       break;
-                                               case TRACK_nX: /* LOCK Z TRACK -X */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[2]);
-                                                       VecSubf(totmat[0], vec, vec2);
-                                                       Normalize(totmat[0]);
-                                                       VecMulf(totmat[0],-1);
-                                                       
-                                                       /* the z axis is fixed */
-                                                       totmat[2][0] = ownermat[2][0];
-                                                       totmat[2][1] = ownermat[2][1];
-                                                       totmat[2][2] = ownermat[2][2];
-                                                       Normalize(totmat[2]);
-                                                       
-                                                       /* the x axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[1], totmat[2], totmat[0]);
-                                               }
-                                                       break;
-                                               case TRACK_nY: /* LOCK Z TRACK -Y */
-                                               {
-                                                       /* Projection of Vector on the plane */
-                                                       Projf(vec2, vec, ownermat[2]);
-                                                       VecSubf(totmat[1], vec, vec2);
-                                                       Normalize(totmat[1]);
-                                                       VecMulf(totmat[1],-1);
-                                                       
-                                                       /* the z axis is fixed */
-                                                       totmat[2][0] = ownermat[2][0];
-                                                       totmat[2][1] = ownermat[2][1];
-                                                       totmat[2][2] = ownermat[2][2];
-                                                       Normalize(totmat[2]);
-                                                               
-                                                       /* the x axis gets mapped onto a third orthogonal vector */
-                                                       Crossf(totmat[0], totmat[1], totmat[2]);
-                                               }
-                                                       break;
-                                               default:
-                                               {
-                                                               totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
-                                                               totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
-                                                               totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
-                                               }
-                                                       break;
-                                       }
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[0]);
+                                       VecSubf(totmat[1], vec, vec2);
+                                       Normalize(totmat[1]);
+                                       VecMulf(totmat[1],-1);
+                                       
+                                       /* the x axis is fixed */
+                                       totmat[0][0] = cob->matrix[0][0];
+                                       totmat[0][1] = cob->matrix[0][1];
+                                       totmat[0][2] = cob->matrix[0][2];
+                                       Normalize(totmat[0]);
+                                       
+                                       /* the z axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[2], totmat[0], totmat[1]);
+                               }
+                                       break;
+                               case TRACK_nZ: /* LOCK X TRACK -Z */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[0]);
+                                       VecSubf(totmat[2], vec, vec2);
+                                       Normalize(totmat[2]);
+                                       VecMulf(totmat[2],-1);
+                                               
+                                       /* the x axis is fixed */
+                                       totmat[0][0] = cob->matrix[0][0];
+                                       totmat[0][1] = cob->matrix[0][1];
+                                       totmat[0][2] = cob->matrix[0][2];
+                                       Normalize(totmat[0]);
+                                               
+                                       /* the z axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[1], totmat[2], totmat[0]);
+                               }
+                                       break;
+                               default:
+                               {
+                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                               }
+                                       break;
+                       }
+               }
+                       break;
+               case LOCK_Y: /* LOCK Y */
+               {
+                       switch (data->trackflag) {
+                               case TRACK_X: /* LOCK Y TRACK X */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[1]);
+                                       VecSubf(totmat[0], vec, vec2);
+                                       Normalize(totmat[0]);
+                                       
+                                       /* the y axis is fixed */
+                                       totmat[1][0] = cob->matrix[1][0];
+                                       totmat[1][1] = cob->matrix[1][1];
+                                       totmat[1][2] = cob->matrix[1][2];
+                                       Normalize(totmat[1]);
+                                       
+                                       /* the z axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[2], totmat[0], totmat[1]);
+                               }
+                                       break;
+                               case TRACK_Z: /* LOCK Y TRACK Z */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[1]);
+                                       VecSubf(totmat[2], vec, vec2);
+                                       Normalize(totmat[2]);
+
+                                       /* the y axis is fixed */
+                                       totmat[1][0] = cob->matrix[1][0];
+                                       totmat[1][1] = cob->matrix[1][1];
+                                       totmat[1][2] = cob->matrix[1][2];
+                                       Normalize(totmat[1]);
+                                       
+                                       /* the z axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[0], totmat[1], totmat[2]);
+                               }
+                                       break;
+                               case TRACK_nX: /* LOCK Y TRACK -X */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[1]);
+                                       VecSubf(totmat[0], vec, vec2);
+                                       Normalize(totmat[0]);
+                                       VecMulf(totmat[0],-1);
+                                       
+                                       /* the y axis is fixed */
+                                       totmat[1][0] = cob->matrix[1][0];
+                                       totmat[1][1] = cob->matrix[1][1];
+                                       totmat[1][2] = cob->matrix[1][2];
+                                       Normalize(totmat[1]);
+                                       
+                                       /* the z axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[2], totmat[0], totmat[1]);
+                               }
+                                       break;
+                               case TRACK_nZ: /* LOCK Y TRACK -Z */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[1]);
+                                       VecSubf(totmat[2], vec, vec2);
+                                       Normalize(totmat[2]);
+                                       VecMulf(totmat[2],-1);
+                                       
+                                       /* the y axis is fixed */
+                                       totmat[1][0] = cob->matrix[1][0];
+                                       totmat[1][1] = cob->matrix[1][1];
+                                       totmat[1][2] = cob->matrix[1][2];
+                                       Normalize(totmat[1]);
+                                       
+                                       /* the z axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[0], totmat[1], totmat[2]);
+                               }
+                                       break;
+                               default:
+                               {
+                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                               }
+                                       break;
+                       }
+               }
+                       break;
+               case LOCK_Z: /* LOCK Z */
+               {
+                       switch (data->trackflag) {
+                               case TRACK_X: /* LOCK Z TRACK X */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[2]);
+                                       VecSubf(totmat[0], vec, vec2);
+                                       Normalize(totmat[0]);
+                                       
+                                       /* the z axis is fixed */
+                                       totmat[2][0] = cob->matrix[2][0];
+                                       totmat[2][1] = cob->matrix[2][1];
+                                       totmat[2][2] = cob->matrix[2][2];
+                                       Normalize(totmat[2]);
+                                       
+                                       /* the x axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[1], totmat[2], totmat[0]);
+                               }
+                                       break;
+                               case TRACK_Y: /* LOCK Z TRACK Y */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[2]);
+                                       VecSubf(totmat[1], vec, vec2);
+                                       Normalize(totmat[1]);
+                                       
+                                       /* the z axis is fixed */
+                                       totmat[2][0] = cob->matrix[2][0];
+                                       totmat[2][1] = cob->matrix[2][1];
+                                       totmat[2][2] = cob->matrix[2][2];
+                                       Normalize(totmat[2]);
+                                               
+                                       /* the x axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[0], totmat[1], totmat[2]);
+                               }
+                                       break;
+                               case TRACK_nX: /* LOCK Z TRACK -X */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[2]);
+                                       VecSubf(totmat[0], vec, vec2);
+                                       Normalize(totmat[0]);
+                                       VecMulf(totmat[0],-1);
+                                       
+                                       /* the z axis is fixed */
+                                       totmat[2][0] = cob->matrix[2][0];
+                                       totmat[2][1] = cob->matrix[2][1];
+                                       totmat[2][2] = cob->matrix[2][2];
+                                       Normalize(totmat[2]);
+                                       
+                                       /* the x axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[1], totmat[2], totmat[0]);
+                               }
+                                       break;
+                               case TRACK_nY: /* LOCK Z TRACK -Y */
+                               {
+                                       /* Projection of Vector on the plane */
+                                       Projf(vec2, vec, cob->matrix[2]);
+                                       VecSubf(totmat[1], vec, vec2);
+                                       Normalize(totmat[1]);
+                                       VecMulf(totmat[1],-1);
+                                       
+                                       /* the z axis is fixed */
+                                       totmat[2][0] = cob->matrix[2][0];
+                                       totmat[2][1] = cob->matrix[2][1];
+                                       totmat[2][2] = cob->matrix[2][2];
+                                       Normalize(totmat[2]);
+                                               
+                                       /* the x axis gets mapped onto a third orthogonal vector */
+                                       Crossf(totmat[0], totmat[1], totmat[2]);
                                }
                                        break;
                                default:
-                                       {
+                               {
                                                totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
                                                totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
                                                totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                               }
+                                       break;
+                       }
+               }
+                       break;
+               default:
+                       {
+                               totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                               totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                               totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                       }
+                       break;
+               }
+               /* Block to keep matrix heading */
+               tmpmat[0][0] = cob->matrix[0][0];tmpmat[0][1] = cob->matrix[0][1];tmpmat[0][2] = cob->matrix[0][2];
+               tmpmat[1][0] = cob->matrix[1][0];tmpmat[1][1] = cob->matrix[1][1];tmpmat[1][2] = cob->matrix[1][2];
+               tmpmat[2][0] = cob->matrix[2][0];tmpmat[2][1] = cob->matrix[2][1];tmpmat[2][2] = cob->matrix[2][2];
+               Normalize(tmpmat[0]);
+               Normalize(tmpmat[1]);
+               Normalize(tmpmat[2]);
+               Mat3Inv(invmat, tmpmat);
+               Mat3MulMat3(tmpmat, totmat, invmat);
+               totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
+               totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
+               totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
+               
+               Mat4CpyMat4(tmat, cob->matrix);
+               
+               mdet = Det3x3(  totmat[0][0],totmat[0][1],totmat[0][2],
+                                               totmat[1][0],totmat[1][1],totmat[1][2],
+                                               totmat[2][0],totmat[2][1],totmat[2][2]);
+               if (mdet==0) {
+                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+               }
+               
+               /* apply out transformaton to the object */
+               Mat4MulMat34(cob->matrix, totmat, tmat);
+       }
+}
+
+static bConstraintTypeInfo CTI_LOCKTRACK = {
+       CONSTRAINT_TYPE_LOCKTRACK, /* type */
+       sizeof(bLockTrackConstraint), /* size */
+       "Locked Track", /* name */
+       "bLockTrackConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       locktrack_new_data, /* new data */
+       locktrack_get_tars, /* get constraint targets */
+       locktrack_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get target matrix */
+       locktrack_evaluate /* evaluate */
+};
+
+/* ---------- Stretch To ------------ */
+
+static void stretchto_new_data (void *cdata)
+{
+       bStretchToConstraint *data= (bStretchToConstraint *)cdata;
+       
+       data->volmode = 0;
+       data->plane = 0;
+       data->orglength = 0.0; 
+       data->bulge = 1.0;
+}
+
+static void stretchto_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bStretchToConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void stretchto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bStretchToConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bStretchToConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target */
+       if (VALID_CONS_TARGET(ct)) {
+               float size[3], scale[3], vec[3], xx[3], zz[3], orth[3];
+               float totmat[3][3];
+               float tmat[4][4];
+               float dist;
+               
+               /* store scaling before destroying obmat */
+               Mat4ToSize(cob->matrix, size);
+               
+               /* store X orientation before destroying obmat */
+               xx[0] = cob->matrix[0][0];
+               xx[1] = cob->matrix[0][1];
+               xx[2] = cob->matrix[0][2];
+               Normalize(xx);
+               
+               /* store Z orientation before destroying obmat */
+               zz[0] = cob->matrix[2][0];
+               zz[1] = cob->matrix[2][1];
+               zz[2] = cob->matrix[2][2];
+               Normalize(zz);
+               
+               VecSubf(vec, cob->matrix[3], ct->matrix[3]);
+               vec[0] /= size[0];
+               vec[1] /= size[1];
+               vec[2] /= size[2];
+               
+               dist = Normalize(vec);
+               //dist = VecLenf( ob->obmat[3], targetmat[3]);
+               
+               /* data->orglength==0 occurs on first run, and after 'R' button is clicked */
+               if (data->orglength == 0)  
+                       data->orglength = dist;
+               if (data->bulge == 0) 
+                       data->bulge = 1.0;
+               
+               scale[1] = dist/data->orglength;
+               switch (data->volmode) {
+               /* volume preserving scaling */
+               case VOLUME_XZ :
+                       scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
+                       scale[2] = scale[0];
+                       break;
+               case VOLUME_X:
+                       scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
+                       scale[2] = 1.0;
+                       break;
+               case VOLUME_Z:
+                       scale[0] = 1.0;
+                       scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
+                       break;
+                       /* don't care for volume */
+               case NO_VOLUME:
+                       scale[0] = 1.0;
+                       scale[2] = 1.0;
+                       break;
+               default: /* should not happen, but in case*/
+                       return;    
+               } /* switch (data->volmode) */
+
+               /* Clear the object's rotation and scale */
+               cob->matrix[0][0]=size[0]*scale[0];
+               cob->matrix[0][1]=0;
+               cob->matrix[0][2]=0;
+               cob->matrix[1][0]=0;
+               cob->matrix[1][1]=size[1]*scale[1];
+               cob->matrix[1][2]=0;
+               cob->matrix[2][0]=0;
+               cob->matrix[2][1]=0;
+               cob->matrix[2][2]=size[2]*scale[2];
+               
+               VecSubf(vec, cob->matrix[3], ct->matrix[3]);
+               Normalize(vec);
+               
+               /* new Y aligns  object target connection*/
+               totmat[1][0] = -vec[0];
+               totmat[1][1] = -vec[1];
+               totmat[1][2] = -vec[2];
+               switch (data->plane) {
+               case PLANE_X:
+                       /* build new Z vector */
+                       /* othogonal to "new Y" "old X! plane */
+                       Crossf(orth, vec, xx);
+                       Normalize(orth);
+                       
+                       /* new Z*/
+                       totmat[2][0] = orth[0];
+                       totmat[2][1] = orth[1];
+                       totmat[2][2] = orth[2];
+                       
+                       /* we decided to keep X plane*/
+                       Crossf(xx, orth, vec);
+                       Normalize(xx);
+                       totmat[0][0] = xx[0];
+                       totmat[0][1] = xx[1];
+                       totmat[0][2] = xx[2];
+                       break;
+               case PLANE_Z:
+                       /* build new X vector */
+                       /* othogonal to "new Y" "old Z! plane */
+                       Crossf(orth, vec, zz);
+                       Normalize(orth);
+                       
+                       /* new X */
+                       totmat[0][0] = -orth[0];
+                       totmat[0][1] = -orth[1];
+                       totmat[0][2] = -orth[2];
+                       
+                       /* we decided to keep Z */
+                       Crossf(zz, orth, vec);
+                       Normalize(zz);
+                       totmat[2][0] = zz[0];
+                       totmat[2][1] = zz[1];
+                       totmat[2][2] = zz[2];
+                       break;
+               } /* switch (data->plane) */
+               
+               Mat4CpyMat4(tmat, cob->matrix);
+               Mat4MulMat34(cob->matrix, totmat, tmat);
+       }
+}
+
+static bConstraintTypeInfo CTI_STRETCHTO = {
+       CONSTRAINT_TYPE_STRETCHTO, /* type */
+       sizeof(bStretchToConstraint), /* size */
+       "Stretch To", /* name */
+       "bStretchToConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       stretchto_new_data, /* new data */
+       stretchto_get_tars, /* get constraint targets */
+       stretchto_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get target matrix */
+       stretchto_evaluate /* evaluate */
+};
+
+/* ---------- Floor ------------ */
+
+static void minmax_new_data (void *cdata)
+{
+       bMinMaxConstraint *data= (bMinMaxConstraint *)cdata;
+       
+       data->minmaxflag = TRACK_Z;
+       data->offset = 0.0f;
+       data->cache[0] = data->cache[1] = data->cache[2] = 0.0f;
+       data->flag = 0;
+}
+
+static void minmax_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bMinMaxConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void minmax_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bMinMaxConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void minmax_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bMinMaxConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target */
+       if (VALID_CONS_TARGET(ct)) {
+               float obmat[4][4], imat[4][4], tarmat[4][4], tmat[4][4];
+               float val1, val2;
+               int index;
+               
+               Mat4CpyMat4(obmat, cob->matrix);
+               Mat4CpyMat4(tarmat, ct->matrix);
+               
+               if (data->flag & MINMAX_USEROT) {
+                       /* take rotation of target into account by doing the transaction in target's localspace */
+                       Mat4Invert(imat, tarmat);
+                       Mat4MulMat4(tmat, obmat, imat);
+                       Mat4CpyMat4(obmat, tmat);
+                       Mat4One(tarmat);
+               }
+               
+               switch (data->minmaxflag) {
+               case TRACK_Z:
+                       val1 = tarmat[3][2];
+                       val2 = obmat[3][2]-data->offset;
+                       index = 2;
+                       break;
+               case TRACK_Y:
+                       val1 = tarmat[3][1];
+                       val2 = obmat[3][1]-data->offset;
+                       index = 1;
+                       break;
+               case TRACK_X:
+                       val1 = tarmat[3][0];
+                       val2 = obmat[3][0]-data->offset;
+                       index = 0;
+                       break;
+               case TRACK_nZ:
+                       val2 = tarmat[3][2];
+                       val1 = obmat[3][2]-data->offset;
+                       index = 2;
+                       break;
+               case TRACK_nY:
+                       val2 = tarmat[3][1];
+                       val1 = obmat[3][1]-data->offset;
+                       index = 1;
+                       break;
+               case TRACK_nX:
+                       val2 = tarmat[3][0];
+                       val1 = obmat[3][0]-data->offset;
+                       index = 0;
+                       break;
+               default:
+                       return;
+               }
+               
+               if (val1 > val2) {
+                       obmat[3][index] = tarmat[3][index] + data->offset;
+                       if (data->flag & MINMAX_STICKY) {
+                               if (data->flag & MINMAX_STUCK) {
+                                       VECCOPY(obmat[3], data->cache);
+                               } 
+                               else {
+                                       VECCOPY(data->cache, obmat[3]);
+                                       data->flag |= MINMAX_STUCK;
+                               }
+                       }
+                       if (data->flag & MINMAX_USEROT) {
+                               /* get out of localspace */
+                               Mat4MulMat4(tmat, obmat, ct->matrix);
+                               Mat4CpyMat4(cob->matrix, tmat);
+                       } 
+                       else {                  
+                               VECCOPY(cob->matrix[3], obmat[3]);
+                       }
+               } 
+               else {
+                       data->flag &= ~MINMAX_STUCK;
+               }
+       }
+}
+
+static bConstraintTypeInfo CTI_MINMAX = {
+       CONSTRAINT_TYPE_MINMAX, /* type */
+       sizeof(bMinMaxConstraint), /* size */
+       "Floor", /* name */
+       "bMinMaxConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       minmax_new_data, /* new data */
+       minmax_get_tars, /* get constraint targets */
+       minmax_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get target matrix */
+       minmax_evaluate /* evaluate */
+};
+
+/* ------- RigidBody Joint ---------- */
+
+static void rbj_new_data (void *cdata)
+{
+       bRigidBodyJointConstraint *data= (bRigidBodyJointConstraint *)cdata;
+       
+       // removed code which set target of this constraint  
+    data->type=1;
+}
+
+static void rbj_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bRigidBodyJointConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints without subtargets */
+               SINGLETARGETNS_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void rbj_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bRigidBodyJointConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static bConstraintTypeInfo CTI_RIGIDBODYJOINT = {
+       CONSTRAINT_TYPE_RIGIDBODYJOINT, /* type */
+       sizeof(bRigidBodyJointConstraint), /* size */
+       "RigidBody Joint", /* name */
+       "bRigidBodyJointConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       rbj_new_data, /* new data */
+       rbj_get_tars, /* get constraint targets */
+       rbj_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get target matrix */
+       NULL /* evaluate - this is not solved here... is just an interface for game-engine */
+};
+
+/* -------- Clamp To ---------- */
+
+static void clampto_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bClampToConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints without subtargets */
+               SINGLETARGETNS_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void clampto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bClampToConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void clampto_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       if (VALID_CONS_TARGET(ct)) {
+               Curve *cu= ct->tar->data;
+               
+               /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
+                *              currently for paths to work it needs to go through the bevlist/displist system (ton) 
+                */
+               
+               /* only happens on reload file, but violates depsgraph still... fix! */
+               if (cu->path==NULL || cu->path->data==NULL) 
+                       makeDispListCurveTypes(ct->tar, 0);
+       }
+       
+       /* technically, this isn't really needed for evaluation, but we don't know what else
+        * might end up calling this...
+        */
+       if (ct)
+               Mat4One(ct->matrix);
+}
+
+static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bClampToConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target and it is a curve */
+       if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) {
+               Curve *cu= data->tar->data;
+               float obmat[4][4], targetMatrix[4][4], ownLoc[3];
+               float curveMin[3], curveMax[3];
+               
+               Mat4CpyMat4(obmat, cob->matrix);
+               Mat4One(targetMatrix);
+               VECCOPY(ownLoc, obmat[3]);
+               
+               INIT_MINMAX(curveMin, curveMax)
+               minmax_object(ct->tar, curveMin, curveMax);
+               
+               /* get targetmatrix */
+               if (cu->path && cu->path->data) {
+                       float vec[4], dir[3], totmat[4][4];
+                       float curvetime;
+                       short clamp_axis;
+                       
+                       /* find best position on curve */
+                       /* 1. determine which axis to sample on? */
+                       if (data->flag == CLAMPTO_AUTO) {
+                               float size[3];
+                               VecSubf(size, curveMax, curveMin);
+                               
+                               /* find axis along which the bounding box has the greatest
+                                * extent. Otherwise, default to the x-axis, as that is quite
+                                * frequently used.
+                                */
+                               if ((size[2]>size[0]) && (size[2]>size[1]))
+                                       clamp_axis= CLAMPTO_Z - 1;
+                               else if ((size[1]>size[0]) && (size[1]>size[2]))
+                                       clamp_axis= CLAMPTO_Y - 1;
+                               else
+                                       clamp_axis = CLAMPTO_X - 1;
+                       }
+                       else 
+                               clamp_axis= data->flag - 1;
+                               
+                       /* 2. determine position relative to curve on a 0-1 scale based on bounding box */
+                       if (data->flag2 & CLAMPTO_CYCLIC) {
+                               /* cyclic, so offset within relative bounding box is used */
+                               float len= (curveMax[clamp_axis] - curveMin[clamp_axis]);
+                               float offset;
+                               
+                               /* find bounding-box range where target is located */
+                               if (ownLoc[clamp_axis] < curveMin[clamp_axis]) {
+                                       /* bounding-box range is before */
+                                       offset= curveMin[clamp_axis];
+                                       
+                                       while (ownLoc[clamp_axis] < offset)
+                                               offset -= len;
+                                       
+                                       /* now, we calculate as per normal, except using offset instead of curveMin[clamp_axis] */
+                                       curvetime = (ownLoc[clamp_axis] - offset) / (len);
+                               }
+                               else if (ownLoc[clamp_axis] > curveMax[clamp_axis]) {
+                                       /* bounding-box range is after */
+                                       offset= curveMax[clamp_axis];
+                                       
+                                       while (ownLoc[clamp_axis] > offset) {
+                                               if ((offset + len) > ownLoc[clamp_axis])
+                                                       break;
+                                               else
+                                                       offset += len;
                                        }
-                                       break;
+                                       
+                                       /* now, we calculate as per normal, except using offset instead of curveMax[clamp_axis] */
+                                       curvetime = (ownLoc[clamp_axis] - offset) / (len);
                                }
-                               /* Block to keep matrix heading */
-                               tmpmat[0][0] = ownermat[0][0];tmpmat[0][1] = ownermat[0][1];tmpmat[0][2] = ownermat[0][2];
-                               tmpmat[1][0] = ownermat[1][0];tmpmat[1][1] = ownermat[1][1];tmpmat[1][2] = ownermat[1][2];
-                               tmpmat[2][0] = ownermat[2][0];tmpmat[2][1] = ownermat[2][1];tmpmat[2][2] = ownermat[2][2];
-                               Normalize(tmpmat[0]);
-                               Normalize(tmpmat[1]);
-                               Normalize(tmpmat[2]);
-                               Mat3Inv(invmat,tmpmat);
-                               Mat3MulMat3(tmpmat, totmat, invmat);
-                               totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
-                               totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
-                               totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
-                               
-                               Mat4CpyMat4(tmat, ownermat);
-                               
-                               mdet = Det3x3(  totmat[0][0],totmat[0][1],totmat[0][2],
-                                                               totmat[1][0],totmat[1][1],totmat[1][2],
-                                                               totmat[2][0],totmat[2][1],totmat[2][2]);
-                               if (mdet==0) {
-                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
-                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
-                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                               else {
+                                       /* as the location falls within bounds, just calculate */
+                                       curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (len);
                                }
-                               
-                               /* apply out transformaton to the object */
-                               Mat4MulMat34(ownermat, totmat, tmat);
                        }
-               }
-               break;
-       case CONSTRAINT_TYPE_FOLLOWPATH:
-               {
-                       bFollowPathConstraint *data;
-                       float obmat[4][4];
-                       float size[3], obsize[3];
-                       
-                       data = constraint->data;                        
+                       else {
+                               /* no cyclic, so position is clamped to within the bounding box */
+                               if (ownLoc[clamp_axis] <= curveMin[clamp_axis])
+                                       curvetime = 0.0;
+                               else if (ownLoc[clamp_axis] >= curveMax[clamp_axis])
+                                       curvetime = 1.0;
+                               else
+                                       curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (curveMax[clamp_axis] - curveMin[clamp_axis]);
+                       }
                        
-                       if (data->tar) {
-                               /* get Object local transform (loc/rot/size) to determine transformation from path */
-                               //object_to_mat4(ob, obmat);
-                               Mat4CpyMat4(obmat, ownermat); // FIXME!!!
-                               
-                               /* get scaling of object before applying constraint */
-                               Mat4ToSize(ownermat, size);
-                               
-                               /* apply targetmat - containing location on path, and rotation */
-                               Mat4MulSerie(ownermat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
+                       /* 3. position on curve */
+                       if (where_on_path(ct->tar, curvetime, vec, dir) ) {
+                               Mat4One(totmat);
+                               VECCOPY(totmat[3], vec);
                                
-                               /* un-apply scaling caused by path */
-                               Mat4ToSize(ownermat, obsize);
-                               if (obsize[0] != 0)
-                                       VecMulf(ownermat[0], size[0] / obsize[0]);
-                               if (obsize[1] != 0)
-                                       VecMulf(ownermat[1], size[1] / obsize[1]);
-                               if (obsize[2] != 0)
-                                       VecMulf(ownermat[2], size[2] / obsize[2]);
+                               Mat4MulSerie(targetMatrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
                        }
                }
-               break;
-       case CONSTRAINT_TYPE_STRETCHTO:
-        {
-            bStretchToConstraint *data;
-            float size[3],scale[3],vec[3],xx[3],zz[3],orth[3];
-            float totmat[3][3];
-            float tmat[4][4];
-            float dist;
-                       
-            data = constraint->data;            
-            Mat4ToSize (ownermat, size);
-            
-            if (data->tar) {
-                /* store X orientation before destroying obmat */
-                xx[0] = ownermat[0][0];
-                xx[1] = ownermat[0][1];
-                xx[2] = ownermat[0][2];
-                Normalize(xx);
-                               
-                /* store Z orientation before destroying obmat */
-                zz[0] = ownermat[2][0];
-                zz[1] = ownermat[2][1];
-                zz[2] = ownermat[2][2];
-                Normalize(zz);
-                               
-                               VecSubf(vec, ownermat[3], targetmat[3]);
-                               vec[0] /= size[0];
-                               vec[1] /= size[1];
-                               vec[2] /= size[2];
-
-                               dist = Normalize(vec);
-                //dist = VecLenf( ob->obmat[3], targetmat[3]);
-
-                if (data->orglength == 0)  data->orglength = dist;
-                if (data->bulge == 0) data->bulge = 1.0;
-
-                scale[1] = dist/data->orglength;
-                switch (data->volmode) {
-                /* volume preserving scaling */
-                case VOLUME_XZ :
-                    scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
-                    scale[2] = scale[0];
-                    break;
-                case VOLUME_X:
-                    scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
-                    scale[2] = 1.0;
-                    break;
-                case VOLUME_Z:
-                    scale[0] = 1.0;
-                    scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
-                    break;
-                    /* don't care for volume */
-                case NO_VOLUME:
-                    scale[0] = 1.0;
-                    scale[2] = 1.0;
-                    break;
-                default: /* should not happen, but in case*/
-                    return;    
-                } /* switch (data->volmode) */
-
-                /* Clear the object's rotation and scale */
-                               ownermat[0][0]=size[0]*scale[0];
-                               ownermat[0][1]=0;
-                               ownermat[0][2]=0;
-                               ownermat[1][0]=0;
-                               ownermat[1][1]=size[1]*scale[1];
-                               ownermat[1][2]=0;
-                               ownermat[2][0]=0;
-                               ownermat[2][1]=0;
-                               ownermat[2][2]=size[2]*scale[2];
-                
-                               VecSubf(vec, ownermat[3], targetmat[3]);
-                               Normalize(vec);
-                               
-                /* new Y aligns  object target connection*/
-                totmat[1][0] = -vec[0];
-                totmat[1][1] = -vec[1];
-                totmat[1][2] = -vec[2];
-                switch (data->plane) {
-                case PLANE_X:
-                    /* build new Z vector */
-                    /* othogonal to "new Y" "old X! plane */
-                    Crossf(orth, vec, xx);
-                    Normalize(orth);
-                    
-                    /* new Z*/
-                    totmat[2][0] = orth[0];
-                    totmat[2][1] = orth[1];
-                    totmat[2][2] = orth[2];
-                    
-                    /* we decided to keep X plane*/
-                    Crossf(xx, orth, vec);
-                    Normalize(xx);
-                    totmat[0][0] = xx[0];
-                    totmat[0][1] = xx[1];
-                    totmat[0][2] = xx[2];
-                    break;
-                case PLANE_Z:
-                    /* build new X vector */
-                    /* othogonal to "new Y" "old Z! plane */
-                    Crossf(orth, vec, zz);
-                    Normalize(orth);
-                    
-                    /* new X */
-                    totmat[0][0] = -orth[0];
-                    totmat[0][1] = -orth[1];
-                    totmat[0][2] = -orth[2];
-                    
-                    /* we decided to keep Z */
-                    Crossf(zz, orth, vec);
-                    Normalize(zz);
-                    totmat[2][0] = zz[0];
-                    totmat[2][1] = zz[1];
-                    totmat[2][2] = zz[2];
-                    break;
-                } /* switch (data->plane) */
-                
-                Mat4CpyMat4(tmat, ownermat);
-                               
-                Mat4MulMat34(ownermat, totmat, tmat);
-            }
-        }
-        break;
-       case CONSTRAINT_TYPE_LOCLIMIT:
-               {
-                       bLocLimitConstraint *data;
+               
+               /* obtain final object position */
+               VECCOPY(cob->matrix[3], targetMatrix[3]);
+       }
+}
 
-                       data = constraint->data;
-                       
-                       if (data->flag & LIMIT_XMIN) {
-                               if(ownermat[3][0] < data->xmin)
-                                       ownermat[3][0] = data->xmin;
-                       }
-                       if (data->flag & LIMIT_XMAX) {
-                               if (ownermat[3][0] > data->xmax)
-                                       ownermat[3][0] = data->xmax;
-                       }
-                       if (data->flag & LIMIT_YMIN) {
-                               if(ownermat[3][1] < data->ymin)
-                                       ownermat[3][1] = data->ymin;
-                       }
-                       if (data->flag & LIMIT_YMAX) {
-                               if (ownermat[3][1] > data->ymax)
-                                       ownermat[3][1] = data->ymax;
-                       }
-                       if (data->flag & LIMIT_ZMIN) {
-                               if(ownermat[3][2] < data->zmin) 
-                                       ownermat[3][2] = data->zmin;
-                       }
-                       if (data->flag & LIMIT_ZMAX) {
-                               if (ownermat[3][2] > data->zmax)
-                                       ownermat[3][2] = data->zmax;
-                       }
+static bConstraintTypeInfo CTI_CLAMPTO = {
+       CONSTRAINT_TYPE_CLAMPTO, /* type */
+       sizeof(bClampToConstraint), /* size */
+       "Clamp To", /* name */
+       "bClampToConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       NULL, /* new data */
+       clampto_get_tars, /* get constraint targets */
+       clampto_flush_tars, /* flush constraint targets */
+       clampto_get_tarmat, /* get target matrix */
+       clampto_evaluate /* evaluate */
+};
+
+/* ---------- Transform Constraint ----------- */
+
+static void transform_new_data (void *cdata)
+{
+       bTransformConstraint *data= (bTransformConstraint *)cdata;
+       
+       data->map[0]= 0;
+       data->map[1]= 1;
+       data->map[2]= 2;
+}
+
+static void transform_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bTransformConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data, ct, list)
+       }
+}
+
+static void transform_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bTransformConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+       }
+}
+
+static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bTransformConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target */
+       if (VALID_CONS_TARGET(ct)) {
+               float loc[3], eul[3], size[3];
+               float dvec[3], sval[3];
+               short i;
+               
+               /* obtain target effect */
+               switch (data->from) {
+                       case 2: /* scale */
+                               Mat4ToSize(ct->matrix, dvec);
+                               break;
+                       case 1: /* rotation */
+                               Mat4ToEul(ct->matrix, dvec);
+                               break;
+                       default: /* location */
+                               VecCopyf(dvec, ct->matrix[3]);
+                               break;
                }
-               break;
-       case CONSTRAINT_TYPE_ROTLIMIT:
-               {
-                       bRotLimitConstraint *data;
-                       float loc[3];
-                       float eul[3];
-                       float size[3];
-                       
-                       data = constraint->data;
-                       
-                       VECCOPY(loc, ownermat[3]);
-                       Mat4ToSize(ownermat, size);
-                       
-                       Mat4ToEul(ownermat, eul);
-                       
-                       /* eulers: radians to degrees! */
-                       eul[0] = (eul[0] / M_PI * 180);
-                       eul[1] = (eul[1] / M_PI * 180);
-                       eul[2] = (eul[2] / M_PI * 180);
-                       
-                       /* limiting of euler values... */
-                       if (data->flag & LIMIT_XROT) {
-                               if (eul[0] < data->xmin) 
-                                       eul[0] = data->xmin;
-                                       
-                               if (eul[0] > data->xmax)
-                                       eul[0] = data->xmax;
-                       }
-                       if (data->flag & LIMIT_YROT) {
-                               if (eul[1] < data->ymin)
-                                       eul[1] = data->ymin;
-                                       
-                               if (eul[1] > data->ymax)
-                                       eul[1] = data->ymax;
-                       }
-                       if (data->flag & LIMIT_ZROT) {
-                               if (eul[2] < data->zmin)
-                                       eul[2] = data->zmin;
-                                       
-                               if (eul[2] > data->zmax)
-                                       eul[2] = data->zmax;
+               
+               /* extract components of owner's matrix */
+               VECCOPY(loc, cob->matrix[3]);
+               Mat4ToEul(cob->matrix, eul);
+               Mat4ToSize(cob->matrix, size);
+               
+               /* determine where in range current transforms lie */
+               if (data->expo) {
+                       for (i=0; i<3; i++) {
+                               if (data->from_max[i] - data->from_min[i])
+                                       sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
+                               else
+                                       sval[i]= 0.0f;
                        }
-                               
-                       /* eulers: degrees to radians ! */
-                       eul[0] = (eul[0] / 180 * M_PI); 
-                       eul[1] = (eul[1] / 180 * M_PI);
-                       eul[2] = (eul[2] / 180 * M_PI);
-                       
-                       LocEulSizeToMat4(ownermat, loc, eul, size);
                }
-               break;
-       case CONSTRAINT_TYPE_SIZELIMIT:
-               {
-                       bSizeLimitConstraint *data;
-                       float obsize[3], size[3];
-                       
-                       data = constraint->data;
-                       
-                       Mat4ToSize(ownermat, size);
-                       Mat4ToSize(ownermat, obsize);
-                       
-                       if (data->flag & LIMIT_XMIN) {
-                               if (size[0] < data->xmin) 
-                                       size[0] = data->xmin;   
-                       }
-                       if (data->flag & LIMIT_XMAX) {
-                               if (size[0] > data->xmax) 
-                                       size[0] = data->xmax;
-                       }
-                       if (data->flag & LIMIT_YMIN) {
-                               if (size[1] < data->ymin) 
-                                       size[1] = data->ymin;   
-                       }
-                       if (data->flag & LIMIT_YMAX) {
-                               if (size[1] > data->ymax) 
-                                       size[1] = data->ymax;
-                       }
-                       if (data->flag & LIMIT_ZMIN) {
-                               if (size[2] < data->zmin) 
-                                       size[2] = data->zmin;   
-                       }
-                       if (data->flag & LIMIT_ZMAX) {
-                               if (size[2] > data->zmax) 
-                                       size[2] = data->zmax;
+               else {
+                       /* clamp transforms out of range */
+                       for (i=0; i<3; i++) {
+                               CLAMP(dvec[i], data->from_min[i], data->from_max[i]);
+                               if (data->from_max[i] - data->from_min[i])
+                                       sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
+                               else
+                                       sval[i]= 0.0f;
                        }
-                       
-                       VecMulf(ownermat[0], size[0]/obsize[0]);
-                       VecMulf(ownermat[1], size[1]/obsize[1]);
-                       VecMulf(ownermat[2], size[2]/obsize[2]);
                }
-               break;
-       case CONSTRAINT_TYPE_RIGIDBODYJOINT:
-        {
-                       /* Do nothing. The GameEngine will take care of this.*/
-        }
-        break; 
-       case CONSTRAINT_TYPE_CLAMPTO:
-               {
-                       bClampToConstraint *data;
-                       Curve *cu;
-                       float obmat[4][4], targetMatrix[4][4], ownLoc[3];
-                       float curveMin[3], curveMax[3];
-                       
-                       data = constraint->data;
-                       
-                       /* prevent crash if user deletes curve */
-                       if ((data->tar == NULL) || (data->tar->type != OB_CURVE) ) 
-                               return;
-                       else
-                               cu= data->tar->data;
-                       
-                       Mat4CpyMat4(obmat, ownermat);
-                       Mat4One(targetMatrix);
-                       VECCOPY(ownLoc, obmat[3]);
-                       
-                       INIT_MINMAX(curveMin, curveMax)
-                       minmax_object(data->tar, curveMin, curveMax);
-                       
-                       /* get targetmatrix */
-                       if (cu->path && cu->path->data) {
-                               float vec[4], dir[3], totmat[4][4];
-                               float curvetime;
-                               short clamp_axis;
-                               
-                               /* find best position on curve */
-                               /* 1. determine which axis to sample on? */
-                               if (data->flag == CLAMPTO_AUTO) {
-                                  &n