Result of 2 weeks of quiet coding work in Greece :)
authorTon Roosendaal <ton@blender.org>
Sun, 3 Jul 2005 17:35:38 +0000 (17:35 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 3 Jul 2005 17:35:38 +0000 (17:35 +0000)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs

A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;

- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes

Armatures;

Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!

Important to note is;

1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.

- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.

TODO NOW;

- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.

TODO LATER;

We now can do loadsa new nifty features as well; like:

- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...

Bugfixes;

- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change

-Ton-

112 files changed:
source/blender/blenkernel/BKE_action.h
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/BKE_constraint.h
source/blender/blenkernel/BKE_depsgraph.h
source/blender/blenkernel/BKE_displist.h
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_ika.h [deleted file]
source/blender/blenkernel/BKE_ipo.h
source/blender/blenkernel/BKE_key.h
source/blender/blenkernel/BKE_main.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/SConscript
source/blender/blenkernel/depsgraph_private.h
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/deform.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/exotic.c
source/blender/blenkernel/intern/font.c
source/blender/blenkernel/intern/ika.c [deleted file]
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readblenentry.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/BDR_editcurve.h
source/blender/include/BDR_editobject.h
source/blender/include/BIF_butspace.h
source/blender/include/BIF_editarmature.h
source/blender/include/BIF_editconstraint.h
source/blender/include/BIF_editfont.h
source/blender/include/BIF_editika.h [deleted file]
source/blender/include/BIF_outliner.h
source/blender/include/BIF_poseobject.h
source/blender/include/butspace.h
source/blender/include/transform.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_armature_types.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_ika_types.h [deleted file]
source/blender/makesdna/DNA_ipo_types.h
source/blender/makesdna/DNA_key_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/python/api2_2x/Armature.c
source/blender/python/api2_2x/Bone.c
source/blender/python/api2_2x/Object.c
source/blender/python/api2_2x/Object.h
source/blender/python/api2_2x/Scene.c
source/blender/python/api2_2x/doc/Object.py
source/blender/python/api2_2x/doc/Scene.py
source/blender/render/intern/source/initrender.c
source/blender/renderconverter/intern/convertBlenderScene.c
source/blender/src/SConscript
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c
source/blender/src/buttons_script.c
source/blender/src/drawdeps.c
source/blender/src/drawobject.c
source/blender/src/drawview.c
source/blender/src/edit.c
source/blender/src/editaction.c
source/blender/src/editarmature.c
source/blender/src/editconstraint.c
source/blender/src/editcurve.c
source/blender/src/editfont.c
source/blender/src/editika.c [deleted file]
source/blender/src/editipo.c
source/blender/src/editkey.c
source/blender/src/editlattice.c
source/blender/src/editmball.c
source/blender/src/editmesh.c
source/blender/src/editmesh_add.c
source/blender/src/editmesh_mods.c
source/blender/src/editmesh_tools.c
source/blender/src/editmode_undo.c
source/blender/src/editobject.c
source/blender/src/editview.c
source/blender/src/filesel.c
source/blender/src/header_action.c
source/blender/src/header_info.c
source/blender/src/header_view3d.c
source/blender/src/headerbuttons.c
source/blender/src/interface.c
source/blender/src/meshtools.c
source/blender/src/outliner.c
source/blender/src/poseobject.c
source/blender/src/renderwin.c
source/blender/src/space.c
source/blender/src/toets.c
source/blender/src/transform.c
source/blender/src/transform_constraints.c
source/blender/src/transform_conversions.c
source/blender/src/transform_generics.c
source/blender/src/transform_manipulator.c
source/blender/src/vpaint.c
source/blender/yafray/intern/yafray_Render.h
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_ArmatureObject.cpp
source/gameengine/Converter/BL_SkinDeformer.cpp
source/nan_definitions.mk

index 2f3af8c..5b8c8c1 100644 (file)
@@ -28,9 +28,7 @@
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
+ * Contributor(s): Full recode, Ton Roosendaal, Crete 2005
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
@@ -55,25 +53,16 @@ struct Object;
 extern "C" {
 #endif
 
-/**
- * Allocate a new pose channel on the heap and binary copy the 
- * contents of the src pose channel.
- */
-struct bPoseChannel *copy_pose_channel(const struct bPoseChannel *src);
-
+       
 /**
  * Removes and deallocates all channels from a pose.
  * Does not free the pose itself.
  */
-void clear_pose(struct bPose *pose);
-
-/* Sets the value of a pose channel */
-struct bPoseChannel *set_pose_channel(struct bPose *pose, 
-                                                                         struct bPoseChannel *chan);
+void free_pose_channels(struct bPose *pose);
 
 /**
  * Allocate a new pose on the heap, and copy the src pose and it's channels
- * into the new pose. *dst is set to the newly allocated structure.
+ * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL.
  */ 
 void copy_pose(struct bPose **dst, struct bPose *src,
                           int copyconstraints);
@@ -104,6 +93,9 @@ struct  bPoseChannel *get_pose_channel(const struct bPose *pose,
 struct bPoseChannel *verify_pose_channel(struct bPose* pose, 
                                                                                 const char* name);
 
+/* sets constraint flags */
+void update_pose_constraint_flags(struct bPose *pose);
+
 /**
  * Allocate a new bAction on the heap and copy 
  * the contents of src into it. If src is NULL NULL is returned.
@@ -119,30 +111,11 @@ float calc_action_start(const struct bAction *act);
 float calc_action_end(const struct bAction *act);
 
 /**
- * Evaluate the pose from the given action.
- * If the pose does not exist, a new one is created.
- * Some deep calls into blender are made here.
+ * Set the pose channels from the given action.
  */
-void get_pose_from_action(struct bPose **pose, struct bAction *act,
+void extract_pose_from_action(struct bPose *pose, struct bAction *act,
                                                   float ctime);
 
-/**
- * I think this duplicates the src into *pose.
- * If the pose does not exist, a new one is created.
- * If the pose does not contain channels from src
- * new channels are created.
- */ 
-void get_pose_from_pose(struct bPose **pose, const struct bPose *src);
-
-void clear_pose_constraint_status(struct Object *ob);
-
-/**
- * Blends the common subset of channels from dst and src.
- * and writes result to dst.
- */
-void blend_poses(struct bPose *dst, const struct bPose *src,
-                                 float srcweight, short mode);
-
 /**
  * Iterate through the action channels of the action
  * and return the channel with the given name.
@@ -151,30 +124,20 @@ void blend_poses(struct bPose *dst, const struct bPose *src,
 struct bActionChannel *get_named_actionchannel(struct bAction *act,
                                                                                           const char *name);
 
+// exported for game engine
+void blend_poses(struct bPose *dst, const struct bPose *src, float srcweight, short mode);
+void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
+
+
 #ifdef __cplusplus
 };
 #endif
 
+/* nla strip flag */
 enum   {
                        POSE_BLEND              = 0,
                        POSE_ADD
 };
 
-enum   {
-                       POSE_KEY                =       0x10000000,
-                       POSE_LOC                =       0x00000001,
-                       POSE_ROT                =       0x00000002,
-                       POSE_SIZE               =       0x00000004,
-                       POSE_UNUSED1    =       0x00000008,
-                       POSE_UNUSED2    =       0x00000010,
-                       POSE_UNUSED3    =       0x00000020,
-                       POSE_UNUSED4    =       0x00000040,
-                       POSE_UNUSED5    =       0x00000080,
-                       POSE_OBMAT              =       0x00000100,
-                       POSE_PARMAT             =       0x00000200,
-                       PCHAN_DONE              =       0x00000400,
-                       PCHAN_TRANS_UPDATE = 0x00000800
-};
-
 #endif
 
index 1f9725a..3b924b5 100644 (file)
@@ -38,6 +38,8 @@ struct Bone;
 struct Main;
 struct bArmature;
 struct bPose;
+struct bPoseChannel;
+struct bConstraint;
 struct Object;
 struct MDeformVert;
 struct Mesh;
@@ -46,10 +48,12 @@ struct ListBase;
 
 typedef struct PoseChain
 {
-       struct PoseChain *next, *prev;
-       struct Bone     *root;
-       struct Bone     *target;
+       struct PoseChain *next, *prev;  // hurms
+       struct bPoseChannel     **pchanchain;
+       struct bConstraint *con;
+       struct Bone *root, *target;
        struct bPose *pose;
+       int totchannel;
        float   goal[3];
        float   tolerance;
        int             iterations;
@@ -68,42 +72,27 @@ void unlink_armature(struct bArmature *arm);
 void free_armature(struct bArmature *arm);
 void make_local_armature(struct bArmature *arm);
 struct bArmature *copy_armature(struct bArmature *arm);
-void apply_pose_armature (struct bArmature* arm, struct bPose* pose, int doit);
+
 void calc_armature_deform (struct Object *ob, float *co, int index);
-int verify_boneptr (struct bArmature *arm, struct Bone *tBone);
+
 void init_armature_deform(struct Object *parent, struct Object *ob);
 struct bArmature* get_armature (struct Object* ob);
 struct Bone *get_named_bone (struct bArmature *arm, const char *name);
-struct Bone *get_indexed_bone (struct bArmature *arm, int index);
-void make_displists_by_armature (struct Object *ob);
-void calc_bone_deform (struct Bone *bone, float weight, float *vec, float *co, float *contrib);
+struct Bone *get_indexed_bone (struct Object *ob, int index);
+
 float dist_to_bone (float vec[3], float b1[3], float b2[3]);
 
-void where_is_armature_time (struct Object *ob, float ctime);
-void where_is_armature (struct Object *ob);
-void where_is_bone1_time (struct Object *ob, struct Bone *bone, float ctime);
-
-/*     Handy bone matrix functions */
-void bone_to_mat4(struct Bone *bone, float mat[][4]);
-void bone_to_mat3(struct Bone *bone, float mat[][3]);
-void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll);
-void make_boneMatrix (float outmatrix[][4], struct Bone *bone);
-void get_bone_root_pos (struct Bone* bone, float vec[3], int posed);
-void get_bone_tip_pos (struct Bone* bone, float vec[3], int posed);
-float get_bone_length (struct Bone *bone);
+void where_is_armature (struct bArmature *arm);
+void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone);
+void armature_rebuild_pose(struct Object *ob, struct bArmature *arm);
+void where_is_pose (struct Object *ob);
+
 void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed);
-void precalc_bone_irestmat (struct Bone *bone);
-void precalc_armature_posemats (struct bArmature *arm);
-void precalc_bonelist_irestmats (struct ListBase* bonelist);
-void apply_bonemat(struct Bone *bone);
+void vec_roll_to_mat3(float *vec, float roll, float mat[][3]);
 
-/* void make_armatureParentMatrices (struct bArmature *arm); */
-void precalc_bone_defmat (struct Bone *bone);
-void rebuild_bone_parent_matrix (struct Bone *bone);
 
 /*     Animation functions */
-void where_is_bone_time (struct Object *ob, struct Bone *bone, float ctime);
-void where_is_bone (struct Object *ob, struct Bone *bone);
+
 struct PoseChain *ik_chain_to_posechain (struct Object *ob, struct Bone *bone);
 void solve_posechain (PoseChain *chain);
 void free_posechain (PoseChain *chain);
index cc2e549..8fdc63b 100644 (file)
@@ -50,9 +50,7 @@ void *copy_constraint_channels (ListBase *dst, ListBase *src);
 struct bConstraintChannel *clone_constraint_channels (struct ListBase *dst, struct ListBase *src, struct bConstraintChannel *oldact);
 void relink_constraints (struct ListBase *list);
 void free_constraint_data (struct bConstraint *con);
-void clear_object_constraint_status (struct Object *ob);
-void clear_all_constraints(void);
-void rebuild_all_armature_displists(void);
+
 void do_constraint_channels (struct ListBase *conbase, struct ListBase *chanbase, float ctime);
 short get_constraint_target_matrix (struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float size[3], float time);
 struct bConstraintChannel *find_constraint_channel (ListBase *list, const char *name);
@@ -61,7 +59,9 @@ void free_constraint_channels (ListBase *chanbase);
 /* Gemeric functions */
 
 char constraint_has_target (struct bConstraint *con);
-struct Object *get_constraint_target(struct bConstraint *con);
+struct Object *get_constraint_target(struct bConstraint *con, char **subtarget);
+void set_constraint_target(struct bConstraint *con, struct Object *ob);
+
 
 /* Constraint target/owner types */
 #define TARGET_OBJECT                  1       //      string is ""
index 06eea7a..0c59236 100644 (file)
@@ -40,31 +40,26 @@ struct DagNodeQueue;
 struct DagForest;
 struct DagNode;
 
-typedef enum { 
-       DAG_RL_SCENE                            = 1,
-       DAG_RL_DATA                                     = 2,
-       DAG_RL_PARENT                           = 4,
-       DAG_RL_TRACK                            = 8,
-       DAG_RL_PATH                                     = 16,
-       DAG_RL_CONSTRAINT                       = 32,
-       DAG_RL_HOOK                                     = 64,
-       DAG_RL_DATA_CONSTRAINT          = 128,
-       DAG_NO_RELATION                         = 256
-} dag_rel_type;
-
-
-typedef enum {
-       DAG_RL_SCENE_MASK                       = 1,
-       DAG_RL_DATA_MASK                        = 2,
-       DAG_RL_PARENT_MASK                      = 4,
-       DAG_RL_TRACK_MASK                       = 8,
-       DAG_RL_PATH_MASK                        = 16,
-       DAG_RL_CONSTRAINT_MASK          = 32,
-       DAG_RL_HOOK_MASK                        = 64,
-       DAG_RL_DATA_CONSTRAINT_MASK     = 128,
-       DAG_RL_ALL_BUT_DATA_MASK        = 253,
-       DAG_RL_ALL_MASK                         = 255
-} dag_rel_type_mask;
+/* **** DAG relation types *** */
+
+       /* scene link to object */
+#define DAG_RL_SCENE           1
+       /* object link to data */
+#define DAG_RL_DATA                    2
+
+       /* object changes object (parent, track, constraints) */
+#define DAG_RL_OB_OB           4
+       /* object changes obdata (hooks, constraints) */
+#define DAG_RL_OB_DATA         8
+       /* data changes object (vertex parent) */
+#define DAG_RL_DATA_OB         16
+       /* data changes data (deformers) */
+#define DAG_RL_DATA_DATA       32
+
+#define DAG_NO_RELATION                64
+#define DAG_RL_ALL                     63
+#define DAG_RL_ALL_BUT_DATA 61
+
 
 typedef void (*graph_action_func)(void * ob, void **data);
 
@@ -91,13 +86,19 @@ int pre_and_post_source_DFS(struct DagForest *dag, short mask, struct DagNode *s
 struct DagNodeQueue *get_obparents(struct DagForest    *dag, void *ob); 
 struct DagNodeQueue *get_first_ancestors(struct DagForest      *dag, void *ob); 
 struct DagNodeQueue *get_all_childs(struct DagForest   *dag, void *ob); //
-dag_rel_type           are_obs_related(struct DagForest        *dag, void *ob1, void *ob2);
+short          are_obs_related(struct DagForest        *dag, void *ob1, void *ob2);
 int                                    is_acyclic(struct DagForest     *dag); //
 //int                                  get_cycles(struct DagForest     *dag, struct DagNodeQueue **queues, int *count); //
-void                           topo_sort_baselist(struct Scene *sce);
 
 void   boundbox_deps(void);
 void   draw_all_deps(void);
 
+/* ********** API *************** */
+
+void   DAG_scene_sort(struct Scene *sce);
+void   DAG_scene_update_flags(struct Scene *sce, unsigned int lay);
+void   DAG_scene_flush_update(struct Scene *sce);
+void   DAG_object_flush_update(struct Scene *sce, struct Object *ob, short flag);
+void   DAG_pose_sort(struct Object *ob);
 
 #endif
index ca08b54..0a79d8e 100644 (file)
@@ -148,7 +148,6 @@ void freefastshade(void);
 void boundbox_displist(struct Object *ob);
 void imagestodisplist(void);
 void reshadeall_displist(void);
-void test_all_displists(void);
 void filldisplist(struct ListBase *dispbase, struct ListBase *to);
 
 #endif
index 848f82c..211280f 100644 (file)
@@ -88,7 +88,7 @@ typedef struct Global {
     char ima[160], sce[160], lib[160];
     
     /* totals */
-    short totobj, totlamp, totobjsel, totcurve, totmesh, totmat;
+    short totobj, totlamp, totobjsel, totcurve, totmesh, totbone, totbonesel;
     int totvert, totedge, totface, totvertsel, totedgesel, totfacesel;
     
     short machine, afbreek, moving, colact, zbuf;
diff --git a/source/blender/blenkernel/BKE_ika.h b/source/blender/blenkernel/BKE_ika.h
deleted file mode 100644 (file)
index 93856c3..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * blenlib/BKE_ika.h (mar-2001 nzc)
- *     
- * $Id$ 
- *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
- */
-#ifndef BKE_IKA_H
-#define BKE_IKA_H
-
-struct Ika;
-struct Limb;
-struct Object;
-
-void unlink_ika(struct Ika *ika);
-void free_ika(struct Ika *ika);
-struct Ika *add_ika(void);
-struct Ika *copy_ika(struct Ika *ika);
-void make_local_ika(struct Ika *ika);
-int count_limbs(struct Object *ob);
-void calc_limb(struct Limb *li);
-void calc_ika(struct Ika *ika, struct Limb *li);
-void init_defstate_ika(struct Object *ob);
-void itterate_limb(struct Ika *ika, struct Limb *li);
-void rotate_ika(struct Object *ob, struct Ika *ika);
-void rotate_ika_xy(struct Object *ob, struct Ika *ika);
-void itterate_ika(struct Object *ob);
-void do_all_ikas(void);
-void do_all_visible_ikas(void);
-void init_skel_deform(struct Object *par, struct Object *ob);
-void calc_skel_deform(struct Ika *ika, float *co);
-
-#endif
-
index c251630..e0c7fd7 100644 (file)
@@ -82,7 +82,7 @@ void do_mat_ipo(struct Material *ma);
 void do_ob_ipo(struct Object *ob);
 void do_seq_ipo(struct Sequence *seq);
 int has_ipo_code(struct Ipo *ipo, int code);
-void do_all_ipos(void);
+void do_all_data_ipos(void);
 int calc_ipo_spec(struct Ipo *ipo, int adrcode, float *ctime);
 void clear_delta_obipo(struct Ipo *ipo);
 void add_to_cfra_elem(struct ListBase *lb, struct BezTriple *bezt);
index 481c08c..b46f02c 100644 (file)
@@ -62,9 +62,10 @@ void do_cu_key(struct Curve *cu, struct KeyBlock **k, float *t);
 void do_rel_cu_key(struct Curve *cu, float ctime);
 void do_curve_key(struct Curve *cu);
 void do_latt_key(struct Lattice *lt);
-void do_all_keys(void);
 void do_ob_key(struct Object *ob);
 void do_spec_key(struct Key *key);
-       
+
+void unlock_all_keys(void);
+
 #endif
 
index 058ac3f..9a37f91 100644 (file)
@@ -59,7 +59,6 @@ typedef struct Main {
        ListBase mat;
        ListBase tex;
        ListBase image;
-       ListBase ika;
        ListBase wave;
        ListBase latt;
        ListBase lamp;
index 775b205..1fadaa1 100644 (file)
@@ -88,13 +88,15 @@ int during_scriptlink(void);
 void where_is_object_time(struct Object *ob, float ctime);
 void where_is_object(struct Object *ob);
 void where_is_object_simul(struct Object *ob);
-void what_does_parent1(struct Object *par, int partype, int par1, int par2, int par3);
+
 void what_does_parent(struct Object *ob);
 struct BoundBox *unit_boundbox(void);
 void minmax_object(struct Object *ob, float *min, float *max);
 void solve_tracking (struct Object *ob, float targetmat[][4]);
 void solve_constraints (struct Object *ob, short obtype, void *obdata, float ctime);
 
+void object_handle_update(struct Object *ob);
+
 #ifdef __cplusplus
 }
 #endif
index 538912a..1313ad2 100644 (file)
@@ -57,12 +57,14 @@ struct QuicktimeCodecData;
 
 void free_avicodecdata(struct AviCodecData *acd);
 void free_qtcodecdata(struct QuicktimeCodecData *acd);
+
 void free_scene(struct Scene *me);
 struct Scene *add_scene(char *name);
 int object_in_scene(struct Object *ob, struct Scene *sce);
-void sort_baselist(struct Scene *sce);
+
 void set_scene_bg(struct Scene *sce);
 void set_scene_name(char *name);
+
 int next_object(int val, struct Base **base, struct Object **ob);
 struct Object *scene_find_camera(struct Scene *sc);
 
@@ -70,5 +72,7 @@ struct Base *scene_add_base(struct Scene *sce, struct Object *ob);
 void scene_deselect_all(struct Scene *sce);
 void scene_select_base(struct Scene *sce, struct Base *selbase);
 
+void scene_update_for_newframe(struct Scene *sce, unsigned int lay);
+
 #endif
 
index 0b6bf52..a30c648 100644 (file)
@@ -12,7 +12,6 @@ source_files = ['intern/constraint.c',
                 'intern/sca.c',
                 'intern/world.c',
                 'intern/curve.c',
-                'intern/ika.c',
                 'intern/mball.c',
                 'intern/scene.c',
                 'intern/writeavi.c',
index d6d74f7..6b29de2 100644 (file)
@@ -51,8 +51,9 @@ enum {
 typedef struct DagAdjList
 {
        struct DagNode *node;
-       dag_rel_type type;
-       int count; // number of identical arcs
+       short type;
+       int count;                      // number of identical arcs
+       unsigned int lay;   // for flushing redraw/rebuild events
        struct DagAdjList *next;
 } DagAdjList;
 
@@ -64,7 +65,9 @@ typedef struct DagNode
        float x, y, k;  
        void * ob;
        void * first_ancestor;
-       int             ancestor_count;
+       int ancestor_count;
+       int lay;                        // accumulated layers of its relations + itself
+       int lasttime;           // if lasttime != DagForest->time, this node was not evaluated yet for flushing
        int BFS_dist;           // BFS distance
        int DFS_dist;           // DFS distance
        int DFS_dvtm;           // DFS discovery time
@@ -93,6 +96,7 @@ typedef struct DagForest
        ListBase DagNode;
        int numNodes;
        int is_acyclic;
+       int time;               // for flushing/tagging, compare with node->lasttime
 } DagForest;
 
 
@@ -112,7 +116,7 @@ DagNode * dag_find_node (DagForest *forest,void * fob);
 DagNode * dag_add_node (DagForest *forest,void * fob);
 DagNode * dag_get_node (DagForest *forest,void * fob);
 DagNode * dag_get_sub_node (DagForest *forest,void * fob);
-void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, dag_rel_type rel);
+void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel);
 
 void graph_bfs(void);
 
index 4b1f477..911df2a 100644 (file)
@@ -23,9 +23,7 @@
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
+ * Contributor(s): Full recode, Ton Roosendaal, Crete 2005
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
 #include <stdlib.h>    /* for NULL */
 
 #include "MEM_guardedalloc.h"
-#include "BLI_arithb.h"
-#include "BLI_blenlib.h"
-
-#include "BKE_action.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
-#include "BKE_utildefines.h"
 
-#include "DNA_object_types.h"
-#include "DNA_ipo_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_scene_types.h"
 #include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
 #include "DNA_nla_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
 
+#include "BKE_action.h"
+#include "BKE_anim.h"
+#include "BKE_armature.h"
 #include "BKE_blender.h"
+#include "BKE_constraint.h"
+#include "BKE_global.h"
 #include "BKE_ipo.h"
-#include "BKE_object.h"
 #include "BKE_library.h"
-#include "BKE_anim.h"
-#include "BKE_armature.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
 
 #include "nla.h"
 
-#include "BKE_constraint.h"
-#include "DNA_constraint_types.h"
+/* *********************** NOTE ON POSE AND ACTION **********************
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+  - Pose is the local (object level) component of armature. The current
+    object pose is saved in files, and (will be) is presorted for dependency
+  - Actions have fewer (or other) channels, and write data to a Pose
+  - Currently ob->pose data is controlled in where_is_pose only. The (recalc)
+    event system takes care of calling that
+  - The NLA system (here too) uses Poses as interpolation format for Actions
+  - Therefore we assume poses to be static, and duplicates of poses have channels in
+    same order, for quick interpolation reasons
+
+  ****************************** (ton) ************************************ */
+
+/* ***************** Library data level operations on action ************** */
+
+void make_local_action(bAction *act)
+{
+       Object *ob;
+       bAction *actn;
+       int local=0, lib=0;
+       
+       if(act->id.lib==0) return;
+       if(act->id.us==1) {
+               act->id.lib= 0;
+               act->id.flag= LIB_LOCAL;
+               new_id(0, (ID *)act, 0);
+               return;
+       }
+       
+       ob= G.main->object.first;
+       while(ob) {
+               if(ob->action==act) {
+                       if(ob->id.lib) lib= 1;
+                       else local= 1;
+               }
+               ob= ob->id.next;
+       }
+       
+       if(local && lib==0) {
+               act->id.lib= 0;
+               act->id.flag= LIB_LOCAL;
+               new_id(0, (ID *)act, 0);
+       }
+       else if(local && lib) {
+               actn= copy_action(act);
+               actn->id.us= 0;
+               
+               ob= G.main->object.first;
+               while(ob) {
+                       if(ob->action==act) {
+                               
+                               if(ob->id.lib==0) {
+                                       ob->action = actn;
+                                       ob->activecon = NULL;
+                                       actn->id.us++;
+                                       act->id.us--;
+                               }
+                       }
+                       ob= ob->id.next;
+               }
+       }
+}
+
+
+void free_action(bAction *act)
+{
+       bActionChannel *chan;
+       
+       /* Free channels */
+       for (chan=act->chanbase.first; chan; chan=chan->next){
+               if (chan->ipo)
+                       chan->ipo->id.us--;
+               free_constraint_channels(&chan->constraintChannels);
+       }
+       
+       if (act->chanbase.first)
+               BLI_freelistN (&act->chanbase);
+}
 
-/* Local function prototypes */
+bAction* copy_action(bAction *src)
+{
+       bAction *dst = NULL;
+       bActionChannel *dchan, *schan;
+       
+       if(!src) return NULL;
+       
+       dst= copy_libblock(src);
+       duplicatelist(&(dst->chanbase), &(src->chanbase));
+       
+       for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
+               dchan->ipo = copy_ipo(dchan->ipo);
+               copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
+       }
+       dst->id.flag |= LIB_FAKEUSER;
+       dst->id.us++;
+       return dst;
+}
 
-static void do_pose_constraint_channels(bPose *pose, bAction *act, 
-                                                                               float ctime);
 
-static void rest_pose(bPose *pose, int clearflag);
 
-/* Implementation */
+/* ************************ Pose channels *************** */
 
 bPoseChannel *get_pose_channel(const bPose *pose, const char *name)
 {
        bPoseChannel *chan;
 
+       if(pose==NULL) return NULL;
+       
        for (chan=pose->chanbase.first; chan; chan=chan->next){
                if (!strcmp (chan->name, name))
                        return chan;
@@ -91,70 +180,132 @@ bPoseChannel *get_pose_channel(const bPose *pose, const char *name)
        return NULL;
 }
 
-static void rest_pose(bPose *pose, int clearflag)
+/* Use with care, not on Armature poses but for temporal ones */
+/* (currently used for action constraints and in rebuild_pose) */
+bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
 {
        bPoseChannel *chan;
-       int i;
+       
+       if (!pose){
+               return NULL;
+       }
+       
+       /*      See if this channel exists */
+       for (chan=pose->chanbase.first; chan; chan=chan->next){
+               if (!strcmp (name, chan->name))
+                       return chan;
+       }
+       
+       /* If not, create it and add it */
+       chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
+       
+       strcpy (chan->name, name);
+       /* init vars to prevent mat errors */
+       chan->quat[0] = 1.0F;
+       chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
+       Mat3One(chan->ik_mat);
+       
+       BLI_addtail (&pose->chanbase, chan);
+       
+       return chan;
+}
 
-       if (!pose)
+
+/* dst should be freed already, makes entire duplicate */
+void copy_pose(bPose **dst, bPose *src, int copycon)
+{
+       bPose *outPose;
+       bPoseChannel    *pchan;
+       ListBase listb;
+       
+       if (!src){
+               *dst=NULL;
                return;
+       }
+       
+       outPose= MEM_callocN(sizeof(bPose), "pose");
+       
+       duplicatelist (&outPose->chanbase, &src->chanbase);
+       
+       if (copycon) {
+               for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) {
+                       copy_constraints(&listb, &pchan->constraints);  // copy_constraints NULLs listb
+                       pchan->constraints= listb;
+               }
+       }
+       
+       *dst=outPose;
+}
 
-       for (chan=pose->chanbase.first; chan; chan=chan->next){
-               for (i=0; i<3; i++){
-                       chan->loc[i]=0.0;
-                       chan->quat[i+1]=0.0;
-                       chan->size[i]=1.0;
+void free_pose_channels(bPose *pose) 
+{
+       bPoseChannel *chan;
+       
+       if (pose->chanbase.first){
+               for (chan = pose->chanbase.first; chan; chan=chan->next){
+                       free_constraints(&chan->constraints);
                }
-               chan->quat[0]=1.0;
-               if (clearflag)
-                       chan->flag =0;
+               BLI_freelistN (&pose->chanbase);
        }
 }
 
-#ifdef __NLA_BLENDCON
-static void blend_constraints(ListBase *dst, const ListBase *src,
-                                                         float srcweight, short mode)
+static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan)
 {
-       bConstraint *dcon;
-       const bConstraint *scon;
-       float dstweight = 0;
+       VECCOPY(pchan->loc, chan->loc);
+       VECCOPY(pchan->size, chan->size);
+       QUATCOPY(pchan->quat, chan->quat);
+       pchan->flag= chan->flag;
+}
 
-       switch (mode){
-       case POSE_BLEND:
-               dstweight = 1.0F - srcweight;
-               break;
-       case POSE_ADD:
-               dstweight = 1.0F;
-               break;
+/* checks for IK constraint, can do more constraints flags later */
+/* pose should be entirely OK */
+void update_pose_constraint_flags(bPose *pose)
+{
+       bPoseChannel *pchan;
+       bConstraint *con;
+       
+       /* clear */
+       for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
+               pchan->constflag= 0;
        }
-
-       /* Blend constraints */
-       for (dcon=dst->first; dcon; dcon=dcon->next){
-               for (scon = src->first; scon; scon=scon->next){
-                       if (!strcmp(scon->name, dcon->name))
-                               break;
+       /* detect */
+       for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
+               for(con= pchan->constraints.first; con; con= con->next) {
+                       if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
+                               pchan->constflag |= PCHAN_HAS_IK;
+                       }
+                       else pchan->constflag |= PCHAN_HAS_CONST;
                }
-               
-               if (scon){
-                       dcon->enforce = (dcon->enforce*dstweight) + (scon->enforce*srcweight);
-                       if (mode == POSE_BLEND)
-                               dcon->enforce/=2.0;
-                       
-                       if (dcon->enforce>1.0)
-                               dcon->enforce=1.0;
-                       if (dcon->enforce<0.0)
-                               dcon->enforce=0.0;
+       }
+}
 
-               }
+
+/* ************************ END Pose channels *************** */
+
+bActionChannel *get_named_actionchannel(bAction *act, const char *name)
+{
+       bActionChannel *chan;
+       
+       if (!act)
+               return NULL;
+       
+       for (chan = act->chanbase.first; chan; chan=chan->next){
+               if (!strcmp (chan->name, name))
+                       return chan;
        }
+       
+       return NULL;
 }
-#endif
 
+/* ************************ Blending with NLA *************** */
+
+
+/* Only allowed for Poses with identical channels */
 void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode)
 {
        bPoseChannel *dchan;
        const bPoseChannel *schan;
-       float   dquat[4], squat[4]; //, mat[3][3];
+       float   dquat[4], squat[4];
        float dstweight;
        int i;
        
@@ -169,67 +320,35 @@ void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode)
                dstweight = 1.0F;
        }
        
-       for (dchan = dst->chanbase.first; dchan; dchan=dchan->next){
-               schan = get_pose_channel(src, dchan->name);
-               if (schan){
-                       if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)){
-                               
-                               /* Convert both quats to matrices and then back again. 
-                                * This prevents interpolation problems
-                                * This sucks because it is slow and stupid
-                                */
-                               
-                               //QuatToMat3(dchan->quat, mat);
-                               //Mat3ToQuat(mat, dquat);
-                               //QuatToMat3(schan->quat, mat);
-                               //Mat3ToQuat(mat, squat);
+       schan= src->chanbase.first;
+       for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){
+               if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) {
+                       
+                       /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */
+                       
+                       /* Do the transformation blend */
+                       if (schan->flag & POSE_ROT) {
+                               QUATCOPY(dquat, dchan->quat);
+                               QUATCOPY(squat, schan->quat);
+                               if(mode==POSE_BLEND)
+                                       QuatInterpol(dchan->quat, dquat, squat, srcweight);
+                               else
+                                       QuatAdd(dchan->quat, dquat, squat, srcweight);
                                
-                               /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */
-                               /* Do the transformation blend */
-                               if (schan->flag & POSE_ROT) {
-                                       QUATCOPY(dquat, dchan->quat);
-                                       QUATCOPY(squat, schan->quat);
-                                       if(mode==POSE_BLEND)
-                                               QuatInterpol(dchan->quat, dquat, squat, srcweight);
-                                       else
-                                               QuatAdd(dchan->quat, dquat, squat, srcweight);
-                                       NormalQuat (dchan->quat);
-                               }
+                               NormalQuat (dchan->quat);
+                       }
 
-                               for (i=0; i<3; i++){
-                                       if (schan->flag & POSE_LOC)
-                                               dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
-                                       if (schan->flag & POSE_SIZE)
-                                               dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
-                                       //if (schan->flag & POSE_ROT)
-                                       //      dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
-                               }
-                               
-                               /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
-                               //if (schan->flag & POSE_ROT)
-                               //      dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
-                               //if (mode==POSE_BLEND)
-                               //      NormalQuat (dchan->quat);
-                               
-                               dchan->flag |= schan->flag;
+                       for (i=0; i<3; i++){
+                               if (schan->flag & POSE_LOC)
+                                       dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
+                               if (schan->flag & POSE_SIZE)
+                                       dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
                        }
+                       dchan->flag |= schan->flag;
                }
        }
 }
 
-void clear_pose_constraint_status(Object *ob)
-{
-       bPoseChannel *chan;
-
-       if (!ob)
-               return;
-       if (!ob->pose)
-               return;
-
-       for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
-               chan->flag &= ~PCHAN_DONE;
-       }
-}
 
 float calc_action_start(const bAction *act)
 {
@@ -291,59 +410,60 @@ float calc_action_end(const bAction *act)
        return size;
 }
 
-bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
+/* Copy the data from the action-pose (src) into the pose */
+/* both args are assumed to be valid */
+/* exported to game engine */
+void extract_pose_from_pose(bPose *pose, const bPose *src)
 {
-       bPoseChannel *chan;
+       const bPoseChannel *schan;
+       bPoseChannel *pchan= pose->chanbase.first;
 
-       if (!pose){
-               return NULL;
+       for (schan=src->chanbase.first; schan; schan=schan->next, pchan= pchan->next) {
+               copy_pose_channel_data(pchan, schan);
        }
+}
 
-       /*      See if this channel exists */
-       for (chan=pose->chanbase.first; chan; chan=chan->next){
-               if (!strcmp (name, chan->name))
-                       return chan;
-       }
-
-       /* If not, create it and add it */
-       chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
-
-       strcpy (chan->name, name);
-       chan->loc[0] = chan->loc[1] = chan->loc[2] = 0.0F;
-       chan->quat[1] = chan->quat[2] = chan->quat[3] = 0.0F;
-       chan->quat[0] = 1.0F;
-       chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
-
-       chan->flag |= POSE_ROT|POSE_SIZE|POSE_LOC;
-
-       BLI_addtail (&pose->chanbase, chan);
-
-       return chan;
-}
-
-void get_pose_from_pose(bPose **pose, const bPose *src)
+/* seems to be disabled... (ton) */
+#ifdef __NLA_BLENDCON
+static void blend_constraints(ListBase *dst, const ListBase *src,
+                                                         float srcweight, short mode)
 {
-       const bPoseChannel      *pchan;
-       bPoseChannel *newchan;
-
-       if (!src)
-               return;
-       if (!pose)
-               return;
-
-       /* If there is no pose, create one */
-       if (!*pose){
-               *pose=MEM_callocN (sizeof(bPose), "pose");
+       bConstraint *dcon;
+       const bConstraint *scon;
+       float dstweight = 0;
+       
+       switch (mode){
+               case POSE_BLEND:
+                       dstweight = 1.0F - srcweight;
+                       break;
+               case POSE_ADD:
+                       dstweight = 1.0F;
+                       break;
        }
-
-       /* Copy the data from the action into the pose */
-       for (pchan=src->chanbase.first; pchan; pchan=pchan->next){
-               newchan = copy_pose_channel(pchan);
-               verify_pose_channel(*pose, pchan->name);
-               set_pose_channel(*pose, newchan);
+       
+       /* Blend constraints */
+       for (dcon=dst->first; dcon; dcon=dcon->next){
+               for (scon = src->first; scon; scon=scon->next){
+                       if (!strcmp(scon->name, dcon->name))
+                               break;
+               }
+               
+               if (scon){
+                       dcon->enforce = (dcon->enforce*dstweight) + (scon->enforce*srcweight);
+                       if (mode == POSE_BLEND)
+                               dcon->enforce/=2.0;
+                       
+                       if (dcon->enforce>1.0)
+                               dcon->enforce=1.0;
+                       if (dcon->enforce<0.0)
+                               dcon->enforce=0.0;
+                       
+               }
        }
 }
+#endif
 
+/* seems to be disabled... (ton) */
 #ifdef __NLA_BLENDCON
 static void get_constraint_influence_from_pose(bPose *dst, bPose *src)
 {
@@ -364,72 +484,76 @@ static void get_constraint_influence_from_pose(bPose *dst, bPose *src)
 }
 #endif
 
-/* If the pose does not exist, a new one is created */
-
-void get_pose_from_action(bPose **pose, bAction *act, float ctime) 
+/* Pose should exist, can have any number of channels too (used for constraint) */
+void extract_pose_from_action(bPose *pose, bAction *act, float ctime) 
 {
        bActionChannel *achan;
        bPoseChannel    *pchan;
        Ipo                             *ipo;
-       IpoCurve                *curve;
-       
 
        if (!act)
                return;
        if (!pose)
                return;
 
-       /* If there is no pose, create one */
-       if (!*pose){
-               *pose=MEM_callocN (sizeof(bPose), "pose");
-       }
-
        /* Copy the data from the action into the pose */
        for (achan=act->chanbase.first; achan; achan=achan->next){
-               act->achan= achan;
+               act->achan= achan;  // for ipos
 
                ipo = achan->ipo;
-               if (ipo){
-                       pchan=MEM_callocN (sizeof(bPoseChannel), "gpfa_poseChannel");
-                       strcpy (pchan->name, achan->name);
-
-                       act->pchan=pchan;
-                       /* Evaluates and sets the internal ipo value */
-                       calc_ipo(ipo, ctime);
-
-                       /* Set the pchan flags */
-                       for (curve = achan->ipo->curve.first; curve; curve=curve->next){
-                               /*      Skip empty curves */
-                               if (!curve->totvert)
-                                       continue;
-
-                               switch (curve->adrcode){
-                               case AC_QUAT_X:
-                               case AC_QUAT_Y:
-                               case AC_QUAT_Z:
-                               case AC_QUAT_W:
-                                       pchan->flag |= POSE_ROT;
-                                       break;
-                               case AC_LOC_X:
-                               case AC_LOC_Y:
-                               case AC_LOC_Z:
-                                       pchan->flag |= POSE_LOC;
-                                       break;
-                               case AC_SIZE_X:
-                               case AC_SIZE_Y:
-                               case AC_SIZE_Z:
-                                       pchan->flag |= POSE_SIZE;
-                                       break;
-                               }
+               if (ipo) {
+                       pchan= get_pose_channel(pose, achan->name);
+                       if(pchan) {
+                               act->pchan= pchan;  // for ipos
+                               
+                               /* Evaluates and sets the internal ipo value */
+                               calc_ipo(ipo, ctime);
+
+                               /* This call also sets the pchan flags */
+                               execute_ipo((ID*)act, achan->ipo);
                        }
+               }
+       }
+}
 
-                       execute_ipo((ID*)act, achan->ipo);
-               
-                       set_pose_channel(*pose, pchan);
+/* for do_all_actions, clears the pose */
+static void rest_pose(bPose *pose, int clearflag)
+{
+       bPoseChannel *chan;
+       int i;
+       
+       if (!pose)
+               return;
+       
+       for (chan=pose->chanbase.first; chan; chan=chan->next){
+               for (i=0; i<3; i++){
+                       chan->loc[i]=0.0;
+                       chan->quat[i+1]=0.0;
+                       chan->size[i]=1.0;
                }
+               chan->quat[0]=1.0;
+               if (clearflag)
+                       chan->flag =0;
+       }
+}
+
+/* do constraint channels = execute the ipos */
+static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime)
+{
+       bPoseChannel *pchan;
+       bActionChannel *achan;
+       
+       if (!pose || !act)
+               return;
+       
+       for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
+               achan=get_named_actionchannel(act, pchan->name);
+               if (achan)
+                       do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime);
        }
 }
 
+
 void do_all_actions(Object *only_this)
 {
        Base *base;
@@ -440,9 +564,11 @@ void do_all_actions(Object *only_this)
        int     doit;
        float striptime, frametime, length, actlength;
        float blendfac, stripframe;
-
        int set;
 
+       //printf("do all actions disabled\n");
+       //return;
+       
        /* NEW: current scene ob ipo's */
        base= G.scene->base.first;
        set= 0;
@@ -453,150 +579,154 @@ void do_all_actions(Object *only_this)
                else ob = base->object;
 
                /* Retrieve data from the NLA */
-               if(ob->type==OB_ARMATURE){
+               if(ob->type==OB_ARMATURE && ob->pose) {
+                       bArmature *arm= ob->data;
 
-                       doit=0;
-
-                       /* Clear pose */
-                       if (apose){
-                               clear_pose(apose);
-                               MEM_freeN(apose);
-                       }
-                       /* Clear pose */
-                       if (tpose){
-                               clear_pose(tpose);
-                               MEM_freeN(tpose);
+                       if(arm->flag & ARM_NO_ACTION) {  // no action set while transform
+                               ;
                        }
+                       else {
+                               doit=0;
 
-                       copy_pose(&apose, ob->pose, 1);
-                       copy_pose(&tpose, ob->pose, 1);
-                       rest_pose(apose, 1);
-                       if (ob->nlastrips.first){
-                               rest_pose(ob->pose, 0);
-                       }
+                               /* Clear pose */
+                               if (apose){
+                                       free_pose_channels(apose);
+                                       MEM_freeN(apose);
+                               }
+                               /* Clear pose */
+                               if (tpose){
+                                       free_pose_channels(tpose);
+                                       MEM_freeN(tpose);
+                               }
 
-                       for (strip=ob->nlastrips.first; strip; strip=strip->next){
-                               doit = 0;
-                               if (strip->act){
-                       
-                                       /* Determine if the current frame is within the strip's range */
-                                       length = strip->end-strip->start;
-                                       actlength = strip->actend-strip->actstart;
-                                       striptime = (G.scene->r.cfra-(strip->start)) / length;
-                                       stripframe = (G.scene->r.cfra-(strip->start)) ;
-
-
-                                       if (striptime>=0.0){
-                                               
-                                               rest_pose(tpose, 1);
-
-                                               /* Handle path */
-                                               if (strip->flag & ACTSTRIP_USESTRIDE){
-                                                       if (ob->parent && ob->parent->type==OB_CURVE){
-                                                               Curve *cu = ob->parent->data;
-                                                               float ctime, pdist;
-
-                                                               if (cu->flag & CU_PATH){
-                                                                       /* Ensure we have a valid path */
-                                                                       if(cu->path==0 || cu->path->data==0) calc_curvepath(ob->parent);
-
-                                                                       /* Find the position on the path */
-                                                                       ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
-                                                                       
-                                                                       if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
-                                                                               ctime /= cu->pathlen;
-                                                                               CLAMP(ctime, 0.0, 1.0);
+                               copy_pose(&apose, ob->pose, 1);
+                               copy_pose(&tpose, ob->pose, 1);
+                               rest_pose(apose, 1);
+        
+                               if (ob->nlastrips.first){
+                                       rest_pose(ob->pose, 0);
+                               }
+
+                               for (strip=ob->nlastrips.first; strip; strip=strip->next){
+                                       doit = 0;
+                                       if (strip->act){
+                               
+                                               /* Determine if the current frame is within the strip's range */
+                                               length = strip->end-strip->start;
+                                               actlength = strip->actend-strip->actstart;
+                                               striptime = (G.scene->r.cfra-(strip->start)) / length;
+                                               stripframe = (G.scene->r.cfra-(strip->start)) ;
+
+
+                                               if (striptime>=0.0){
+                                                       
+                                                       rest_pose(tpose, 1);
+
+                                                       /* Handle path */
+                                                       if (strip->flag & ACTSTRIP_USESTRIDE){
+                                                               if (ob->parent && ob->parent->type==OB_CURVE){
+                                                                       Curve *cu = ob->parent->data;
+                                                                       float ctime, pdist;
+
+                                                                       if (cu->flag & CU_PATH){
+                                                                               /* Ensure we have a valid path */
+                                                                               if(cu->path==NULL || cu->path->data==NULL) printf("action path error\n");
+                                                                               else {
+
+                                                                                       /* Find the position on the path */
+                                                                                       ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
+                                                                                       
+                                                                                       if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
+                                                                                               ctime /= cu->pathlen;
+                                                                                               CLAMP(ctime, 0.0, 1.0);
+                                                                                       }
+                                                                                       pdist = ctime*cu->path->totdist;
+                                                                                       
+                                                                                       if (strip->stridelen)
+                                                                                               striptime = pdist / strip->stridelen;
+                                                                                       else
+                                                                                               striptime = 0;
+                                                                                       
+                                                                                       striptime = (float)fmod (striptime, 1.0);
+                                                                                       
+                                                                                       frametime = (striptime * actlength) + strip->actstart;
+                                                                                       extract_pose_from_action (tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+               #ifdef __NLA_BLENDCON
+                                                                                       do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+               #endif
+                                                                                       doit=1;
+                                                                               }
                                                                        }
-                                                                       pdist = ctime*cu->path->totdist;
-                                                                       
-                                                                       if (strip->stridelen)
-                                                                               striptime = pdist / strip->stridelen;
-                                                                       else
-                                                                               striptime = 0;
-                                                                       
-                                                                       striptime = (float)fmod (striptime, 1.0);
-                                                                       
-                                                                       frametime = (striptime * actlength) + strip->actstart;
-                                                                       get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
-#ifdef __NLA_BLENDCON
-                                                                       do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
-#endif
-                                                                       doit=1;
                                                                }
                                                        }
-                                               }
 
-                                               /* Handle repeat */
-               
-                                               else if (striptime < 1.0){
-                                                       /* Mod to repeat */
-                                                       striptime*=strip->repeat;
-                                                       striptime = (float)fmod (striptime, 1.0);
-                                                       
-                                                       frametime = (striptime * actlength) + strip->actstart;
-                                                       get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
-#ifdef __NLA_BLENDCON
-                                                       do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
-#endif
-                                                       doit=1;
-                                               }
-                                               /* Handle extend */
-                                               else{
-                                                       if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
-                                                               striptime = 1.0;
+                                                       /* Handle repeat */
+                       
+                                                       else if (striptime < 1.0){
+                                                               /* Mod to repeat */
+                                                               striptime*=strip->repeat;
+                                                               striptime = (float)fmod (striptime, 1.0);
+                                                               
                                                                frametime = (striptime * actlength) + strip->actstart;
-                                                               get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
-#ifdef __NLA_BLENDCON
+                                                               extract_pose_from_action (tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+       #ifdef __NLA_BLENDCON
                                                                do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
-#endif
+       #endif
                                                                doit=1;
                                                        }
-                                               }
+                                                       /* Handle extend */
+                                                       else{
+                                                               if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
+                                                                       striptime = 1.0;
+                                                                       frametime = (striptime * actlength) + strip->actstart;
+                                                                       extract_pose_from_action (tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+       #ifdef __NLA_BLENDCON
+                                                                       do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+       #endif
+                                                                       doit=1;
+                                                               }
+                                                       }
 
-                                               /* Handle blendin & blendout */
-                                               if (doit){
-                                                       /* Handle blendin */
+                                                       /* Handle blendin & blendout */
+                                                       if (doit){
+                                                               /* Handle blendin */
 
-                                                       if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){
-                                                               blendfac = stripframe/strip->blendin;
-                                                       }
-                                                       else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){
-                                                               blendfac = (length-stripframe)/(strip->blendout);
+                                                               if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){
+                                                                       blendfac = stripframe/strip->blendin;
+                                                               }
+                                                               else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){
+                                                                       blendfac = (length-stripframe)/(strip->blendout);
+                                                               }
+                                                               else
+                                                                       blendfac = 1;
+
+                                                               /* Blend this pose with the accumulated pose */
+                                                               blend_poses (apose, tpose, blendfac, strip->mode);
+       #ifdef __NLA_BLENDCON
+                                                               blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode);
+       #endif
                                                        }
-                                                       else
-                                                               blendfac = 1;
-
-                                                       /* Blend this pose with the accumulated pose */
-                                                       blend_poses (apose, tpose, blendfac, strip->mode);
-#ifdef __NLA_BLENDCON
-                                                       blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode);
-#endif
+                                               }                                       
+                                               if (apose){
+                                                       extract_pose_from_pose(ob->pose, apose);
+       #ifdef __NLA_BLENDCON
+                                                       get_constraint_influence_from_pose(ob->pose, apose);
+       #endif
                                                }
-                                       }                                       
-                                       if (apose){
-                                               get_pose_from_pose(&ob->pose, apose);
-#ifdef __NLA_BLENDCON
-                                               get_constraint_influence_from_pose(ob->pose, apose);
-#endif
                                        }
+                                       
                                }
+
+                               /* Do local action (always overrides the nla actions) */
+                               /*      At the moment, only constraint ipos on the local action have any effect */
+                               if(ob->action) {
+                                       extract_pose_from_action (ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
+                                       do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
+                                       doit = 1;
+                               } 
                                
                        }
-
-                       /* Do local action (always overrides the nla actions) */
-                       /*      At the moment, only constraint ipos on the local action have any effect */
-                       if(ob->action) {
-                               get_pose_from_action (&ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
-                               do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
-                               doit = 1;
-                       } 
-                       
-                       if (doit)
-                               apply_pose_armature(get_armature(ob), ob->pose, 1);
-
-               }
-               
+               }               
                if(only_this) break;
                
                base= base->next;
@@ -608,222 +738,15 @@ void do_all_actions(Object *only_this)
        }
 
        if (apose){
-               clear_pose(apose);
+               free_pose_channels(apose);
                MEM_freeN(apose);
                apose = NULL;
        }       
        if (tpose){
-               clear_pose(tpose);
+               free_pose_channels(tpose);
                MEM_freeN(tpose);
                apose = NULL;
        }
 
 }
 
-static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime)
-{
-       bPoseChannel *pchan;
-       bActionChannel *achan;
-
-       if (!pose || !act)
-               return;
-       
-       for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
-               achan=get_named_actionchannel(act, pchan->name);
-               if (achan)
-                       do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime);
-       }
-}
-
-bActionChannel *get_named_actionchannel(bAction *act, const char *name)
-{
-       bActionChannel *chan;
-
-       if (!act)
-               return NULL;
-
-       for (chan = act->chanbase.first; chan; chan=chan->next){
-               if (!strcmp (chan->name, name))
-                       return chan;
-       }
-
-       return NULL;
-}
-
-void clear_pose(bPose *pose) 
-{
-       bPoseChannel *chan;
-       
-       if (pose->chanbase.first){
-               for (chan = pose->chanbase.first; chan; chan=chan->next){
-                       free_constraints(&chan->constraints);
-               }
-               BLI_freelistN (&pose->chanbase);
-       }
-}
-
-void make_local_action(bAction *act)
-{
-       Object *ob;
-       bAction *actn;
-       int local=0, lib=0;
-
-       if(act->id.lib==0) return;
-       if(act->id.us==1) {
-               act->id.lib= 0;
-               act->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)act, 0);
-               return;
-       }
-       
-       ob= G.main->object.first;
-       while(ob) {
-               if(ob->action==act) {
-                       if(ob->id.lib) lib= 1;
-                       else local= 1;
-               }
-               ob= ob->id.next;
-       }
-       
-       if(local && lib==0) {
-               act->id.lib= 0;
-               act->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)act, 0);
-       }
-       else if(local && lib) {
-               actn= copy_action(act);
-               actn->id.us= 0;
-               
-               ob= G.main->object.first;
-               while(ob) {
-                       if(ob->action==act) {
-                               
-                               if(ob->id.lib==0) {
-                                       ob->action = actn;
-                                       ob->activecon = NULL;
-                                       actn->id.us++;
-                                       act->id.us--;
-                               }
-                       }
-                       ob= ob->id.next;
-               }
-       }
-}
-
-
-void free_action(bAction *act)
-{
-       bActionChannel *chan;
-
-       /* Free channels */
-       for (chan=act->chanbase.first; chan; chan=chan->next){
-               if (chan->ipo)
-                       chan->ipo->id.us--;
-               free_constraint_channels(&chan->constraintChannels);
-       }
-
-       if (act->chanbase.first)
-               BLI_freelistN (&act->chanbase);
-}
-
-bAction* copy_action(bAction *src)
-{
-       bAction *dst = NULL;
-       bActionChannel *dchan, *schan;
-       
-       if(!src) return NULL;
-       
-       dst= copy_libblock(src);
-       duplicatelist(&(dst->chanbase), &(src->chanbase));
-
-       for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
-               dchan->ipo = copy_ipo(dchan->ipo);
-               copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
-       }
-       dst->id.flag |= LIB_FAKEUSER;
-       dst->id.us++;
-       return dst;
-}
-
-bPoseChannel *copy_pose_channel(const bPoseChannel* src)
-{
-       bPoseChannel *dst;
-
-       if (!src)
-               return NULL;
-
-       dst = MEM_callocN (sizeof(bPoseChannel), "copyPoseChannel");
-       memcpy (dst, src, sizeof(bPoseChannel));
-       dst->prev=dst->next=NULL;
-
-       return dst;
-}
-
-void copy_pose(bPose **dst, bPose *src, int copycon)
-{
-       bPose *outPose;
-       bPose * inPose;
-       bPoseChannel    *newChan;
-       bPoseChannel *curChan;
-
-       inPose = src;
-       
-       if (!inPose){
-               *dst=NULL;
-               return;
-       }
-
-       outPose=MEM_callocN(sizeof(bPose), "pose");
-
-       for (curChan=inPose->chanbase.first; curChan; curChan=curChan->next){
-               newChan=MEM_callocN(sizeof(bPoseChannel), "copyposePoseChannel");
-
-               strcpy (newChan->name, curChan->name);
-               newChan->flag=curChan->flag;
-
-               memcpy (newChan->loc, curChan->loc, sizeof (curChan->loc));
-               memcpy (newChan->size, curChan->size, sizeof (curChan->size));
-               memcpy (newChan->quat, curChan->quat, sizeof (curChan->quat));
-               Mat4CpyMat4 (newChan->obmat, (void *)curChan->obmat);
-
-               BLI_addtail (&outPose->chanbase, newChan);
-               if (copycon){
-                       copy_constraints(&newChan->constraints, &curChan->constraints);
-               }
-       }
-       
-       *dst=outPose;
-}
-
-bPoseChannel *set_pose_channel(bPose *pose, bPoseChannel *chan)
-{
-       /*      chan is no longer valid for the calling function.
-               and should not be used by that function after calling
-               this one
-       */
-       bPoseChannel    *curChan;
-
-       /*      Determine if an equivalent channel exists already */
-       for (curChan=pose->chanbase.first; curChan; curChan=curChan->next){
-               if (!strcmp (curChan->name, chan->name)){
-                       if (chan->flag & POSE_ROT)
-                               memcpy (curChan->quat, chan->quat, sizeof(chan->quat)); 
-                       if (chan->flag & POSE_SIZE) 
-                               memcpy (curChan->size, chan->size, sizeof(chan->size));
-                       if (chan->flag & POSE_LOC)
-                               memcpy (curChan->loc, chan->loc, sizeof(chan->loc));
-                       if (chan->flag & PCHAN_DONE)
-                               Mat4CpyMat4 (curChan->obmat, chan->obmat);
-
-                       curChan->flag |= chan->flag;
-                       MEM_freeN (chan);
-                       return curChan;
-               }
-       }
-
-       MEM_freeN (chan);
-       return NULL;
-       /* If an equivalent channel doesn't exist, then don't bother setting it. */
-}
-
-
index f92294d..9ff8abf 100644 (file)
@@ -89,7 +89,7 @@ void calc_curvepath(Object *ob)
        /* in a path vertices are with equal differences: path->len = number of verts */
        /* NOW WITH BEVELCURVE!!! */
        
-       if(ob==0 || ob->type != OB_CURVE) return;
+       if(ob==NULL || ob->type != OB_CURVE) return;
        cu= ob->data;
        if(ob==G.obedit) nu= editNurb.first;
        else nu= cu->nurb.first;
@@ -98,10 +98,6 @@ void calc_curvepath(Object *ob)
        cu->path= NULL;
        
        bl= cu->bev.first;
-       if(bl==NULL) {
-               makeDispList(ob);
-               bl= cu->bev.first;
-       }
        if(bl==NULL) return;
 
        cu->path=path= MEM_callocN(sizeof(Path), "path");
@@ -213,11 +209,10 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir)        /* returns OK
        float data[4];
        int cycl=0, s0, s1, s2, s3;
 
-       if(ob==0 || ob->type != OB_CURVE) return 0;
+       if(ob==NULL || ob->type != OB_CURVE) return 0;
        cu= ob->data;
-       if(cu->path==0 || cu->path->data==0) {
-               calc_curvepath(ob);
-               if(cu->path==0 || cu->path->data==0) return 0;
+       if(cu->path==NULL || cu->path->data==NULL) {
+               printf("no path!\n");
        }
        path= cu->path;
        fp= path->data;
@@ -242,7 +237,8 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir)  /* returns OK
        p2= fp + 4*s2;
        p3= fp + 4*s3;
 
-       if(cu->flag & CU_FOLLOW) {
+       /* note, commented out for follow constraint */
+       //if(cu->flag & CU_FOLLOW) {
                
                set_afgeleide_four_ipo(1.0f-fac, data, KEY_BSPLINE);
                
@@ -254,7 +250,7 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir)  /* returns OK
                dir[0]= -dir[0];
                dir[1]= -dir[1];
                dir[2]= -dir[2];
-       }
+       //}
        
        nu= cu->nurb.first;
 
index 1f96b48..6112261 100644 (file)
@@ -6,10 +6,7 @@
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version. 
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,9 +20,7 @@
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
+ * Contributor(s): Full recode, Ton Roosendaal, Crete 2005
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
@@ -50,6 +45,7 @@
 #include "DNA_view3d_types.h"
 #include "DNA_constraint_types.h"
 
+#include "BKE_depsgraph.h"
 #include "BKE_displist.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include <config.h>
 #endif
 
-/*     Function prototypes */
-
-static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit);
-static Bone *get_named_bone_bonechildren (Bone *bone, const char *name);
-static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index);
-/*void make_bone_parent_matrix (Bone* bone);*/
-static void copy_bonechildren (Bone* newBone, Bone* oldBone);
-static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4]);
-static int verify_boneptr_children (Bone *cBone, Bone *tBone);
-static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime);
-static Bone *get_last_ik_bone (Bone *bone);
-static void precalc_bonelist_posemats(ListBase *bonelist, float parlen);
-
-/* Globals */
+/* ugly Globals */
 static float g_premat[4][4];
 static float g_postmat[4][4];
 static MDeformVert *g_dverts;
 static ListBase                *g_defbase;
-static bArmature *g_defarm;
+static Object *g_deform;
+
+/*     **************** Generic Functions, data level *************** */
 
-/*     Functions */
+bArmature *get_armature(Object *ob)
+{
+       if(ob==NULL) return NULL;
+       if(ob->type==OB_ARMATURE) return ob->data;
+       else return NULL;
+}
 
-float get_bone_length (Bone *bone)
+bArmature *add_armature()
 {
-       float result[3];
+       bArmature *arm;
+       
+       arm= alloc_libblock (&G.main->armature, ID_AR, "Armature");
+       return arm;
+}
+
+
+void free_boneChildren(Bone *bone)
+{ 
+       Bone *child;
+       
+       if (bone) {
+               
+               child=bone->childbase.first;
+               if (child){
+                       while (child){
+                               free_boneChildren (child);
+                               child=child->next;
+                       }
+                       BLI_freelistN (&bone->childbase);
+               }
+       }
+}
 
-       VecSubf (result, bone->tail, bone->head);
-       return (float)sqrt(result[0]*result[0] + result[1]*result[1] + result[2]*result[2]);
+void free_bones (bArmature *arm)
+{
+       Bone *bone;
+       /*      Free children (if any)  */
+       bone= arm->bonebase.first;
+       if (bone) {
+               while (bone){
+                       free_boneChildren (bone);
+                       bone=bone->next;
+               }
+       }
+       
+       
+       BLI_freelistN(&arm->bonebase);
+}
 
+void free_armature(bArmature *arm)
+{
+       if (arm) {
+               /*              unlink_armature(arm);*/
+               free_bones(arm);
+       }
 }
 
-void apply_bonemat(Bone *bone)
+void make_local_armature(bArmature *arm)
 {
-       float mat[3][3], imat[3][3], tmat[3][3];
+       int local=0, lib=0;
+       Object *ob;
+       bArmature *newArm;
        
-       if(!bone)
+       if (arm->id.lib==0)
+               return;
+       if (arm->id.us==1) {
+               arm->id.lib= 0;
+               arm->id.flag= LIB_LOCAL;
+               new_id(0, (ID*)arm, 0);
                return;
+       }
+       
+       if(local && lib==0) {
+               arm->id.lib= 0;
+               arm->id.flag= LIB_LOCAL;
+               new_id(0, (ID *)arm, 0);
+       }
+       else if(local && lib) {
+               newArm= copy_armature(arm);
+               newArm->id.us= 0;
+               
+               ob= G.main->object.first;
+               while(ob) {
+                       if(ob->data==arm) {
+                               
+                               if(ob->id.lib==0) {
+                                       ob->data= newArm;
+                                       newArm->id.us++;
+                                       arm->id.us--;
+                               }
+                       }
+                       ob= ob->id.next;
+               }
+       }
+}
 
-       Mat3CpyMat4(mat, bone->obmat);
+static void    copy_bonechildren (Bone* newBone, Bone* oldBone)
+{
+       Bone    *curBone, *newChildBone;
        
-       VECCOPY(bone->loc, bone->obmat[3]);
+       /*      Copy this bone's list*/
+       duplicatelist (&newBone->childbase, &oldBone->childbase);
        
-       Mat3ToQuat(mat, bone->quat);
-       QuatToMat3(bone->quat, tmat);
+       /*      For each child in the list, update it's children*/
+       newChildBone=newBone->childbase.first;
+       for (curBone=oldBone->childbase.first;curBone;curBone=curBone->next){
+               newChildBone->parent=newBone;
+               copy_bonechildren(newChildBone,curBone);
+               newChildBone=newChildBone->next;
+       }
+}
 
-       Mat3Inv(imat, tmat);
+bArmature *copy_armature(bArmature *arm)
+{
+       bArmature *newArm;
+       Bone            *oldBone, *newBone;
+       
+       newArm= copy_libblock (arm);
+       duplicatelist(&newArm->bonebase, &arm->bonebase);
        
-       Mat3MulMat3(tmat, imat, mat);
+       /*      Duplicate the childrens' lists*/
+       newBone=newArm->bonebase.first;
+       for (oldBone=arm->bonebase.first;oldBone;oldBone=oldBone->next){
+               newBone->parent=NULL;
+               copy_bonechildren (newBone, oldBone);
+               newBone=newBone->next;
+       };
        
-       bone->size[0]= tmat[0][0];
-       bone->size[1]= tmat[1][1];
-       bone->size[2]= tmat[2][2];
+       return newArm;
+}
 
+static Bone *get_named_bone_bonechildren (Bone *bone, const char *name)
+{
+       Bone *curBone, *rbone;
+       
+       if (!strcmp (bone->name, name))
+               return bone;
+       
+       for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
+               rbone=get_named_bone_bonechildren (curBone, name);
+               if (rbone)
+                       return rbone;
+       }
+       
+       return NULL;
+}
+
+
+Bone *get_named_bone (bArmature *arm, const char *name)
+/*
+       Walk the list until the bone is found
+ */
+{
+       Bone *bone=NULL, *curBone;
+       
+       if (!arm) return NULL;
+       
+       for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
+               bone = get_named_bone_bonechildren (curBone, name);
+               if (bone)
+                       return bone;
+       }
+       
+       return bone;
 }
 
+/* ****************** Game Blender functions, called by engine ************** */
+
 void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4])
 {
        float obinv[4][4];
-#if 0
-       Mat4Invert(obinv, obmat);
-       Mat4CpyMat4(premat, obmat);
-       Mat4MulMat4(postmat, parmat, obinv);
 
-       Mat4Invert (postmat, premat);
-#else
        Mat4Invert(obinv, obmat);
        Mat4CpyMat4(premat, obmat);
        Mat4MulMat4(postmat, parmat, obinv);
 
        Mat4Invert (premat, postmat);
-#endif
 }
 
 void GB_init_armature_deform(ListBase *defbase, float premat[][4], float postmat[][4])
@@ -176,7 +287,7 @@ void GB_calc_armature_deform (float *co, MDeformVert *dvert)
        
        for (i=0; i<dvert->totweight; i++){
                bone = dvert->dw[i].data;
-               if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib);
+//             if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib);
        }
        
        if (contrib){
@@ -189,207 +300,13 @@ void GB_calc_armature_deform (float *co, MDeformVert *dvert)
        Mat4MulVecfl(g_postmat, co);
 }
 
-static Bone *get_last_ik_bone (Bone *bone)
-{
-       Bone *curBone;
-
-       for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
-               if (curBone->flag & BONE_IK_TOPARENT){
-                       return get_last_ik_bone (curBone);
-               }
-       }
-
-       return bone;
-}
-
-#if 0
-static Bone *get_first_ik_bone (Bone *bone)
-{
-       Bone *curBone;
-
-       for (curBone = bone; curBone; curBone=curBone->parent){
-               if (!bone->parent)
-                       return curBone;
-               if (!bone->flag & BONE_IK_TOPARENT)
-                       return curBone;
-       }
-
-       return bone;
-/*     for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
-               if (curBone->flag & BONE_IK_TOPARENT){
-                       return get_last_ik_bone (curBone);
-               }
-       }
-*/
-       return bone;
-
-}
-#endif
-
-void where_is_bone(Object *ob, Bone *bone)
-{
-       where_is_bone_time (ob, bone, G.scene->r.cfra);
-}
-
-void where_is_bone_time (Object *ob, Bone *bone, float ctime)
-{ 
-       where_is_bone1_time (ob, get_last_ik_bone(bone), ctime);
-}
-
-void rebuild_bone_parent_matrix (Bone *bone)
-{
-       if (!bone)
-               return;
-
-       if (bone->parent)
-               rebuild_bone_parent_matrix(bone->parent);
-
-       /* Get the parent inverse */
-       if (bone->parent)
-               Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat);
-       else
-               Mat4One (bone->parmat);
-
-}
-void where_is_bone1_time (Object *ob, Bone *bone, float ctime)
-/* Assumes the pose has already been retrieved from the action */
-/* Also assumes where_is_object has been called for owner */
-{
-       bPose   *pose;
-       bPoseChannel    *chan;
-       bArmature *arm;
-       float   imat[4][4];
-       float   totmat[4][4];
-       Object conOb;
-
-       pose = ob->pose;
-       if (!pose)
-               return;
-       
-       arm = get_armature(ob);
-
-       /* Ensure there is a channel for this bone*/
-       chan = verify_pose_channel (pose, bone->name);
-       if (!chan) return;
-
-#if 1
-       /* If 1 attempt to use pose caching features */
-       /* Bail out if we've been recalced recently */
-       if (chan->flag & PCHAN_DONE){
-               Mat4CpyMat4 (bone->obmat, chan->obmat);
-               if (bone->parent){
-                       if ((bone->flag & BONE_IK_TOPARENT))
-                               where_is_bone1_time (ob, bone->parent, ctime);
-                       else
-                               where_is_bone_time (ob, bone->parent, ctime);
-               }
-               return;
-       }
-       else
-               chan->flag |= PCHAN_DONE;
-#endif
-
-#if 1
-       /* Ensure parents have been evaluated */
-       if (bone->parent){
-               if ((bone->flag & BONE_IK_TOPARENT))
-                       where_is_bone1_time (ob, bone->parent, ctime);
-               else
-                       where_is_bone_time (ob, bone->parent, ctime);
-       }
-
-#endif
-
-       if (arm){
-               if ((arm->flag & ARM_RESTPOS) || ((G.obedit && (ob->data == G.obedit->data)))){
-                       Mat4One (bone->obmat);
-                       Mat4One (chan->obmat);
-                       return;
-               }
-       }
-
-       /* If the bone has been flagged as 'no calc', let's not
-        * bother calculating it.
-        */
-       if (bone->flag & BONE_NOCALC) {
-               return;
-       }
-
-       if (bone->flag & BONE_IK_TOPARENT){
-               bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F;
-       }
-       bone_to_mat4(bone, bone->obmat);        
-       
-       /* Do constraints */
-       //      clear_workob();
-       
-       memset(&conOb, 0, sizeof(Object));      
-       conOb.size[0]= conOb.size[1]= conOb.size[2]= 1.0;
-       
-       /* Collect the constraints from the pose */
-       conOb.constraints.first = chan->constraints.first;
-       conOb.constraints.last = chan->constraints.last;
-       
-       /* Totmat takes bone's obmat to worldspace */
-       
-       {
-               float parmat[4][4];
-               float temp[4][4];
-               
-               Mat4CpyMat4 (temp, bone->obmat);
-               Mat4One (bone->obmat);
-               get_objectspace_bone_matrix(bone, parmat, 1, 1);
-               Mat4CpyMat4 (bone->obmat, temp);
-               Mat4MulMat4 (totmat, parmat, ob->obmat);
-       }
-       
-       /* Build a workob to pass the bone to the constraint solver */
-       conOb.data = ob->data;
-       conOb.type = ob->type;
-       conOb.parent = ob;      
-       conOb.trackflag = ob->trackflag;
-       conOb.upflag = ob->upflag;
-
-       VECCOPY(conOb.size, bone->size);
-       
-       Mat4MulMat4 (conOb.obmat, bone->obmat, totmat);
-       
-       /* Solve */
-       solve_constraints (&conOb, TARGET_BONE, (void*)bone, ctime);
-       
-       {
-               float parmat[4][4];
-               float temp[4][4];
-               
-               Mat4CpyMat4 (temp, bone->obmat);
-               Mat4One (bone->obmat);
-               get_objectspace_bone_matrix(bone, parmat, 1, 1);
-               Mat4CpyMat4 (bone->obmat, temp);
-               Mat4MulMat4 (totmat, parmat, ob->obmat);
-       }
-
-       VECCOPY(bone->size, conOb.size);
-       
-       /* Take out of worldspace */
-       Mat4Invert (imat, totmat);
-       Mat4MulMat4 (bone->obmat, conOb.obmat, imat);
-       Mat4CpyMat4 (chan->obmat, bone->obmat);
-
-}
-
-
-bArmature *get_armature(Object *ob)
-{
-       if(ob==NULL) return NULL;
-       if(ob->type==OB_ARMATURE) return ob->data;
-       else return NULL;
-}
+/* ****************** END Game Blender functions, called by engine ************** */
+/* ************ Armature Deform ******************* */
 
 void init_armature_deform(Object *parent, Object *ob)
 {
        bArmature *arm;
        bDeformGroup *dg;
-       Bone *curBone;
        MDeformVert *dvert;
        int     totverts;
        float   obinv[4][4];
@@ -399,18 +316,8 @@ void init_armature_deform(Object *parent, Object *ob)
        if (!arm)
                return;
 
-       if (ob)
-               where_is_object (ob);
-
-#if 1
-       apply_pose_armature (arm, parent->pose, 1);     /* Hopefully doit parameter can be set to 0 in future */
-       where_is_armature (parent);
-#else
-       apply_pose_armature (arm, parent->pose, 0);
-#endif
-
        g_defbase = &ob->defbase;
-       g_defarm = arm;
+       g_deform = parent;
 
        Mat4Invert(obinv, ob->obmat);
        Mat4CpyMat4(g_premat, ob->obmat);
@@ -428,17 +335,12 @@ void init_armature_deform(Object *parent, Object *ob)
                totverts=0;
        }
 
-       /* Precalc bone defmats */
-       precalc_armature_posemats (arm);
-
-       for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
-               precalc_bone_defmat(curBone);
-       }
+       /* bone defmats are already in the channels, chan_mat */
        
-       /* Validate bone data in bDeformGroups */
+       /* Validate channel data in bDeformGroups */
 
        for (dg=g_defbase->first; dg; dg=dg->next)
-               dg->data = (void*)get_named_bone(arm, dg->name);
+               dg->data = (void*)get_pose_channel(parent->pose, dg->name);
 
        if (g_dverts){
                for (j=0; j<totverts; j++){
@@ -456,114 +358,6 @@ void init_armature_deform(Object *parent, Object *ob)
        }
 }
 
-void get_bone_root_pos (Bone* bone, float vec[3], int posed)
-{
-       Bone    *curBone;
-       float   mat[4][4];
-       
-       get_objectspace_bone_matrix(bone, mat, 1, posed);
-       VECCOPY (vec, mat[3]);
-       return;
-
-       rebuild_bone_parent_matrix(bone);
-       if (posed){
-
-               get_objectspace_bone_matrix(bone, mat, 1, posed);
-               VECCOPY (vec, mat[3]);
-       }
-       else {
-               vec[0]=vec[1]=vec[2]=0.0F;
-               for (curBone=bone; curBone; curBone=curBone->parent){
-                       if (curBone==bone)
-                               VecAddf (vec, vec, curBone->head);
-                       else
-                               VecAddf (vec, vec, curBone->tail);
-               }
-       }
-}
-
-void get_bone_tip_pos (Bone* bone, float vec[3], int posed)
-{
-       Bone    *curBone;
-       float   mat[4][4], tmat[4][4], rmat[4][4], bmat[4][4], fmat[4][4];
-
-       get_objectspace_bone_matrix(bone, mat, 0, posed);
-       VECCOPY (vec, mat[3]);
-       return;
-
-       rebuild_bone_parent_matrix(bone);
-       if (posed){
-       
-       Mat4One (mat);
-
-       for (curBone = bone; curBone; curBone=curBone->parent){
-               Mat4One (bmat);
-               /*      [BMAT] This bone's offset */
-               VECCOPY (bmat[3], curBone->head);
-               if (curBone==bone){
-                       Mat4One (tmat);
-                       VecSubf (tmat[3], curBone->tail, curBone->head);
-                       Mat4MulMat4 (bmat, tmat, curBone->obmat);
-                       VecAddf (bmat[3], bmat[3], curBone->head);
-               }
-               else
-                       VecAddf (bmat[3], bmat[3], curBone->obmat[3]);  // Test
-
-               /* [RMAT] Parent's bone length = parent rotmat * bone length */
-               if (curBone->parent){
-                       Mat4One (tmat);
-                       VecSubf (tmat[3], curBone->parent->tail, curBone->parent->head);
-                       Mat4MulMat4 (rmat, tmat, curBone->parent->obmat);
-                       VecSubf (rmat[3], rmat[3], curBone->parent->obmat[3]);
-               }
-               else
-                       Mat4One (rmat);
-
-               Mat4MulSerie (fmat, rmat, bmat, mat, 0, 0, 0, 0, 0);
-               Mat4CpyMat4 (mat, fmat);
-       }
-
-               VECCOPY (vec, mat[3]);
-       }
-       else{
-               vec[0]=vec[1]=vec[2]=0.0F;
-               for (curBone=bone; curBone; curBone=curBone->parent){
-                       VecAddf (vec, vec, curBone->tail);
-               }
-       }
-}
-
-int    verify_boneptr (bArmature *arm, Bone *bone)
-{
-       /* Ensures that a given bone exists in an armature */
-       Bone *curBone;
-
-       if (!arm)
-               return 0;
-
-       for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
-               if (verify_boneptr_children (curBone, bone))
-                       return 1;
-       }
-
-       return 0;
-}
-
-static int verify_boneptr_children (Bone *cBone, Bone *tBone)
-{
-       Bone *curBone;
-
-       if (cBone == tBone)
-               return 1;
-
-       for (curBone=cBone->childbase.first; curBone; curBone=curBone->next){
-               if (verify_boneptr_children (curBone, tBone))
-                       return 1;
-       }
-       return 0;
-}
-
-
 float dist_to_bone (float vec[3], float b1[3], float b2[3])
 {
 /*     float dist=0; */
@@ -592,137 +386,41 @@ float dist_to_bone (float vec[3], float b1[3], float b2[3])
        else {
                return (hsqr - (a*a));
        }
-       
-
 }
 
-static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4])
+static float calc_armature_deform_bone(Bone *bone, bPoseChannel *pchan, float *vec, float *co)
 {
-       Bone *curBone;
-       float   root[3];
-       float   tip[3];
        float   dist, fac, ifac;
        float   cop[3];
-       float   bdsqr;
-
-       
-       get_bone_root_pos (bone, root, 0);
-       get_bone_tip_pos (bone, tip, 0);
+       float   bdsqr, contrib=0.0;
 
        bdsqr = bone->dist*bone->dist;
        VECCOPY (cop, co);
 
-       dist = dist_to_bone(cop, root, tip);
+       dist = dist_to_bone(cop, bone->arm_head, bone->arm_tail);
        
        if ((dist) <= bdsqr){
                fac = (dist)/bdsqr;
                ifac = 1.0F-fac;
                
                ifac*=bone->weight;
-               
-               if (!vec)
-                       (*contrib) +=ifac;
-               else{
-                       ifac*=(1.0F/(*contrib));
+               contrib= ifac;
+               if(contrib>0.0) {
 
                        VECCOPY (cop, co);
                        
-                       Mat4MulVecfl(bone->defmat, cop);
+                       Mat4MulVecfl(pchan->chan_mat, cop);
                        
                        VecSubf (cop, cop, co); //      Make this a delta from the base position
                        cop[0]*=ifac; cop[1]*=ifac; cop[2]*=ifac;
                        VecAddf (vec, vec, cop);
-
                }
        }
        
-//     calc_bone_deform (bone, bone->weight, vec, co, contrib, obmat);
-       for (curBone = bone->childbase.first; curBone; curBone=curBone->next)
-               calc_armature_deform_bonechildren (curBone, vec, co, contrib, obmat);
-}
-
-void precalc_bone_irestmat (Bone *bone)
-{
-       float restmat[4][4];
-
-       get_objectspace_bone_matrix(bone, restmat, 1, 0);
-       Mat4Invert (bone->irestmat, restmat);
+       return contrib;
 }
 
-static void precalc_bonelist_posemats(ListBase *bonelist, float parlen)
-{
-       Bone *curBone;
-       float length;
-       float T_parlen[4][4];
-       float T_root[4][4];
-       float M_obmat[4][4];
-       float R_bmat[4][4];
-       float M_accumulatedMatrix[4][4];
-       float delta[3];
-
-       for (curBone = bonelist->first; curBone; curBone=curBone->next){
-
-               /* Get the length translation (length along y axis) */
-               length = get_bone_length(curBone);
-
-               /* Get the bone's root offset (in the parent's coordinate system) */
-               Mat4One (T_root);
-               VECCOPY (T_root[3], curBone->head);
-
-               /* Compose the restmat */
-               VecSubf(delta, curBone->tail, curBone->head);
-               make_boneMatrixvr(R_bmat, delta, curBone->roll);
-
-               /* Retrieve the obmat (user transformation) */
-               Mat4CpyMat4 (M_obmat, curBone->obmat);
-
-               /* Compose the accumulated matrix (i.e. parent matrix * parent translation ) */
-               if (curBone->parent){
-                       Mat4One (T_parlen);
-                       T_parlen[3][1] = parlen;
-                       Mat4MulMat4 (M_accumulatedMatrix, T_parlen, curBone->parent->posemat);
-               }
-               else
-                       Mat4One (M_accumulatedMatrix);
-
-               /* Compose the matrix for this bone  */
-               Mat4MulSerie (curBone->posemat, M_accumulatedMatrix, T_root, R_bmat, M_obmat, NULL, NULL, NULL, NULL);
-
-               precalc_bonelist_posemats(&curBone->childbase, length);
-       }
-}
-
-void precalc_armature_posemats (bArmature *arm)
-{
-       precalc_bonelist_posemats(&arm->bonebase, 0.0);
-}
-
-void precalc_bone_defmat (Bone *bone)
-{
-       Bone *curBone;
-#if 0
-       float restmat[4][4];
-       float posemat[4][4];
-       float imat[4][4];
-       
-       /* Store restmat and restmat inverse - Calculate once when leaving editmode */
-       /* Store all bones' posemats - Do when applied */
-
-       /* EXPENSIVE! Don't do this! */
-       get_objectspace_bone_matrix(bone, restmat, 1, 0);
-       get_objectspace_bone_matrix(bone, posemat, 1, 1);
-       Mat4Invert (imat, restmat);
-       Mat4MulMat4 (bone->defmat, imat, posemat);
-       /* /EXPENSIVE */
-#else
-       Mat4MulMat4 (bone->defmat, bone->irestmat, bone->posemat);
-#endif
-       for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
-               precalc_bone_defmat(curBone);
-       }
-}
-
-void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *contrib)
+void calc_bone_deform (bPoseChannel *pchan, float weight, float *vec, float *co, float *contrib)
 {
        float   cop[3];
 
@@ -731,7 +429,7 @@ void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *c
 
        VECCOPY (cop, co);
        
-       Mat4MulVecfl(bone->defmat, cop);
+       Mat4MulVecfl(pchan->chan_mat, cop);
        
        vec[0]+=(cop[0]-co[0])*weight;
        vec[1]+=(cop[1]-co[1])*weight;
@@ -742,540 +440,638 @@ void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *c
 
 void calc_armature_deform (Object *ob, float *co, int index)
 {
-       bArmature *arm;
-       Bone *bone;
-       Bone    *curBone;
+       bPoseChannel *pchan;
+       MDeformVert *dvert = g_dverts+index;
        float   vec[3];
-       float   contrib=0;
+       float   contrib=0.0;
        int             i;
-       MDeformVert *dvert = g_dverts+index;
 
-       arm=g_defarm;
        vec[0]=vec[1]=vec[2]=0;
 
        /* Apply the object's matrix */
        Mat4MulVecfl(g_premat, co);
 
+       /* using deform vertex groups */
        if (g_dverts){
+               
                for (i=0; i<dvert->totweight; i++){
-                       bone = dvert->dw[i].data;
-                       if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib);
+                       pchan = (bPoseChannel *)dvert->dw[i].data;
+                       if (pchan) calc_bone_deform (pchan, dvert->dw[i].weight, vec, co, &contrib);
                }
+       }
+       else {  /* or use bone distances */
+               Bone *bone;
                
-               if (contrib){
-                       vec[0]/=contrib;
-                       vec[1]/=contrib;
-                       vec[2]/=contrib;
+               for(pchan= g_deform->pose->chanbase.first; pchan; pchan= pchan->next) {
+                       bone= pchan->bone;
+                       if(bone) {
+                               contrib+= calc_armature_deform_bone(bone, pchan, vec, co);
+                       }
                }
-               VecAddf (co, vec, co);
-               Mat4MulVecfl(g_postmat, co);
-               return;
-       }
-
 
-       //      Count the number of interested bones
-       for (curBone = arm->bonebase.first; curBone; curBone=curBone->next)
-               calc_armature_deform_bonechildren (curBone, NULL, co, &contrib, ob->obmat);
-
-       //      Do the deformation
-       for (curBone = arm->bonebase.first; curBone; curBone=curBone->next)
-               calc_armature_deform_bonechildren (curBone, vec, co, &contrib, ob->obmat);
+       }
+       if (contrib>0.0){
+               vec[0]/=contrib;
+               vec[1]/=contrib;
+               vec[2]/=contrib;
+       }
 
        VecAddf (co, vec, co);
        Mat4MulVecfl(g_postmat, co);
 }
 
-void apply_pose_armature (bArmature* arm, bPose* pose, int doit)
-{
-       Bone    *curBone;
-       for (curBone = arm->bonebase.first; curBone; curBone=curBone->next){
-               apply_pose_bonechildren (curBone, pose, doit);
-       }
-}
+/* ************ END Armature Deform ******************* */
 
-void where_is_armature (Object *ob)
+void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed)
 {
-       where_is_object (ob);
-       where_is_armature_time(ob, (float)G.scene->r.cfra);
+       Mat4CpyMat4(M_accumulatedMatrix, bone->arm_mat);
 }
 
-void where_is_armature_time (Object *ob, float ctime)
+#if 0
+/* IK in the sense of; connected directly */
+static Bone *get_last_ik_bone (Bone *bone)
 {
-       bArmature *arm;
-
-       arm = get_armature(ob);
-       if (!arm)
-               return;
+       Bone *curBone;
+       
+       for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
+               if (curBone->flag & BONE_IK_TOPARENT){
+                       return get_last_ik_bone (curBone);
+               }
+       }
+       
+       return bone;
+}
 
-       where_is_bonelist_time (ob, &arm->bonebase, ctime);
+#endif
 
-}
+/* **************** The new & simple (but OK!) armature evaluation ********* */ 
 
-static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime)
-{
-       Bone *curBone;
+/*  ****************** And how it works! ****************************************
 
-       for (curBone=base->first; curBone; curBone=curBone->next){
-               if (!curBone->childbase.first)
-                       where_is_bone1_time (ob, curBone, ctime);
+  This is the bone transformation trick; they're hierarchical so each bone(b)
+  is in the coord system of bone(b-1):
 
-               where_is_bonelist_time(ob, &curBone->childbase, ctime);
-       }
-}
-static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit)
-{
-       Bone    *curBone;
-       bPoseChannel    *chan;
+  arm_mat(b)= arm_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) 
+  
+  -> yoffs is just the y axis translation in parent's coord system
+  -> d_root is the translation of the bone root, also in parent's coord system
 
-       if (!pose){
-               
-               bone->dsize[0]=bone->dsize[1]=bone->dsize[2]=1.0F;
-               bone->size[0]=bone->size[1]=bone->size[2]=1.0F;
+  pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b)
 
-               bone->dquat[0]=bone->dquat[1]=bone->dquat[2]=bone->dquat[3]=0;
-               bone->quat[0]=bone->quat[1]=bone->quat[2]=bone->quat[3]=0.0F;
-               
-               bone->dloc[0]=bone->dloc[1]=bone->dloc[2]=0.0F;
-               bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F;
-       }
+  we then - in init deform - store the deform in chan_mat, such that:
 
-       // Ensure there is a channel for this bone 
-       chan = verify_pose_channel (pose, bone->name);
+  pose_mat(b)= arm_mat(b) * chan_mat(b)
+  
+  *************************************************************************** */
 
-       /* Only do this crazy stuff if the no calc flag
-        * is cleared for this bone.
-        */
-       if (chan && (~bone->flag & BONE_NOCALC)) {
-               if (chan->flag & POSE_LOC) 
-                       memcpy (bone->loc, chan->loc, sizeof (bone->loc));
-               if (chan->flag & POSE_SIZE) 
-                       memcpy (bone->size, chan->size, sizeof (bone->size));
-               if (chan->flag & POSE_ROT) 
-                       memcpy (bone->quat, chan->quat, sizeof (bone->quat));                   
-
-               if (doit){
-                       bone_to_mat4(bone, bone->obmat);
-               }
-               else{
-                       Mat4CpyMat4 (bone->obmat, chan->obmat);
-               }
-       }
-       
-       for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
-               apply_pose_bonechildren (curBone, pose, doit);
-       }
-}
 
-void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll)
 /*     Calculates the rest matrix of a bone based
        On its vector and a roll around that vector */
+void vec_roll_to_mat3(float *vec, float roll, float mat[][3])
 {
-       float   nor[3],axis[3],target[3]={0,1,0};
+       float   nor[3], axis[3], target[3]={0,1,0};
        float   theta;
-       float   rMatrix[3][3], bMatrix[3][3], fMatrix[3][3];
-
-       VECCOPY (nor,delta);
+       float   rMatrix[3][3], bMatrix[3][3];
+       
+       VECCOPY (nor, vec);
        Normalise (nor);
-
+       
        /*      Find Axis & Amount for bone matrix*/
        Crossf (axis,target,nor);
-
+       
        if (Inpf(axis,axis) > 0.0000000000001) {
                /* if nor is *not* a multiple of target ... */
                Normalise (axis);
                theta=(float) acos (Inpf (target,nor));
-
+               
                /*      Make Bone matrix*/
                VecRotToMat3(axis, theta, bMatrix);
        }
        else {
                /* if nor is a multiple of target ... */
                float updown;
-
+               
                /* point same direction, or opposite? */
                updown = ( Inpf (target,nor) > 0 ) ? 1.0 : -1.0;
-
+               
                /* I think this should work ... */
                bMatrix[0][0]=updown; bMatrix[0][1]=0.0;    bMatrix[0][2]=0.0;
                bMatrix[1][0]=0.0;    bMatrix[1][1]=updown; bMatrix[1][2]=0.0;
                bMatrix[2][0]=0.0;    bMatrix[2][1]=0.0;    bMatrix[2][2]=1.0;
        }
-
+       
        /*      Make Roll matrix*/
        VecRotToMat3(nor, roll, rMatrix);
        
        /*      Combine and output result*/
-       Mat3MulMat3 (fMatrix,rMatrix,bMatrix);
-       Mat4CpyMat3 (outmatrix,fMatrix);
-}
-
-void make_boneMatrix (float outmatrix[][4], Bone *bone)
-/*     Calculates the rest matrix of a bone based
-       On its vector and a roll around that vector */
-{
-       float   delta[3];
-       float   parmat[4][4], imat[4][4], obmat[4][4];
-
-       if (bone->parent){
-               VecSubf (delta, bone->parent->tail, bone->parent->head);
-               make_boneMatrixvr(parmat, delta, bone->parent->roll);
-       }
-       else{
-               Mat4One (parmat);
-       }
-
-       Mat4Invert (imat, parmat);
-       
-       VecSubf (delta, bone->tail, bone->head);
-       make_boneMatrixvr(obmat, delta, bone->roll);
-
-       Mat4MulMat4(outmatrix, obmat, imat);
-
+       Mat3MulMat3 (mat, rMatrix, bMatrix);
 }
 
 
-bArmature *add_armature()
+/* recursive part, calculates restposition of entire tree of children */
+/* used by exiting editmode too */
+void where_is_armature_bone(Bone *bone, Bone *prevbone)
 {
-       bArmature *arm;
-
-       arm= alloc_libblock (&G.main->armature, ID_AR, "Armature");
-
-       if(arm) {
-
+       float vec[3];
        
-       }
-       return arm;
-}
-
-
-void free_boneChildren(Bone *bone)
-{ 
-       Bone *child;
-
-       if (bone) {
+       /* Bone Space */
+       VecSubf (vec, bone->tail, bone->head);
+       vec_roll_to_mat3(vec, bone->roll, bone->bone_mat);
 
-               child=bone->childbase.first;
-               if (child){
-                       while (child){
-                               free_boneChildren (child);
-                               child=child->next;
-                       }
-                       BLI_freelistN (&bone->childbase);
-               }
-       }
-}
-
-void free_bones (bArmature *arm)
-{
-       Bone *bone;
-       /*      Free children (if any)  */
-       bone= arm->bonebase.first;
-       if (bone) {
-               while (bone){
-                       free_boneChildren (bone);
-                       bone=bone->next;
-               }
-       }
-       
-       
-       BLI_freelistN(&arm->bonebase);
-}
-
-void free_armature(bArmature *arm)
-{
-       if (arm) {
-/*             unlink_armature(arm);*/
-               free_bones(arm);
-       }
-}
-
-void make_local_armature(bArmature *arm)
-{
-       int local=0, lib=0;
-       Object *ob;
-       bArmature *newArm;
-
-       if (arm->id.lib==0)
-               return;
-       if (arm->id.us==1) {
-               arm->id.lib= 0;
-               arm->id.flag= LIB_LOCAL;
-               new_id(0, (ID*)arm, 0);
-               return;
-       }
-
-       if(local && lib==0) {
-               arm->id.lib= 0;
-               arm->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)arm, 0);
-       }
-       else if(local && lib) {
-               newArm= copy_armature(arm);
-               newArm->id.us= 0;
-               
-               ob= G.main->object.first;
-               while(ob) {
-                       if(ob->data==arm) {
-                               
-                               if(ob->id.lib==0) {
-                                       ob->data= newArm;
-                                       newArm->id.us++;
-                                       arm->id.us--;
-                               }
-                       }
-                       ob= ob->id.next;
-               }
+       bone->length= VecLenf(bone->head, bone->tail);
+       
+       if(prevbone) {
+               float offs_bone[4][4];  // yoffs(b-1) + root(b) + bonemat(b)
+               
+               /* bone transform itself */
+               Mat4CpyMat3(offs_bone, bone->bone_mat);
+                               
+               /* The bone's root offset (is in the parent's coordinate system) */
+               VECCOPY(offs_bone[3], bone->head);
+
+               /* Get the length translation of parent (length along y axis) */
+               offs_bone[3][1]+= prevbone->length;
+               
+               /* Compose the matrix for this bone  */
+               Mat4MulMat4(bone->arm_mat, offs_bone, prevbone->arm_mat);
+       }
+       else {
+               Mat4CpyMat3(bone->arm_mat, bone->bone_mat);
+               VECCOPY(bone->arm_mat[3], bone->head);
+       }
+       
+       /* head */
+       VECCOPY(bone->arm_head, bone->arm_mat[3]);
+       /* tail is in current local coord system */
+       VECCOPY(vec, bone->arm_mat[1]);
+       VecMulf(vec, bone->length);
+       VecAddf(bone->arm_tail, bone->arm_head, vec);
+       
+       /* and the kiddies */
+       prevbone= bone;
+       for(bone= bone->childbase.first; bone; bone= bone->next) {
+               where_is_armature_bone(bone, prevbone);
        }
 }
 
-static void    copy_bonechildren (Bone* newBone, Bone* oldBone)
+/* updates vectors and matrices on rest-position level, only needed 
+   after editing armature itself, now only on reading file */
+void where_is_armature (bArmature *arm)
 {
-       Bone    *curBone, *newChildBone;
+       Bone *bone;
+       
+       /* hierarchical from root to children */
+       for(bone= arm->bonebase.first; bone; bone= bone->next) {
+               where_is_armature_bone(bone, NULL);
+       }
+}
 
-       /*      Copy this bone's list*/
-       duplicatelist (&newBone->childbase, &oldBone->childbase);
+static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int depth, int counter)
+{
+       bPoseChannel *pchan = verify_pose_channel (pose, bone->name);   // verify checks and/or adds
 
-       /*      For each child in the list, update it's children*/
-       newChildBone=newBone->childbase.first;
-       for (curBone=oldBone->childbase.first;curBone;curBone=curBone->next){
-               newChildBone->parent=newBone;
-               copy_bonechildren(newChildBone,curBone);
-               newChildBone=newChildBone->next;
+       pchan->bone= bone;
+       pchan->parent= parchan;
+       pchan->depth= depth;
+       counter++;
+       
+       for(bone= bone->childbase.first; bone; bone= bone->next) {
+               counter= rebuild_pose_bone(pose, bone, pchan, depth+1, counter);
        }
+       
+       return counter;
 }
 
-bArmature *copy_armature(bArmature *arm)
+/* only after leave editmode, but also for validating older files */
+/* NOTE: pose->flag is set for it */
+void armature_rebuild_pose(Object *ob, bArmature *arm)
 {
-       bArmature *newArm;
-       Bone            *oldBone, *newBone;
+       Bone *bone;
+       bPose *pose;
+       bPoseChannel *pchan, *next;
+       int counter=0;
+               
+       /* only done here */
+       if(ob->pose==NULL) ob->pose= MEM_callocN(sizeof(bPose), "new pose");
+       pose= ob->pose;
+       
+       /* first step, check if all channels are there, also sets depth */
+       for(bone= arm->bonebase.first; bone; bone= bone->next) {
+               counter= rebuild_pose_bone(pose, bone, NULL, 0, counter);
+       }
+       /* sort channels on dependency order, so we can walk the channel list */
 
-       newArm= copy_libblock (arm);
-       duplicatelist(&newArm->bonebase, &arm->bonebase);
+       /* and a check for garbage */
+       for(pchan= pose->chanbase.first; pchan; pchan= next) {
+               next= pchan->next;
+               if(pchan->bone==NULL) {
+                       BLI_freelinkN(&pose->chanbase, pchan);  // constraints?
+               }
+       }
+       //printf("rebuild pose, %d bones\n", counter);
+       if(counter<2) return;
+       
+       update_pose_constraint_flags(ob->pose); // for IK detection for example
+       
+       /* the sorting */
+       DAG_pose_sort(ob);
+       
+       ob->pose->flag &= ~POSE_RECALC;
+}
 
-       /*      Duplicate the childrens' lists*/
-       newBone=newArm->bonebase.first;
-       for (oldBone=arm->bonebase.first;oldBone;oldBone=oldBone->next){
-               newBone->parent=NULL;
-               copy_bonechildren (newBone, oldBone);
-               newBone=newBone->next;
-       };
 
-       return newArm;
-}
+/* ********************** THE IK SOLVER ******************* */
 
 
-void bone_to_mat3(Bone *bone, float mat[][3])  /* no parent */
+/* allocates PoseChain, and links that to root bone/channel */
+/* note; if we got this working, it can become static too? */
+static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
 {
-       float smat[3][3];
-       float rmat[3][3];
-/*     float q1[4], vec[3];*/
-       
-       /* size */
-/*     if(bone->ipo) {
-               vec[0]= bone->size[0]+bone->dsize[0];
-               vec[1]= bone->size[1]+bone->dsize[1];
-               vec[2]= bone->size[2]+bone->dsize[2];
-               SizeToMat3(vec, smat);
-       }
-       else 
-*/     {
-               SizeToMat3(bone->size, smat);
+       bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256];
+       PoseChain *chain;
+       bConstraint *con;
+       bKinematicConstraint *data;
+       int a, segcount= 0;
+       
+       /* find IK constraint, and validate it */
+       for(con= pchan_tip->constraints.first; con; con= con->next) {
+               if(con->type==CONSTRAINT_TYPE_KINEMATIC) break;
        }
-
-       /* rot */
-       /*if(bone->flag & BONE_QUATROT) {
-               if(bone->ipo) {
-                       QuatMul(q1, bone->quat, bone->dquat);
-                       QuatToMat3(q1, rmat);
-               }
-               else 
-       */      {
-                       NormalQuat(bone->quat);
-                       QuatToMat3(bone->quat, rmat);
+       if(con==NULL) return;
+       if(con->flag & CONSTRAINT_DISABLE) return;  // not sure...
+       
+       data=(bKinematicConstraint*)con->data;
+       if(data->tar==NULL) return;
+       
+       /* Find the chain's root & count the segments needed */
+       for (curchan = pchan_tip; curchan; curchan=curchan->parent){
+               pchan_root = curchan;
+               /* tip is not in the chain */
+               if (curchan!=pchan_tip){
+                       chanlist[segcount]=curchan;
+                       segcount++;
                }
-/*     }
-*/
-       Mat3MulMat3(mat, rmat, smat);
+               if(segcount>255) break; // also weak
+               
+               if (!(curchan->bone->flag & BONE_IK_TOPARENT))
+                       break;
+       }
+       if (!segcount) return;
+       
+       /* setup the chain data */
+       chain = MEM_callocN(sizeof(PoseChain), "posechain");
+       chain->totchannel= segcount;
+       chain->solver = IK_CreateChain();
+       chain->con= con;
+       
+       chain->iterations = data->iterations;
+       chain->tolerance = data->tolerance;
+       
+       chain->pchanchain= MEM_callocN(segcount*sizeof(void *), "channel chain");
+       for(a=0; a<segcount; a++) {
+               chain->pchanchain[a]= chanlist[segcount-a-1];
+       }
+       
+       /* AND! link the chain to the root */
+       BLI_addtail(&pchan_root->chain, chain);
 }
 
-void bone_to_mat4(Bone *bone, float mat[][4])
+/* called from within the core where_is_pose loop, all animsystems and constraints
+were executed & assigned. Now as last we do an IK pass */
+static void execute_posechain(Object *ob, PoseChain *chain)
 {
-       float tmat[3][3];
+       IK_Segment_Extern       *segs;
+       bPoseChannel *pchan;
+       float R_parmat[3][3];
+       float iR_parmat[3][3];
+       float R_bonemat[3][3];
+       float rootmat[4][4], imat[4][4];
+       float size[3];
+       int curseg;
+       
+       /* first set the goal inverse transform, assuming the root of chain was done ok! */
+       pchan= chain->pchanchain[0];
+       Mat4One(rootmat);
+       VECCOPY(rootmat[3], pchan->pose_head);
        
-       bone_to_mat3(bone, tmat);
+       Mat4MulMat4 (imat, rootmat, ob->obmat);
+       Mat4Invert (chain->goalinv, imat);
        
-       Mat4CpyMat3(mat, tmat);
+       /* and set and transform goal */
+       get_constraint_target_matrix(chain->con, TARGET_BONE, NULL, rootmat, size, 1.0);   // 1.0=ctime
+       VECCOPY (chain->goal, rootmat[3]);
+       Mat4MulVecfl (chain->goalinv, chain->goal);
        
-       VECCOPY(mat[3], bone->loc);
-//     VecAddf(mat[3], mat[3], bone->loc);
-/*     if(bone->ipo) {
-               mat[3][0]+= bone->dloc[0];
-               mat[3][1]+= bone->dloc[1];
-               mat[3][2]+= bone->dloc[2];
+       /* Now we construct the IK segments */
+       segs = MEM_callocN (sizeof(IK_Segment_Extern)*chain->totchannel, "iksegments");
+       
+       for (curseg=0; curseg<chain->totchannel; curseg++){
+               
+               pchan= chain->pchanchain[curseg];
+               
+               /* Get the matrix that transforms from prevbone into this bone */
+               Mat3CpyMat4(R_bonemat, pchan->pose_mat);
+               
+               if (pchan->parent && (pchan->bone->flag & BONE_IK_TOPARENT)) {
+                       Mat3CpyMat4(R_parmat, pchan->parent->pose_mat);
+               }
+               else
+                       Mat3One (R_parmat);
+               
+               Mat3Inv(iR_parmat, R_parmat);
+               
+               /* Mult and Copy the matrix into the basis and transpose (IK lib likes it) */
+               Mat3MulMat3((void *)segs[curseg].basis, iR_parmat, R_bonemat);
+               Mat3Transp((void *)segs[curseg].basis);
+               
+               /* Fill out the IK segment */
+               segs[curseg].length = pchan->bone->length; 
        }
-*/
+       
+       /*      Solve the chain */
+       
+       IK_LoadChain(chain->solver, segs, chain->totchannel);
+       
+       IK_SolveChain(chain->solver, chain->goal, chain->tolerance,  
+                                 chain->iterations,  0.1f, chain->solver->segments);
+       
+       
+       /* not yet free! */
 }
 
-Bone *get_indexed_bone (bArmature *arm, int index)
-/*
-       Walk the list until the index is reached
-*/
-{
-       Bone *bone=NULL, *curBone;
-       int     ref=index;
-
-       if (!arm)
-               return NULL;
 
-       for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
-               bone = get_indexed_bone_bonechildren (curBone, &ref);
-               if (bone)
-                       return bone;
-       }
+/* ********************** THE POSE SOLVER ******************* */
 
-       return bone;
-}
 
-Bone *get_named_bone (bArmature *arm, const char *name)
-/*
-       Walk the list until the bone is found
-*/
+/* loc/rot/size to mat4 */
+static void chan_calc_mat(bPoseChannel *chan)
 {
-       Bone *bone=NULL, *curBone;
-
-       if (!arm) return NULL;
-
-       for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){
-               bone = get_named_bone_bonechildren (curBone, name);
-               if (bone)
-                       return bone;
+       float smat[3][3];
+       float rmat[3][3];
+       float tmat[3][3];
+       
+       SizeToMat3(chan->size, smat);
+       
+       NormalQuat(chan->quat);
+       QuatToMat3(chan->quat, rmat);
+       
+       Mat3MulMat3(tmat, rmat, smat);
+       
+       Mat4CpyMat3(chan->chan_mat, tmat);
+       
+       /* prevent action channels breaking chains */
+       if (!(chan->bone->flag & BONE_IK_TOPARENT)) {
+               VECCOPY(chan->chan_mat[3], chan->loc);
        }
 
-       return bone;
 }
 
-static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index)
+/* transform from bone(b) to bone(b+1), store in chan_mat */
+static void make_dmats(bPoseChannel *pchan)
 {
-       Bone *curBone, *rbone;
-
-       if (!*index)
-               return bone;
-
-       (*index)--;
-
-       for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
-               rbone=get_indexed_bone_bonechildren (curBone, index);
-               if (rbone)
-                       return rbone;
+       if (pchan->parent) {
+               float iR_parmat[4][4];
+               Mat4Invert(iR_parmat, pchan->parent->pose_mat);
+               Mat4MulMat4(pchan->chan_mat,  pchan->pose_mat, iR_parmat);      // delta mat
        }
-
-       return NULL;
+       else Mat4CpyMat4(pchan->chan_mat, pchan->pose_mat);
 }
 
-static Bone *get_named_bone_bonechildren (Bone *bone, const char *name)
+/* applies IK matrix to pchan, IK is done separated */
+/* formula: pose_mat(b) = pose_mat(b-1) * diffmat(b-1, b) * ik_mat(b) */
+/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */
+static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3])   // nr = to detect if this is first bone
 {
-       Bone *curBone, *rbone;
-
-       if (!strcmp (bone->name, name))
-               return bone;
+       float vec[3], ikmat[4][4];
+       
+       Mat4CpyMat3(ikmat, ik_mat);
+       
+       if (pchan->parent)
+               Mat4MulSerie(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL);
+       else 
+               Mat4MulMat4(pchan->pose_mat, ikmat, pchan->chan_mat);
 
-       for (curBone=bone->childbase.first; curBone; curBone=curBone->next){
-               rbone=get_named_bone_bonechildren (curBone, name);
-               if (rbone)
-                       return rbone;
-       }
+       /* calculate head */
+       VECCOPY(pchan->pose_head, pchan->pose_mat[3]);
+       /* calculate tail */
+       VECCOPY(vec, pchan->pose_mat[1]);
+       VecMulf(vec, pchan->bone->length);
+       VecAddf(pchan->pose_tail, pchan->pose_head, vec);
 
-       return NULL;
+       pchan->flag |= POSE_DONE;
 }
 
-void make_displists_by_armature (Object *ob)
+/* The main armature solver, does all constraints excluding IK */
+/* pchan is validated, as having bone and parent pointer */
+static void where_is_pose_bone(Object *ob, bPoseChannel *pchan)
 {
-       Base *base;
-
-       if (ob){
-               if (ob->type != OB_ARMATURE) return;
-               for (base= G.scene->base.first; base; base= base->next){
-                       if ((ob==base->object->parent) && (base->lay & G.scene->lay))
-                               if ((base->object->partype==PARSKEL) || (base->object->type==OB_MBALL))
-                                       makeDispList(base->object);
+       Bone *bone, *parbone;
+       bPoseChannel *parchan;
+       float vec[3], ctime= 1.0;   // ctime todo
+
+       /* set up variables for quicker access below */
+       bone= pchan->bone;
+       parbone= bone->parent;
+       parchan= pchan->parent;
+               
+       /* this gives a chan_mat with actions (ipos) results */
+       chan_calc_mat(pchan);
+       
+       /* construct the posemat based on PoseChannels, that we do before applying constraints */
+       /* pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) */
+       
+       if(parchan) {
+               float offs_bone[4][4];  // yoffs(b-1) + root(b) + bonemat(b)
+               
+               /* bone transform itself */
+               Mat4CpyMat3(offs_bone, bone->bone_mat);
+               
+               /* The bone's root offset (is in the parent's coordinate system) */
+               VECCOPY(offs_bone[3], bone->head);
+               
+               /* Get the length translation of parent (length along y axis) */
+               offs_bone[3][1]+= parbone->length;
+               
+               /* Compose the matrix for this bone  */
+               Mat4MulSerie(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
+       }
+       else 
+               Mat4MulMat4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat);
+       
+       
+       /* Do constraints */
+       if(pchan->constraints.first) {
+               static Object conOb;
+               static int initialized= 0;
+               
+               /* Build a workob to pass the bone to the constraint solver */
+               if(initialized==0) {
+                       memset(&conOb, 0, sizeof(Object));
+                       initialized= 1;
                }
+               conOb.size[0]= conOb.size[1]= conOb.size[2]= 1.0;
+               conOb.data = ob->data;
+               conOb.type = ob->type;
+               conOb.parent = ob;      // ik solver retrieves the armature that way !?!?!?!
+               conOb.pose= ob->pose;                           // needed for retrieving pchan
+               conOb.trackflag = ob->trackflag;
+               conOb.upflag = ob->upflag;
+               
+               /* Collect the constraints from the pose (listbase copy) */
+               conOb.constraints = pchan->constraints;
+               
+               /* conOb.obmat takes bone to worldspace */
+               Mat4MulMat4 (conOb.obmat, pchan->pose_mat, ob->obmat);
+               
+               //VECCOPY(conOb.size, pchan->size);  // stretchto constraint
+               
+               /* Solve */
+               solve_constraints (&conOb, TARGET_BONE, (void*)bone, ctime);    // ctime doesnt alter objects
+               
+               //VECCOPY(bone->size, conOb.size);      // stretchto constraint
+               
+               /* Take out of worldspace */
+               Mat4MulMat4 (pchan->pose_mat, conOb.obmat, ob->imat);
        }
-/*
-(ton) changed this; now a free displist is sufficient, drawobject.c will make disp
-(ton) changed it back... doesnt work yet, do it after release
-*/
-
-}      
+       
+       /* calculate head */
+       VECCOPY(pchan->pose_head, pchan->pose_mat[3]);
+       /* calculate tail */
+       VECCOPY(vec, pchan->pose_mat[1]);
+       VecMulf(vec, bone->length);
+       VecAddf(pchan->pose_tail, pchan->pose_head, vec);
+       
+}
 
-void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed)
-/* Gets matrix that transforms the bone to object space */
-/* This function is also used to compute the orientation of the bone for display */
+/* This only reads anim data from channels, and writes to channels */
+/* This is the only function adding poses */
+void where_is_pose (Object *ob)
 {
-       Bone    *curBone;
-
-       Bone    *bonelist[256];
-       int             bonecount=0, i;
-
-       Mat4One (M_accumulatedMatrix);
+       bArmature *arm;
+       Bone *bone;
+       bPoseChannel *pchan, *next;
+       float imat[4][4];
+//     float ctime= (float)G.scene->r.cfra;    /* time only applies constraint location on curve path (now) */
 
-       /* Build a list of bones from tip to root */
-       for (curBone=bone; curBone; curBone=curBone->parent){
-               bonelist[bonecount] = curBone;
-               bonecount++;
+       arm = get_armature(ob);
+       
+       if(arm==NULL) return;
+       if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC)) 
+          armature_rebuild_pose(ob, arm);
+       
+//     printf("re-evaluate pose %s\n", ob->id.name);
+       
+       /* In restposition we read the data from the bones */
+       if(arm->flag & ARM_RESTPOS) {
+               
+               for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                       bone= pchan->bone;
+                       if(bone) {
+                               Mat4CpyMat4(pchan->pose_mat, bone->arm_mat);
+                               VECCOPY(pchan->pose_head, bone->arm_head);
+                               VECCOPY(pchan->pose_tail, pchan->pose_head);
+                       }
+               }
+       }
+       else {
+               Mat4Invert(ob->imat, ob->obmat);        // imat is needed 
+
+//#if 0
+               /* 1. construct the PoseChains, clear flags */
+               for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                       pchan->flag &= ~POSE_DONE;
+                       if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints
+                               initialize_posechain(ob, pchan);        // will attach it to root!
+               }
+               
+               /* 2. the main loop, channels are already hierarchical sorted from root to children */
+               for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                       if(!(pchan->flag & POSE_DONE)) {
+                               /* 3. if we find an IK root, we handle it separated */
+                               if(pchan->chain.first) {
+                                       while(pchan->chain.first) {
+                                               PoseChain *chain= pchan->chain.first;
+                                               int a;
+                                               
+                                               /* 4. walk over the chain for regular solving */
+                                               for(a=0; a<chain->totchannel; a++) {
+                                                       if(!(chain->pchanchain[a]->flag & POSE_DONE))   // successive chains can set the flag
+                                                               where_is_pose_bone(ob, chain->pchanchain[a]);
+                                               }
+                                               /* 5. execute the IK solver */
+                                               execute_posechain(ob, chain);   // calculates 3x3 difference matrices
+                                               /* 6. apply the differences to the channels, we calculate the original differences first */
+                                               for(a=0; a<chain->totchannel; a++)
+                                                       make_dmats(chain->pchanchain[a]);
+                                               for(a=0; a<chain->totchannel; a++)
+                                                       where_is_ik_bone(chain->pchanchain[a], (void *)chain->solver->segments[a].basis_change);
+                                                       // (sets POSE_DONE)
+                                               
+                                               /* 6. and free */
+                                               BLI_remlink(&pchan->chain, chain);
+                                               free_posechain(chain);
+                                       }
+                               }
+                               else where_is_pose_bone(ob, pchan);
+                       }
+               }
+//#endif
        }
 
-       /* Count through the inverted list (i.e. iterate from root to tip)*/
-       for (i=0; i<bonecount; i++){
-               float T_root[4][4];
-               float T_len[4][4];
-               float R_bmat[4][4];
-               float M_obmat[4][4];
-               float M_boneMatrix[4][4];
-               float delta[3];
-
-               curBone = bonelist[bonecount-i-1];
-
-               /* Get the length translation (length along y axis) */
-               Mat4One (T_len);
-               T_len[3][1] = get_bone_length(curBone);
-
-               if ((curBone == bone) && (root))
-                       Mat4One (T_len);
-
-               /* Get the bone's root offset (in the parent's coordinate system) */
-               Mat4One (T_root);
-               VECCOPY (T_root[3], curBone->head);
+#if 0
+       doconstraints= 1;
+       for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+               where_is_pose_bone(ob, pchan);
+       }
+       doconstraints= 0;
+       for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+               where_is_pose_bone(ob, pchan);
+               pchan->flag &= ~POSE_IK_MAT;
+       }
+#endif
+               
+       /* calculating deform matrices */
+       for(pchan= ob->pose->chanbase.first; pchan; pchan= next) {
+               next= pchan->next;
+               
+               if(pchan->bone) {
+                       Mat4Invert(imat, pchan->bone->arm_mat);
+                       Mat4MulMat4(pchan->chan_mat, imat, pchan->pose_mat);
+               }
+       }
+}
 
-               /* Compose the restmat */
-               VecSubf(delta, curBone->tail, curBone->head);
-               make_boneMatrixvr(R_bmat, delta, curBone->roll);
 
+/* *************** helper for selection code ****************** */
 
-               /* Retrieve the obmat (user transformation) */
-               if (posed)
-                       Mat4CpyMat4 (M_obmat, curBone->obmat);
-               else
-                       Mat4One (M_obmat);
 
-               /* Compose the matrix for this bone  */
-#if 0
-               Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, M_obmat, R_bmat, T_len, NULL, NULL, NULL);
-#else
-               Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, R_bmat, M_obmat, T_len, NULL, NULL, NULL);
-#endif
-               Mat4CpyMat4 (M_accumulatedMatrix, M_boneMatrix);
+Bone *get_indexed_bone (Object *ob, int index)
+/*
+       Now using pose channel
+*/
+{
+       bPoseChannel *pchan;
+       int a= 0;
+       
+       if(ob->pose==NULL) return NULL;
+       
+       for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, a++) {
+               if(a==index) return pchan->bone;
        }
+       return NULL;
+}
 
 
-}
+/* *********************** Inverse Kinematics ************* */
 
+#if 0
 void solve_posechain (PoseChain *chain)
 {
        float   goal[3];
        int     i;
        Bone *curBone;
-       float M_obmat[4][4];
-       float M_basischange[4][4];
+//     float M_obmat[4][4];
+//     float M_basischange[4][4];
        bPoseChannel *chan;
 
        if (!chain->solver) return;
@@ -1290,7 +1086,6 @@ void solve_posechain (PoseChain *chain)
 
        VECCOPY (goal, chain->goal);
        Mat4MulVecfl (chain->goalinv, goal);
-
        /*      Solve the chain */
 
        IK_SolveChain(chain->solver,
@@ -1302,30 +1097,41 @@ void solve_posechain (PoseChain *chain)
  
        /* Copy the results back into the bones */
        for (i = chain->solver->num_segments-1, curBone=chain->target->parent; i>=0; i--, curBone=curBone->parent){
-
+//     for (i = 0; i<chain->solver->num_segments; i++) {
+               //curBone= bonelist[i];
+               
                /* Retrieve the delta rotation from the solver */
-               Mat4One(M_basischange);
-               Mat4CpyMat3(M_basischange, (void *)chain->solver->segments[i].basis_change);    //basis_change = array[9]
-       
+//             Mat4One(M_basischange);
+//             Mat4CpyMat3(M_basischange, (void *)chain->solver->segments[i].basis_change);    //basis_change = array[9]
+//             printmatrix3(curBone->name, (void *)chain->solver->segments[i].basis_change);
                /**
                 *      Multiply the bone's usertransform by the 
                 *      basis change to get the new usertransform
                 */
 
-               Mat4CpyMat4 (M_obmat, curBone->obmat);
-               Mat4MulMat4 (curBone->obmat, M_basischange, M_obmat);
-
+               //Mat4CpyMat4 (M_obmat, curBone->obmat);
+               //Mat4MulMat4 (curBone->obmat, M_basischange, M_obmat);
+               /* store in channel itself */
+               
+               chan= get_pose_channel(chain->pose, curBone->name);
+               Mat3CpyMat3 (chan->ik_mat, (void *)chain->solver->segments[i].basis_change);
+               chan->flag |= POSE_IK_MAT;
+               
                /* Store the solve results on the childrens' channels */
-               for (chan = chain->pose->chanbase.first; chan; chan=chan->next){
-                       if (!strcmp (chan->name, curBone->name)){
-                               Mat4CpyMat4 (chan->obmat, curBone->obmat);
-                               break;
-                       }
-               }
-
+               //for (chan = chain->pose->chanbase.first; chan; chan=chan->next){
+               //      if (!strcmp (chan->name, curBone->name)){
+               //              Mat4CpyMat4 (chan->obmat, curBone->obmat);
+               //              break;
+               //      }
+               //}
        }
+       /* WARNING! REMOVE LATER !!! */
+       /* flag chain target to recalculate too */
+       chan= get_pose_channel(chain->pose, chain->target->name);
+       Mat3One(chan->ik_mat);
+       chan->flag |= POSE_IK_MAT;
 }
+#endif
 
 void free_posechain (PoseChain *chain)
 {
@@ -1334,9 +1140,13 @@ void free_posechain (PoseChain *chain)
                chain->solver->segments = NULL;
                IK_FreeChain(chain->solver);
        }
-       MEM_freeN (chain);
+       if(chain->pchanchain) MEM_freeN(chain->pchanchain);
+       MEM_freeN(chain);
 }
 
+#if 0
+/* actually; bones to IK_solver data */
+/* Object is its own Armature object */
 PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone)
 {
        IK_Segment_Extern       *segs;
@@ -1344,15 +1154,16 @@ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone)
        Bone            *curBone, *rootBone;
        int                     segcount, curseg, icurseg;
        float   imat[4][4];
+       bPoseChannel *pchan;
        Bone *bonelist[256];
        float rootmat[4][4];
-       float   bonespace[4][4];
+//     float   bonespace[4][4];
 
        /**
         *      Some interesting variables in this function:
         *
         *      Bone->obmat             Bone's user transformation;
-        *                                      It is initialized in where_is_bone1_time
+        *                                      It is initialized in where_is_b one1_time
         *
         *      rootmat                 Bone's coordinate system, computed by
         *                                      get_objectspace_bone_matrix.  Takes all
@@ -1395,27 +1206,29 @@ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone)
        /* Allocate some IK segments */
        segs = MEM_callocN (sizeof(IK_Segment_Extern)*segcount, "iksegments");
 
-
+       //printf("segcount %d\n", segcount);
        /**
         * Remove the offset from the first bone in the chain and take the target to chainspace
         */
 
-
-       get_objectspace_bone_matrix(rootBone, bonespace, 1, 1);
-       Mat4One (rootmat);
-       VECCOPY (rootmat[3], bonespace[3]);
+       //get_objectspace_bone_matrix(rootBone, bonespace, 1, 1);
+       //Mat4One (rootmat);
+       //VECCOPY (rootmat[3], bonespace[3]);
+       pchan= get_pose_channel(ob->pose, rootBone->name);
+       Mat4One(rootmat);
+       VECCOPY(rootmat[3], pchan->pose_head);
 
        /* Take the target to bonespace */
+       /* (ton) I think it's the matrix to take a world coordinate into "chainspace" */
        Mat4MulMat4 (imat, rootmat, ob->obmat);
        Mat4Invert (chain->goalinv, imat);
 
-
        /**
         *      Build matrices from the root to the tip 
         *      We count backwards through the bone list (which is sorted tip to root)
         *      and forwards through the ik_segment list
         */
-
+       /* that we're going to recode! (ton) */
        for (curseg = segcount-1; curseg>=0; curseg--){
                float M_basismat[4][4];
                float R_parmat[4][4];
@@ -1428,11 +1241,16 @@ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone)
                
                /* Get the basis matrix */
                Mat4One (R_parmat);
-               get_objectspace_bone_matrix(curBone, R_bonemat, 1, 1);
+               //get_objectspace_bone_matrix(curBone, R_bonemat, 1, 1);
+               //R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F;
+               pchan= get_pose_channel(ob->pose, curBone->name);
+               Mat4CpyMat4(R_bonemat, pchan->pose_mat);
                R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F;
                
-               if (curBone->parent && (curBone->flag & BONE_IK_TOPARENT)){
-                       get_objectspace_bone_matrix(curBone->parent, R_parmat, 1, 1);
+               if (curBone->parent && (curBone->flag & BONE_IK_TOPARENT)) {
+                       //get_objectspace_bone_matrix(curBone->parent, R_parmat, 1, 1);
+                       Mat4CpyMat4(R_parmat, pchan->parent->pose_mat);
+                       
                        R_parmat[3][0]=R_parmat[3][1]=R_parmat[3][2]=0.0F;
                }
                
@@ -1444,25 +1262,13 @@ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone)
                Mat3Transp((void *)segs[icurseg].basis);
 
                /* Fill out the IK segment */
-               segs[icurseg].length = get_bone_length(curBone);
+               segs[icurseg].length = VecLenf(curBone->head, curBone->tail);
 
-       };
+       }
 
        IK_LoadChain(chain->solver, segs, segcount);
+       
        return chain;
 }
 
-
-
-void precalc_bonelist_irestmats (ListBase* bonelist)
-{
-       Bone *curbone;
-
-       if (!bonelist)
-               return;
-
-       for (curbone = bonelist->first; curbone; curbone=curbone->next){
-               precalc_bone_irestmat(curbone);
-               precalc_bonelist_irestmats(&curbone->childbase);
-       }
-}
+#endif
index 2b7a5b4..b0f84d8 100644 (file)
@@ -392,15 +392,6 @@ static void setup_app_data(BlendFileData *bfd, char *filename)
                }
        }
        
-       /* few DispLists, but do text_to_curve */
-       // this should be removed!!! But first a better displist system (ton)
-       for (ob= G.main->object.first; ob; ob= ob->id.next) {
-               if(ob->type==OB_FONT) {
-                       Curve *cu= ob->data;
-                       if(cu->nurb.first==0) text_to_curve(ob, 0);
-               }
-       }
-       
        if (!G.background) {
                setscreen(G.curscreen);
        }
index dff98c8..f373c7f 100644 (file)
@@ -73,9 +73,178 @@ void Mat4BlendMat4(float [][4], float [][4], float [][4], float );
 
 /* Local function prototypes */
 
-/* Functions */
+/* ********************* Data level ****************** */
 
-char constraint_has_target (bConstraint *con) {
+void free_constraint_data (bConstraint *con)
+{
+       if (con->data){
+               switch (con->type){
+                       default:
+                               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);
+}
+
+void free_constraint_channels (ListBase *chanbase)
+{
+       bConstraintChannel *chan;
+       
+       for (chan=chanbase->first; chan; chan=chan->next)
+       {
+               if (chan->ipo){
+                       chan->ipo->id.us--;
+               }
+       }
+       
+       BLI_freelistN(chanbase);
+}
+
+void relink_constraints (struct ListBase *list)
+{
+       bConstraint *con;
+       
+       for (con = list->first; con; con=con->next){
+               switch (con->type){
+                       case CONSTRAINT_TYPE_KINEMATIC:
+                       {
+                               bKinematicConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                               break;
+                       case CONSTRAINT_TYPE_NULL:
+                       {
+                       }
+                               break;
+                       case CONSTRAINT_TYPE_TRACKTO:
+                       {
+                               bTrackToConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                               break;
+                       case CONSTRAINT_TYPE_LOCKTRACK:
+                       {
+                               bLockTrackConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                               break;
+                       case CONSTRAINT_TYPE_ACTION:
+                       {
+                               bActionConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                               break;
+                       case CONSTRAINT_TYPE_LOCLIKE:
+                       {
+                               bLocateLikeConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                               break;
+                       case CONSTRAINT_TYPE_ROTLIKE:
+                       {
+                               bRotateLikeConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                               break;
+                       case CONSTRAINT_TYPE_FOLLOWPATH:
+                       {
+                               bFollowPathConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                               break;
+                       case CONSTRAINT_TYPE_STRETCHTO:
+                       {
+                               bStretchToConstraint *data;
+                               data = con->data;
+                               
+                               ID_NEW(data->tar);
+                       }
+                               break;
+                               
+               }
+       }
+}
+
+void *copy_constraint_channels (ListBase *dst, ListBase *src)
+{
+       bConstraintChannel *dchan, *schan;
+       bConstraintChannel *newact=NULL;
+       
+       dst->first=dst->last=NULL;
+       duplicatelist(dst, src);
+       
+       for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){
+               dchan->ipo = copy_ipo(schan->ipo);
+       }
+       
+       return newact;
+}
+
+bConstraintChannel *clone_constraint_channels (ListBase *dst, ListBase *src, bConstraintChannel *oldact)
+{
+       bConstraintChannel *dchan, *schan;
+       bConstraintChannel *newact=NULL;
+       
+       dst->first=dst->last=NULL;
+       duplicatelist(dst, src);
+       
+       for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){
+               id_us_plus((ID *)dchan->ipo);
+               if (schan==oldact)
+                       newact=dchan;
+       }
+       
+       return newact;
+}
+
+void copy_constraints (ListBase *dst, ListBase *src)
+{
+       bConstraint *con;
+       
+       dst->first= dst->last= NULL;
+       
+       duplicatelist (dst, src);
+       
+       for (con = dst->first; con; con=con->next) {
+               con->data = MEM_dupallocN (con->data);
+               /* removed a whole lot of useless code here (ton) */
+       }
+}
+
+
+/* **************** Editor Functions **************** */
+
+char constraint_has_target (bConstraint *con) 
+{
        switch (con->type){
        case CONSTRAINT_TYPE_TRACKTO:
                {
@@ -137,7 +306,7 @@ char constraint_has_target (bConstraint *con) {
        return 0;
 }
 
-Object *get_constraint_target(bConstraint *con)
+Object *get_constraint_target(bConstraint *con, char **subtarget)
 {
 /*
 * If the target for this constraint is target, return a pointer 
@@ -147,48 +316,56 @@ Object *get_constraint_target(bConstraint *con)
        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_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_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;
@@ -197,7 +374,65 @@ Object *get_constraint_target(bConstraint *con)
        return NULL;  
 }
 
-void unique_constraint_name (bConstraint *con, ListBase *list){
+void set_constraint_target(bConstraint *con, Object *ob)
+{
+       /*
+        * Set the target for this constraint  
+        */
+       switch (con->type) {
+               case CONSTRAINT_TYPE_ACTION:
+               {
+                       bActionConstraint *data = con->data;
+                       data->tar= ob;
+               }
+                       break;
+               case CONSTRAINT_TYPE_LOCLIKE:
+               {
+                       bLocateLikeConstraint *data = con->data;
+                       data->tar= ob;
+               }
+                       break;
+               case CONSTRAINT_TYPE_ROTLIKE:
+               {
+                       bRotateLikeConstraint *data = con->data;
+                       data->tar= ob;
+               }
+                       break;
+               case CONSTRAINT_TYPE_KINEMATIC:
+               {
+                       bKinematicConstraint *data = con->data;
+                       data->tar= ob;
+               }
+                       break;
+               case CONSTRAINT_TYPE_TRACKTO:
+               {
+                       bTrackToConstraint *data = con->data;
+                       data->tar= ob;
+               }
+                       break;
+               case CONSTRAINT_TYPE_LOCKTRACK:
+               {
+                       bLockTrackConstraint *data = con->data;
+                       data->tar= ob;
+               }
+                       break;
+               case CONSTRAINT_TYPE_FOLLOWPATH: 
+               {
+                       bFollowPathConstraint *data = con->data;
+                       data->tar= ob;
+               }
+                       break;
+               case CONSTRAINT_TYPE_STRETCHTO:
+               {
+                       bStretchToConstraint *data = con->data;
+                       data->tar= ob;
+               }
+                       break;
+       }
+}
+
+void unique_constraint_name (bConstraint *con, ListBase *list)
+{
        char            tempname[64];
        int                     number;
        char            *dot;
@@ -241,9 +476,9 @@ void unique_constraint_name (bConstraint *con, ListBase *list){
        }
 }
 
-void   *new_constraint_data (short type)
+void *new_constraint_data (short type)
 {
-       void    *result;
+       void *result;
        
        switch (type){
        case CONSTRAINT_TYPE_KINEMATIC:
@@ -252,7 +487,7 @@ void        *new_constraint_data (short type)
                        data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
 
                        data->tolerance = (float)0.001;
-                       data->iterations = 500;
+                       data->iterations = 50;
 
                        result = data;
                }
@@ -344,23 +579,27 @@ void      *new_constraint_data (short type)
        return result;
 }
 
-bConstraintChannel *find_constraint_channel (ListBase *list, const char *name){
+bConstraintChannel *find_constraint_channel (ListBase *list, const char *name)
+{
        bConstraintChannel *chan;
 
-       for (chan = list->first; chan; chan=chan->next){
-               if (!strcmp(name, chan->name)){
+       for (chan = list->first; chan; chan=chan->next) {
+               if (!strcmp(name, chan->name)) {
                        return chan;
                }
        }
        return NULL;
 }
 
+/* ***************** Evaluating ********************* */
+
+/* does ipos only */
 void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime)
 {
        bConstraint *con;
        bConstraintChannel *chan;
-       IpoCurve *icu;
-
+       IpoCurve *icu=NULL;
+       
        for (con=conbase->first; con; con=con->next){
                chan = find_constraint_channel(chanbase, con->name);
                if (chan && chan->ipo){
@@ -421,94 +660,33 @@ void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweig
 static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime)
 {
 
-       /*      Update the location of the target object */
-       //where_is_object_time (ob, ctime);     
-
        /*      Case OBJECT */
-       if (!strlen(substring)){
+       if (!strlen(substring)) {
                Mat4CpyMat4 (mat, ob->obmat);
-               VECCOPY (size, ob->size);
-               return;
+               VECCOPY (size, ob->size);  // whats this for, hack! (ton)
        }
-
        /*      Case BONE */
        else {
-               bArmature *arm;
-               Bone    *bone;
-               float   bmat[4][4];
+               bPoseChannel *pchan;
                float   bsize[3]={1, 1, 1};
 
-               arm = get_armature(ob);
-
-               /**
-                *      Locate the bone (if there is one)
-                *      Ensures that the bone's transformation is fully constrained
-                *      (Cyclical relationships are disallowed elsewhere)
-                */
-               bone = get_named_bone(arm, substring);
-               if (bone){
-                       where_is_bone_time(ob, bone, ctime);
-                       get_objectspace_bone_matrix(bone, bmat, 1, 1);
-                       VECCOPY(bsize, bone->size);
+               pchan = get_pose_channel(ob->pose, substring);
+               if (pchan){
+                       /**
+                        *      Multiply the objectspace bonematrix by the skeletons's global
+                        *      transform to obtain the worldspace transformation of the target
+                        */
+                       Mat4MulMat4 (mat, pchan->pose_mat, ob->obmat);
                } 
                else
-                       Mat4One (bmat);
-
-               /**
-                *      Multiply the objectspace bonematrix by the skeletons's global
-                *      transform to obtain the worldspace transformation of the target
-                */
-               VECCOPY(size, bsize);
-               Mat4MulMat4 (mat, bmat, ob->obmat);
-       
-               return; 
-       }
-}
-
-void clear_object_constraint_status (Object *ob)
-{
-       bConstraint *con;
+                       Mat4CpyMat4 (mat, ob->obmat);
 
-       if (!ob) return;
-
-       /* Clear the object's constraints */
-       for (con = ob->constraints.first; con; con=con->next){
-               con->flag &= ~CONSTRAINT_DONE;
-       }
-
-       /* Clear the object's subdata constraints */
-       switch (ob->type){
-       case OB_ARMATURE:
-               {
-                       clear_pose_constraint_status (ob);
-               }
-               break;
-       default:
-               break;
-       }
-}
-
-void clear_all_constraints(void)
-{
-       Base *base;
-
-       /* Clear the constraint "done" flags -- this must be done
-        * before displists are calculated for objects that are
-        * deformed by armatures */
-       for (base = G.scene->base.first; base; base=base->next){
-               clear_object_constraint_status(base->object);
-       }
-}
-
-void rebuild_all_armature_displists(void) {
-       Base *base;
-
-       for (base = G.scene->base.first; base; base=base->next){
-               clear_object_constraint_status(base->object);
-               make_displists_by_armature(base->object);
+               VECCOPY(size, bsize);   // whats this for, hack! (ton)
        }
 }
 
+/* called during solve_constraints */
+/* also for make_parent, to find correct inverse of "follow path" */
 short get_constraint_target_matrix (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime)
 {
        short valid=0;
@@ -531,13 +709,11 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                                float s,t;
                                Bone *curBone;
                                Bone tbone;
-                               int i;
+//                             int i;
                                
                                curBone = (Bone*)ownerdata;
                                
                                if (data->tar){
-                                       /*      Update the location of the target object */
-                                       where_is_object_time (data->tar, ctime);        
                                        constraint_target_to_mat4(data->tar, data->subtarget, tempmat, size, ctime);
                                        valid=1;
                                }
@@ -582,26 +758,26 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                                pose = MEM_callocN(sizeof(bPose), "pose");
                                
                                verify_pose_channel(pose, curBone->name);
-                               get_pose_from_action (&pose, data->act, t);
+                               extract_pose_from_action (pose, data->act, t);
 
                                /* Find the appropriate channel */
                                pchan = get_pose_channel(pose, curBone->name);
                                if (pchan){
                                        memset(&tbone, 0x00, sizeof(Bone));
 
-                                       VECCOPY (tbone.loc, pchan->loc);
-                                       VECCOPY (tbone.size, pchan->size);                              
-                                       for (i=0; i<4; i++)
-                                               tbone.quat[i]=pchan->quat[i];
-                                       
-                                       bone_to_mat4(&tbone, mat);
+//                                     VECCOPY (tbone.loc, pchan->loc);
+//                                     VECCOPY (tbone.size, pchan->size);                              
+//                                     for (i=0; i<4; i++)
+//                                             tbone.quat[i]=pchan->quat[i];
+//                                     
+//                                     bone_to_mat4(&tbone, mat);
 
                                }
                                else{
                                        Mat4One(mat);
                                }
                                /* Clean up */
-                               clear_pose(pose);
+                               free_pose_channels(pose);
                                MEM_freeN(pose);
                        }
                        
@@ -612,8 +788,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                        bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data;
 
                        if (data->tar){
-                               /*      Update the location of the target object */
-                               where_is_object_time (data->tar, ctime);        
                                constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
                                valid=1;
                        }
@@ -627,8 +801,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                        data = (bRotateLikeConstraint*)con->data;
 
                        if (data->tar){
-                               /*      Update the location of the target object */
-                               where_is_object_time (data->tar, ctime);        
                                constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
                                valid=1;
                        }
@@ -642,9 +814,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                        data = (bTrackToConstraint*)con->data;
 
                        if (data->tar){
-                               // Refresh the object if it isn't a constraint loop
-                               if (!(con->flag & CONSTRAINT_NOREFRESH))
-                                       where_is_object_time (data->tar, ctime);        
                                constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
                                valid=1;
                        }
@@ -654,12 +823,10 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                break;
        case CONSTRAINT_TYPE_KINEMATIC:
                {
-                       bTrackToConstraint *data;
-                       data = (bTrackToConstraint*)con->data;
+                       bKinematicConstraint *data;
+                       data = (bKinematicConstraint*)con->data;
 
                        if (data->tar){
-                               /*      Update the location of the target object */
-                               where_is_object_time (data->tar, ctime);        
                                constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
                                valid=1;
                        }
@@ -673,10 +840,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                        data = (bLockTrackConstraint*)con->data;
 
                        if (data->tar){
-                               // Refresh the object if it isn't a constraint loop
-                               if (!(con->flag & CONSTRAINT_NOREFRESH))
-                                       where_is_object_time (data->tar, ctime);        
-
                                constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
                                valid=1;
                        }
@@ -690,33 +853,17 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                        data = (bFollowPathConstraint*)con->data;
 
                        if (data->tar){
-                               short OldFlag;
                                Curve *cu;
                                float q[4], vec[4], dir[3], *quat, x1, totmat[4][4];
                                float curvetime;
 
-                               where_is_object_time (data->tar, ctime);        
-
                                Mat4One (totmat);
                                Mat4One (mat);
 
                                cu= data->tar->data;
-                               OldFlag = cu->flag;
-                               
-                               if(data->followflag) {
-                                       if(!(cu->flag & CU_FOLLOW)) cu->flag += CU_FOLLOW;
-                               }
-                               else {
-                                       if(cu->flag & CU_FOLLOW) cu->flag -= CU_FOLLOW;
-                               }
-
-                               if(!(cu->flag & CU_PATH)) cu->flag += CU_PATH;
-
-                               if(cu->path==NULL)
-                                       calc_curvepath(data->tar);
-                               else if (cu->path->data==NULL)
-                                       calc_curvepath(data->tar);
 
+                               /* 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 && cu->path->data) {
                                        curvetime= bsystem_time(data->tar, data->tar->parent, (float)ctime, 0.0) - data->offset;
 
@@ -746,7 +893,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                                                Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
                                        }
                                }
-                               cu->flag = OldFlag;
                                valid=1;
                        }
                        else
@@ -759,7 +905,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
                        data = (bStretchToConstraint*)con->data;
 
                        if (data->tar){
-                               where_is_object_time (data->tar, ctime);        
                                constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
                                valid = 1;
                        }
@@ -776,209 +921,10 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
        return valid;
 }
 
-void relink_constraints (struct ListBase *list)
-{
-       bConstraint *con;
-
-       for (con = list->first; con; con=con->next){
-               switch (con->type){
-               case CONSTRAINT_TYPE_KINEMATIC:
-                       {
-                               bKinematicConstraint *data;
-                               data = con->data;
-
-                               ID_NEW(data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_NULL:
-                       {
-                       }
-                       break;
-               case CONSTRAINT_TYPE_TRACKTO:
-                       {
-                               bTrackToConstraint *data;
-                               data = con->data;
-
-                               ID_NEW(data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_LOCKTRACK:
-                       {
-                               bLockTrackConstraint *data;
-                               data = con->data;
-
-                               ID_NEW(data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_ACTION:
-                       {
-                               bActionConstraint *data;
-                               data = con->data;
-
-                               ID_NEW(data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_LOCLIKE:
-                       {
-                               bLocateLikeConstraint *data;
-                               data = con->data;
-
-                               ID_NEW(data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_ROTLIKE:
-                       {
-                               bRotateLikeConstraint *data;
-                               data = con->data;
-
-                               ID_NEW(data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_FOLLOWPATH:
-                       {
-                               bFollowPathConstraint *data;
-                               data = con->data;
-
-                               ID_NEW(data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_STRETCHTO:
-                       {
-                               bStretchToConstraint *data;
-                               data = con->data;
-                               
-                               ID_NEW(data->tar);
-                       }
-                       break;
-                       
-               }
-       }
-}
-
-void *copy_constraint_channels (ListBase *dst, ListBase *src)
-{
-       bConstraintChannel *dchan, *schan;
-       bConstraintChannel *newact=NULL;
-
-       dst->first=dst->last=NULL;
-       duplicatelist(dst, src);
-       
-       for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){
-               dchan->ipo = copy_ipo(schan->ipo);
-       }
-
-       return newact;
-}
-
-bConstraintChannel *clone_constraint_channels (ListBase *dst, ListBase *src, bConstraintChannel *oldact)
-{
-       bConstraintChannel *dchan, *schan;
-       bConstraintChannel *newact=NULL;
-
-       dst->first=dst->last=NULL;
-       duplicatelist(dst, src);
-       
-       for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){
-               id_us_plus((ID *)dchan->ipo);
-               if (schan==oldact)
-                       newact=dchan;
-       }
-
-       return newact;
-}
-
-void copy_constraints (ListBase *dst, ListBase *src)
-{
-       bConstraint *con;
-
-       dst->first=dst->last=NULL;
-
-       duplicatelist (dst, src);
-
-       /* Update specific data */
-       if (!dst->first)
-               return;
-
-       for (con = dst->first; con; con=con->next){
-               switch (con->type){
-               case CONSTRAINT_TYPE_ACTION:
-                       {
-                               bActionConstraint *data;
-
-                               con->data = MEM_dupallocN (con->data);
-                               data = (bActionConstraint*) con->data;
-                       }
-                       break;
-               case CONSTRAINT_TYPE_LOCLIKE:
-                       {
-                               bLocateLikeConstraint *data;
-
-                               con->data = MEM_dupallocN (con->data);
-                               data = (bLocateLikeConstraint*) con->data;
-                       }
-                       break;
-               case CONSTRAINT_TYPE_ROTLIKE:
-                       {
-                               bRotateLikeConstraint *data;
-                               
-                               con->data = MEM_dupallocN (con->data);
-                               data = (bRotateLikeConstraint*) con->data;
-                       }
-                       break;
-               case CONSTRAINT_TYPE_NULL:
-                       {
-                               con->data = NULL;
-                       }
-                       break;
-               case CONSTRAINT_TYPE_TRACKTO:
-                       {
-                               bTrackToConstraint *data;
-                               
-                               con->data = MEM_dupallocN (con->data);
-                               data = (bTrackToConstraint*) con->data;
-                       }
-                       break;
-               case CONSTRAINT_TYPE_LOCKTRACK:
-                       {
-                               bLockTrackConstraint *data;
-                               
-                               con->data = MEM_dupallocN (con->data);
-                               data = (bLockTrackConstraint*) con->data;
-                       }
-                       break;
-               case CONSTRAINT_TYPE_KINEMATIC:
-                       {
-                               bKinematicConstraint *data;
-                               
-                               con->data = MEM_dupallocN (con->data);
-                               data = (bKinematicConstraint*) con->data;
-                       }
-                       break;
-               case CONSTRAINT_TYPE_FOLLOWPATH:
-                       {
-                               bFollowPathConstraint *data;
-                               
-                               con->data = MEM_dupallocN (con->data);
-                               data = (bFollowPathConstraint*) con->data;
-                       }
-                       break;
-               case CONSTRAINT_TYPE_STRETCHTO:
-                       {
-                               bStretchToConstraint *data;
-                               
-                               con->data = MEM_dupallocN (con->data);
-                               data = (bStretchToConstraint*) con->data;
-                       }
-                       break;
-               default:
-                       con->data = MEM_dupallocN (con->data);
-                       break;
-               }
-       }
-}
 
+/* only called during solve_constraints */
+/* bone constraints create a fake object to work on, then ob is a workob */
 void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4])
-/* ob is likely to be a workob */
 {
        float   M_oldmat[4][4];
        float   M_identity[4][4];
@@ -988,11 +934,6 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
        
        Mat4One (M_identity);
        
-       /* We've already been calculated */
-       if (constraint->flag & CONSTRAINT_DONE){
-               return;
-       }
-       
        switch (constraint->type){
        case CONSTRAINT_TYPE_ACTION:
                {
@@ -1088,6 +1029,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                break;
        case CONSTRAINT_TYPE_KINEMATIC:
                {
+#if 0
                        bKinematicConstraint *data;
                        float   imat[4][4];
                        float   temp[4][4];
@@ -1111,15 +1053,19 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                                chain->tolerance = data->tolerance;
                                
                                
-                               {
+                               if(0) {
+                                       bPoseChannel *pchan= get_pose_channel(armob->pose, curBone->name);
                                        float parmat[4][4];
                                        
                                        /* Take the obmat to objectspace */
-                                       Mat4CpyMat4 (temp, curBone->obmat);
-                                       Mat4One (curBone->obmat);
-                                       get_objectspace_bone_matrix(curBone, parmat, 1, 1);
-                                       Mat4CpyMat4 (curBone->obmat, temp);
-                                       Mat4MulMat4 (totmat, parmat, ob->parent->obmat);
+                                       
+//                                     Mat4CpyMat4 (temp, curBone->obmat);
+//                                     Mat4One (curBone->obmat);
+//                                     get_objectspace_bone_matrix(curBone, parmat, 1, 1);
+                                       Mat4CpyMat4(parmat, pchan->pose_mat);
+                                       
+//                                     Mat4CpyMat4 (curBone->obmat, temp);
+                                       Mat4MulMat4 (totmat, parmat, armob->obmat);
                                        
                                        Mat4Invert (imat, totmat);
                                        
@@ -1131,26 +1077,31 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                                /* Solve it */
                                if (chain->solver){
                                        VECCOPY (chain->goal, targetmat[3]);                                    
-                                       solve_posechain(chain);
+                                       solve_posechain(chain); // applies to bones/channels
                                }
                                
                                free_posechain(chain);
                                
-                               {
+                               if(0) {
                                        float parmat[4][4];
+                                       bPoseChannel *pchan= get_pose_channel(armob->pose, curBone->name);
                                        
                                        /* Take the obmat to worldspace */
-                                       Mat4CpyMat4 (temp, curBone->obmat);
-                                       Mat4One (curBone->obmat);
-                                       get_objectspace_bone_matrix(curBone, parmat, 1, 1);
-                                       Mat4CpyMat4 (curBone->obmat, temp);
-                                       Mat4MulMat4 (totmat, parmat, ob->parent->obmat);
+//                                     Mat4CpyMat4 (temp, curBone->obmat);
+//                                     Mat4One (curBone->obmat);
+                                       
+//                                     get_objectspace_bone_matrix(curBone, parmat, 1, 1);
+                                       Mat4CpyMat4(parmat, pchan->pose_mat);
+
+//                                     Mat4CpyMat4 (curBone->obmat, temp);
+                                       Mat4MulMat4 (totmat, parmat, armob->obmat);
                                        
                                        Mat4CpyMat4 (temp, ob->obmat);
                                        Mat4MulMat4 (ob->obmat, temp, totmat);
                                        
                                }
                        }
+#endif
                }
                break;
        case CONSTRAINT_TYPE_LOCKTRACK:
@@ -1481,7 +1432,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                        data=(bFollowPathConstraint*)constraint->data;                  
 
                        if (data->tar) {
-
+                               // weird, this is needed? doesnt work for workob (ton)
                                object_to_mat4(ob, obmat);
 
                                Mat4MulSerie(ob->obmat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
@@ -1617,45 +1568,4 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                printf ("Error: Unknown constraint type\n");
                break;
        }
-
-}
-
-void free_constraint_data (bConstraint *con)
-{
-       if (con->data){
-               switch (con->type){
-               default:
-                       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);
-}
-
-void free_constraint_channels (ListBase *chanbase)
-{
-       bConstraintChannel *chan;
-
-       for (chan=chanbase->first; chan; chan=chan->next)
-       {
-               if (chan->ipo){
-                       chan->ipo->id.us--;
-               }
-       }
-
-       BLI_freelistN(chanbase);
 }
index 226a1d6..7fe0ec6 100644 (file)
@@ -54,6 +54,7 @@
 #include "BKE_displist.h"
 #include "BKE_effect.h"
 #include "BKE_global.h"
+#include "BKE_key.h"
 #include "BKE_lattice.h"
 #include "BKE_object.h"
 #include "BKE_softbody.h"
@@ -237,6 +238,8 @@ int mesh_modifier(Object *ob, char mode)
        MVert *mv;
        int a, done=0;
        
+       do_mesh_key(me);
+       
        /* conditions if it's needed */
        if(ob->hooks.first);
        else if(ob->effect.first);      // weak... particles too
@@ -322,6 +325,8 @@ int curve_modifier(Object *ob, char mode)
        BPoint *bp;
        int a, index, done= 0;
        
+       do_curve_key(cu);
+       
        /* conditions if it's needed */
        if(ob->hooks.first);
        else if(ob->parent && ob->partype==PARSKEL); 
@@ -390,6 +395,8 @@ int lattice_modifier(Object *ob, char mode)
        BPoint *bp;
        int a, index, done= 0;
        
+       do_latt_key(lt);
+       
        /* conditions if it's needed */
        if(ob->hooks.first);
        else if(ob->parent && ob->partype==PARSKEL); 
index 668b18c..9f0501d 100644 (file)
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
 #include "DNA_ID.h"
+#include "DNA_effect_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
 #include "DNA_object_types.h"
+#include "DNA_object_force.h"
 #include "DNA_oops_types.h"
 #include "DNA_scene_types.h"
-#include "DNA_action_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
 #include "DNA_view2d_types.h"
 
-#include "BKE_utildefines.h"
+#include "BKE_action.h"
 #include "BKE_global.h"
+#include "BKE_mball.h"
+#include "BKE_utildefines.h"
 
 #include "MEM_guardedalloc.h"
 #include "blendef.h"
@@ -272,18 +280,16 @@ int               queue_count(struct DagNodeQueue *queue){
 DagForest * dag_init()
 {
        DagForest *forest;
-       
-       forest = MEM_mallocN(sizeof(DagForest),"DAG root");
-       forest->DagNode.first = NULL;
-       forest->DagNode.last = NULL;
-       forest->numNodes = 0;
+       /* use callocN to init all zero */
+       forest = MEM_callocN(sizeof(DagForest),"DAG root");
        return forest;
 }
 
-struct DagForest       *build_dag(struct Scene *sce, short mask) 
+struct DagForest *build_dag(struct Scene *sce, short mask) 
 {
        Base *base;
        Object *ob;
+       bConstraint *con;
        DagNode * node;
        DagNode * node2;
        DagNode * node3;
@@ -299,130 +305,126 @@ struct DagForest        *build_dag(struct Scene *sce, short mask)
                sce->theDag = dag;
        }
        
-       // add base node for scene. scene is always the first node in DAG
+       /* add base node for scene. scene is always the first node in DAG */
        scenenode = dag_add_node(dag, sce);     
        
-       /* targets in object struct yet to be added. should even they ?
-               struct Ipo *ipo;
-       ListBase nlastrips;
-       ListBase hooks;
-       */
-       
-       
-       base = sce->base.first;
-       while(base) { // add all objects in any case
+       for(base = sce->base.first; base; base= base->next) {
                int addtoroot = 1;
                ob= (Object *) base->object;
                
                node = dag_get_node(dag,ob);
                
-               if ((ob->data) && (mask&DAG_RL_DATA_MASK)) {
+               if ((ob->data) && (mask&DAG_RL_DATA)) {
                        node2 = dag_get_node(dag,ob->data);
                        dag_add_relation(dag,node,node2,DAG_RL_DATA);
                        node2->first_ancestor = ob;
                        node2->ancestor_count += 1;
                        
-                       if ((ob->type == OB_ARMATURE) && (mask&DAG_RL_DATA_CONSTRAINT_MASK)) { // add armature constraints to datas
-                               if (ob->pose){
-                                       bPoseChannel *pchan;
-                                       bConstraint *con;
-                                       Object * target;
-                                       
-                                       for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
-                                               for (con = pchan->constraints.first; con; con=con->next){
-                                                       if (constraint_has_target(con)) {
-                                                               target = get_constraint_target(con);
-                                                               if (strcmp(target->id.name, ob->id.name) != 0) {
-                                                                       //fprintf(stderr,"armature target :%s \n", target->id.name);
-                                                                       node3 = dag_get_node(dag,target);
-                                                                       dag_add_relation(dag,node3,node2,DAG_RL_CONSTRAINT);
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
                        
-                       if ((ob->hooks.first) && (mask&DAG_RL_HOOK)) {
-                               ObHook *hook;
+               }
+               if (ob->type == OB_ARMATURE) {
+                       if (ob->pose){
+                               bPoseChannel *pchan;
+                               bConstraint *con;
+                               Object * target;
+                               char *subtarget;
                                
-                               for(hook= ob->hooks.first; hook; hook= hook->next) {
-                                       if(hook->parent) {
-                                               node3 = dag_get_node(dag,hook->parent);
-                                               dag_add_relation(dag,node3,node2,DAG_RL_HOOK);
-                                       }
-                               }
-                       }
-               } else { // add armature constraints to object itself
-                       if ((ob->type == OB_ARMATURE) && (mask&DAG_RL_DATA_CONSTRAINT_MASK)) {
-                               if (ob->pose){
-                                       bPoseChannel *pchan;
-                                       bConstraint *con;
-                                       Object * target;
-                                       
-                                       for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
-                                               for (con = pchan->constraints.first; con; con=con->next){
-                                                       if (constraint_has_target(con)) {
-                                                               target = get_constraint_target(con);
-                                                               if (strcmp(target->id.name, ob->id.name) != 0) {
-                                                                       //fprintf(stderr,"armature target :%s \n", target->id.name);
-                                                                       node3 = dag_get_node(dag,target);
-                                                                       dag_add_relation(dag,node3,node,DAG_RL_CONSTRAINT);
-                                                               }
+                               for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
+                                       for (con = pchan->constraints.first; con; con=con->next){
+                                               if (constraint_has_target(con)) {
+                                                       target = get_constraint_target(con, &subtarget);
+                                                       if (target!=ob) {
+                                                               // fprintf(stderr,"armature %s target :%s \n", ob->id.name, target->id.name);
+                                                               node3 = dag_get_node(dag, target);
+                                                               
+                                                               dag_add_relation(dag,node3,node,DAG_RL_OB_DATA);
+                                                               
                                                        }
                                                }
                                        }
                                }
                        }
-                       if ((ob->hooks.first)  && (mask&DAG_RL_HOOK)) {
-                               ObHook *hook;
-                               
-                               for(hook= ob->hooks.first; hook; hook= hook->next) {
-                                       if(hook->parent) {
-                                               node3 = dag_get_node(dag,hook->parent);
-                                               dag_add_relation(dag,node3,node,DAG_RL_HOOK);
-                                       }
+               }
+               if (ob->hooks.first) {
+                       ObHook *hook;
+                       
+                       for(hook= ob->hooks.first; hook; hook= hook->next) {
+                               if(hook->parent) {
+                                       node3 = dag_get_node(dag,hook->parent);
+                                       dag_add_relation(dag,node3,node,DAG_RL_OB_DATA);
                                }
-                       }                       
+                       }
                }
-               
-               if ((ob->parent) && (mask&DAG_RL_PARENT_MASK)){
+               if (ob->parent) {
                        node2 = dag_get_node(dag,ob->parent);
-                       dag_add_relation(dag,node2,node,DAG_RL_PARENT);
+                       
+                       switch(ob->partype) {
+                       case PARSKEL:
+                               dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_OB);
+                               break;
+                       case PARVERT1: case PARVERT3: case PARBONE:
+                               dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB);
+                               break;
+                       default:
+                               if(ob->parent->type==OB_LATTICE) 
+                                       dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_OB);
+                               else if(ob->parent->type==OB_CURVE) {
+                                       Curve *cu= ob->parent->data;
+                                       if(cu->flag & CU_PATH) 
+                                               dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB);
+                                       else
+                                               dag_add_relation(dag,node2,node,DAG_RL_OB_OB);
+                               }
+                               else
+                                       dag_add_relation(dag,node2,node,DAG_RL_OB_OB);
+                       }
                        addtoroot = 0;
                }
-               if ((ob->track) && (mask&DAG_RL_TRACK_MASK)){
+               if (ob->track) {
                        node2 = dag_get_node(dag,ob->track);
-                       dag_add_relation(dag,node2,node,DAG_RL_TRACK);
+                       dag_add_relation(dag,node2,node,DAG_RL_OB_OB);
                        addtoroot = 0;
-                       
                }
-               if ((ob->path) && (mask&DAG_RL_PATH_MASK)){
-                       node2 = dag_get_node(dag,ob->track);
-                       dag_add_relation(dag,node2,node,DAG_RL_PATH);
-                       addtoroot = 0;
-                       
+               if (ob->type==OB_MBALL) {
+                       Object *mom= find_basis_mball(ob);
+                       if(mom!=ob) {
+                               node2 = dag_get_node(dag, mom);
+                               dag_add_relation(dag,node,node2,DAG_RL_DATA_DATA|DAG_RL_OB_DATA);  // mom depends on children!
+                       }
                }
-               
-               /* Count constraints */
-               if (mask & DAG_RL_CONSTRAINT_MASK) {
-                       bConstraint *con;
-                       for (con = ob->constraints.first; con; con=con->next){
-                               if (constraint_has_target(con)) {
-                                       node2 = dag_get_node(dag,get_constraint_target(con));
-                                       dag_add_relation(dag,node2,node,DAG_RL_CONSTRAINT);
-                                       addtoroot = 0;
-                                       
-                               }
+               else if (ob->type==OB_CURVE) {
+                       Curve *cu= ob->data;
+                       if(cu->bevobj) {
+                               node2 = dag_get_node(dag, cu->bevobj);
+                               dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
                        }
-               }       
+                       if(cu->taperobj) {
+                               node2 = dag_get_node(dag, cu->taperobj);
+                               dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+                       }
+               }
+               else if(ob->type==OB_FONT) {
+                       Curve *cu= ob->data;
+                       if(cu->textoncurve) {
+                               node2 = dag_get_node(dag, cu->textoncurve);
+                               dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+                       }
+               }
                
+               for (con = ob->constraints.first; con; con=con->next){
+                       if (constraint_has_target(con)) {
+                               char *str;
+                               node2 = dag_get_node(dag, get_constraint_target(con, &str));
+                               if(con->type==CONSTRAINT_TYPE_FOLLOWPATH)
+                                       dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB);
+                               else
+                                       dag_add_relation(dag, node2, node, DAG_RL_OB_OB);
+                               addtoroot = 0;
+                       }
+               }
                
                if (addtoroot == 1 )
                        dag_add_relation(dag,scenenode,node,DAG_RL_SCENE);
-               
-               addtoroot = 1;
-               base= base->next;
        }
        
        // cycle detection and solving
@@ -458,18 +460,20 @@ void free_forest(DagForest *Dag)
 
 DagNode * dag_find_node (DagForest *forest,void * fob)
 {
-               DagNode *node = forest->DagNode.first;
-               
-               while (node) {
-                       if (node->ob == fob)
-                               return node;
-                       node = node->next;
-               }
-               return NULL;
+       DagNode *node = forest->DagNode.first;
+       
+       while (node) {
+               if (node->ob == fob)
+                       return node;
+               node = node->next;
+       }
+       return NULL;
 }
 
+static int ugly_hack_sorry= 1; // prevent type check
+
 /* no checking of existance, use dag_find_node first or dag_get_node */
-DagNode * dag_add_node (DagForest *forest,void * fob)
+DagNode * dag_add_node (DagForest *forest, void * fob)
 {
        DagNode *node;
                
@@ -486,7 +490,7 @@ DagNode * dag_add_node (DagForest *forest,void * fob)
                node->first_ancestor = NULL;
                node->ancestor_count = 0;
 
-               node->type = GS(((ID *) fob)->name);
+               if(ugly_hack_sorry) node->type = GS(((ID *) fob)->name);        // sorry, done for pose sorting
                if (forest->numNodes) {
                        ((DagNode *) forest->DagNode.last)->next = node;
                        forest->DagNode.last = node;
@@ -540,7 +544,7 @@ DagNode * dag_get_sub_node (DagForest *forest,void * fob)
        return node;
 }
 
-void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, dag_rel_type rel) 
+void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel) 
 {
        DagAdjList *itA = fob1->child;
        
@@ -846,6 +850,7 @@ DagNodeQueue * graph_dfs(void)
          return(retqueue);
 }
 
+/* unused */
 int pre_and_post_DFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data) {
        DagNode *node;
 
@@ -933,84 +938,6 @@ int pre_and_post_source_DFS(DagForest *dag, short mask, DagNode *source, graph_a
        return(retval);
 }
 
-// sort the base list on place
-void topo_sort_baselist(struct Scene *sce){
-       DagNode *node;
-       DagNodeQueue *nqueue;
-       DagAdjList *itA;
-       int time;
-       int skip = 0;
-       ListBase tempbase;
-       Base *base;
-       
-       tempbase.first= tempbase.last= 0;
-       
-       build_dag(sce,DAG_RL_ALL_BUT_DATA_MASK);
-       
-       nqueue = queue_create(DAGQUEUEALLOC);
-       
-       node = sce->theDag->DagNode.first;
-       while(node) {
-               node->color = DAG_WHITE;
-               node =  node->next;
-       }
-       
-       time = 1;
-       
-       node = sce->theDag->DagNode.first;
-       
-       node->color = DAG_GRAY;
-       time++;
-       push_stack(nqueue,node);  
-       
-       while(nqueue->count) {
-               
-               skip = 0;
-               node = get_top_node_queue(nqueue);
-               
-               itA = node->child;
-               while(itA != NULL) {
-                       if((itA->node->color == DAG_WHITE) ) {
-                               itA->node->DFS_dvtm = time;
-                               itA->node->color = DAG_GRAY;
-                               
-                               time++;
-                               push_stack(nqueue,itA->node);
-                               skip = 1;
-                               break;
-                       } 
-                       itA = itA->next;
-               }                       
-               
-               if (!skip) {
-                       if (node) {
-                               node = pop_queue(nqueue);
-                               if (node->ob == sce)    // we are done
-                                       break ;
-                               node->color = DAG_BLACK;
-                               
-                               time++;
-                               base = sce->base.first;
-                               while (base->object != node->ob)
-                                       base = base->next;
-                               BLI_remlink(&sce->base,base);
-                               BLI_addhead(&tempbase,base);
-                       }       
-               }
-       }
-       
-       // temporal correction for circular dependancies
-       base = sce->base.first;
-       while (base) {
-               BLI_remlink(&sce->base,base);
-               BLI_addhead(&tempbase,base);
-               base = sce->base.first;
-       }
-       
-       sce->base = tempbase;
-       queue_delete(nqueue);
-}
-
 
 // used to get the obs owning a datablock
 struct DagNodeQueue *get_obparents(struct DagForest    *dag, void *ob) 
@@ -1020,7 +947,10 @@ struct DagNodeQueue *get_obparents(struct DagForest       *dag, void *ob)
        DagAdjList *itA;
 
        node = dag_find_node(dag,ob);
-       if (node->ancestor_count == 1) { // simple case
+       if(node==NULL) {
+               return NULL;
+       }
+       else if (node->ancestor_count == 1) { // simple case
                nqueue = queue_create(1);
                push_queue(nqueue,node);
        } else {        // need to go over the whole dag for adj list
@@ -1082,7 +1012,7 @@ struct DagNodeQueue *get_all_childs(struct DagForest      *dag, void *ob)
        int skip = 0;
 
        nqueue = queue_create(DAGQUEUEALLOC);
-       retqueue = queue_create(MainDag->numNodes);
+       retqueue = queue_create(dag->numNodes); // was MainDag... why? (ton)
        
        node = dag->DagNode.first;
        while(node) {
@@ -1092,45 +1022,47 @@ struct DagNodeQueue *get_all_childs(struct DagForest    *dag, void *ob)
        
        time = 1;
        
-       node = dag_find_node(dag,ob);
-       
-       node->color = DAG_GRAY;
-       time++;
-       push_stack(nqueue,node);  
-       
-       while(nqueue->count) {
+       node = dag_find_node(dag,ob);   // could be done in loop above (ton)
+       if(node) { // can be null for newly added objects
                
-               skip = 0;
-               node = get_top_node_queue(nqueue);
-                               
-               itA = node->child;
-               while(itA != NULL) {
-                       if((itA->node->color == DAG_WHITE) ) {
-                               itA->node->DFS_dvtm = time;
-                               itA->node->color = DAG_GRAY;
-                               
-                               time++;
-                               push_stack(nqueue,itA->node);
-                               skip = 1;
-                               break;
-                       } 
-                       itA = itA->next;
-               }                       
+               node->color = DAG_GRAY;
+               time++;
+               push_stack(nqueue,node);  
                
-               if (!skip) {
-                       node = pop_queue(nqueue);
-                       node->color = DAG_BLACK;
+               while(nqueue->count) {
                        
-                       time++;
-                       push_stack(retqueue,node);                      
+                       skip = 0;
+                       node = get_top_node_queue(nqueue);
+                                       
+                       itA = node->child;
+                       while(itA != NULL) {
+                               if((itA->node->color == DAG_WHITE) ) {
+                                       itA->node->DFS_dvtm = time;
+                                       itA->node->color = DAG_GRAY;
+                                       
+                                       time++;
+                                       push_stack(nqueue,itA->node);
+                                       skip = 1;
+                                       break;
+                               } 
+                               itA = itA->next;
+                       }                       
+                       
+                       if (!skip) {
+                               node = pop_queue(nqueue);
+                               node->color = DAG_BLACK;
+                               
+                               time++;
+                               push_stack(retqueue,node);                      
+                       }
                }
        }
-               
        queue_delete(nqueue);
        return(retqueue);
 }
 
-dag_rel_type   are_obs_related(struct DagForest        *dag, void *ob1, void *ob2) {
+/* unused */
+short  are_obs_related(struct DagForest        *dag, void *ob1, void *ob2) {
        DagNode * node;
        DagAdjList *itA;
        
@@ -1211,4 +1143,434 @@ void graph_print_adj_list(void)
        }
 }
 
+/* ************************ API *********************** */
+
+/* sort the base list on dependency order */
+void DAG_scene_sort(struct Scene *sce)
+{
+       DagNode *node;
+       DagNodeQueue *nqueue;
+       DagAdjList *itA;
+       int time;
+       int skip = 0;
+       ListBase tempbase;
+       Base *base;
+       
+       tempbase.first= tempbase.last= NULL;
+       
+       build_dag(sce, DAG_RL_ALL_BUT_DATA);
+       
+       nqueue = queue_create(DAGQUEUEALLOC);
+       
+       node = sce->theDag->DagNode.first;
+       while(node) {
+               node->color = DAG_WHITE;
+               node =  node->next;
+       }
+       
+       time = 1;
+       
+       node = sce->theDag->DagNode.first;
+       
+       node->color = DAG_GRAY;
+       time++;
+       push_stack(nqueue,node);  
+       
+       while(nqueue->count) {
+               
+               skip = 0;
+               node = get_top_node_queue(nqueue);
+               
+               itA = node->child;
+               while(itA != NULL) {
+                       if((itA->node->color == DAG_WHITE) ) {
+                               itA->node->DFS_dvtm = time;
+                               itA->node->color = DAG_GRAY;
+                               
+                               time++;
+                               push_stack(nqueue,itA->node);
+                               skip = 1;
+                               break;
+                       } 
+                       itA = itA->next;
+               }                       
+               
+               if (!skip) {
+                       if (node) {
+                               node = pop_queue(nqueue);
+                               if (node->ob == sce)    // we are done
+                                       break ;
+                               node->color = DAG_BLACK;
+                               
+                               time++;
+                               base = sce->base.first;
+                               while (base->object != node->ob)
+                                       base = base->next;
+                               BLI_remlink(&sce->base,base);
+                               BLI_addhead(&tempbase,base);
+                       }       
+               }
+       }
+       
+       // temporal correction for circular dependancies
+       base = sce->base.first;
+       while (base) {
+               BLI_remlink(&sce->base,base);
+               BLI_addhead(&tempbase,base);
+               //if(G.f & G_DEBUG) 
+                       printf("cyclic %s\n", base->object->id.name);
+               base = sce->base.first;
+       }
+       
+       sce->base = tempbase;
+       queue_delete(nqueue);
+       
+       if(G.f & G_DEBUG) {
+               printf("\nordered\n");
+               for(base = sce->base.first; base; base= base->next) {
+                       printf(" %s\n", base->object->id.name);
+               }
+       }
+}
+
+/* node was checked to have lasttime != curtime and is if type ID_OB */
+static void flush_update_node(DagNode *node, unsigned int layer, int curtime)
+{
+       DagAdjList *itA;
+       Object *ob, *obc;
+       int oldflag, changed=0;
+       unsigned int all_layer;
+       
+       node->lasttime= curtime;
+       
+       ob= node->ob;
+       if(ob->recalc & OB_RECALC) {
+               all_layer= ob->lay;
+               /* got an object node that changes, now check relations */
+               for(itA = node->child; itA; itA= itA->next) {
+                       all_layer |= itA->lay;
+                       /* the relationship is visible */
+                       if(itA->lay & layer) {
+                               if(itA->node->type==ID_OB) {
+                                       obc= itA->node->ob;
+                                       oldflag= obc->recalc;
+                                       
+                                       /* got a ob->obc relation, now check if flag needs flush */
+                                       if(ob->recalc & OB_RECALC_OB) {
+                                               if(itA->type & DAG_RL_OB_OB) {
+                                                       //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name);
+                                                       obc->recalc |= OB_RECALC_OB;
+                                               }
+                                               if(itA->type & DAG_RL_OB_DATA) {
+                                                       //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name);
+                                                       obc->recalc |= OB_RECALC_DATA;
+                                               }
+                                       }
+                                       if(ob->recalc & OB_RECALC_DATA) {
+                                               if(itA->type & DAG_RL_DATA_OB) {
+                                                       //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name);
+                                                       obc->recalc |= OB_RECALC_OB;
+                                               }
+                                               if(itA->type & DAG_RL_DATA_DATA) {
+                                                       //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name);
+                                                       obc->recalc |= OB_RECALC_DATA;
+                                               }
+                                       }
+                                       if(oldflag!=obc->recalc) changed= 1;
+                               }
+                       }
+               }
+               /* even nicer, we can clear recalc flags... but we don't for armatures, these can have poses that need pointer checks (read old file issue) */
+               if(ob->type!=OB_ARMATURE)
+                       if((all_layer & layer)==0)
+                               ob->recalc &= ~OB_RECALC;
+       }
+       else{
+               /* Object has not RECALC flag */
+               /* check case where child changes and parent forcing obdata to change */
+               /* could merge this in with loop above... (ton) */
+               for(itA = node->child; itA; itA= itA->next) {
+                       /* the relationship is visible */
+                       if(itA->lay & layer) {
+                               if(itA->node->type==ID_OB) {
+                                       obc= itA->node->ob;
+                                       /* child moves */
+                                       if((obc->recalc & OB_RECALC)==OB_RECALC_OB) {
+                                               /* parent has deforming info */
+                                               if(itA->type & (DAG_RL_OB_DATA|DAG_RL_DATA_DATA)) {
+                                                       // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name);
+                                                       obc->recalc |= OB_RECALC_DATA;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       /* we only go deeper if node not checked or something changed  */
+       for(itA = node->child; itA; itA= itA->next) {
+               if(changed || itA->node->lasttime!=curtime) 
+                       flush_update_node(itA->node, layer, curtime);
+       }
+}
+
+/* node was checked to have lasttime != curtime , and is of type ID_OB */
+static unsigned int flush_layer_node(DagNode *node, int curtime)
+{
+       DagAdjList *itA;
+       
+       node->lasttime= curtime;
+       node->lay= ((Object *)node->ob)->lay;
+       
+       for(itA = node->child; itA; itA= itA->next) {
+               if(itA->node->type==ID_OB) {
+                       if(itA->node->lasttime!=curtime) {
+                               itA->lay= flush_layer_node(itA->node, curtime);  // lay is only set once for each relation
+                               //printf("layer %d for relation %s to %s\n", itA->lay, ((Object *)node->ob)->id.name, ((Object *)itA->node->ob)->id.name);
+                       }
+                       else itA->lay= itA->node->lay;
+                       
+                       node->lay |= itA->lay;
+               }
+       }
+
+       return node->lay;
+}
+
+/* flushes all recalc flags in objects down the dependency tree */
+void DAG_scene_flush_update(Scene *sce)
+{
+       DagNode *firstnode;
+       DagAdjList *itA;
+       int lasttime;
+       
+       firstnode= sce->theDag->DagNode.first;  // always scene node
+       
+       /* first we flush the layer flags */
+       sce->theDag->time++;    // so we know which nodes were accessed
+       lasttime= sce->theDag->time;
+       for(itA = firstnode->child; itA; itA= itA->next) {
+               if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) 
+                       flush_layer_node(itA->node, lasttime);
+       }
+       
+       /* then we use the relationships + layer info to flush update events */
+       sce->theDag->time++;    // so we know which nodes were accessed
+       lasttime= sce->theDag->time;
+       for(itA = firstnode->child; itA; itA= itA->next) {
+               if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) 
+                       flush_update_node(itA->node, sce->lay, lasttime);
+       }
+}
+
+/* flag all objects that need recalc, for changes in time for example */
+void DAG_scene_update_flags(Scene *sce, unsigned int lay)
+{
+       Base *base;
+       Object *ob;
+       
+       /* set ob flags where animated systems are */
+       for(base= sce->base.first; base; base= base->next) {
+               
+               /* now if DagNode were part of base, the node->lay could be checked... */
+               /* we do all now, since the scene_flush checks layers */
+               //if((base->lay & lay))  {
+                       ob= base->object;
+                       
+                       if(ob->ipo) ob->recalc |= OB_RECALC_OB;
+                       else if(ob->constraints.first) ob->recalc |= OB_RECALC_OB;
+                       else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB;
+                       else if(ob->parent) {
+                               if(ob->parent->type==OB_CURVE) ob->recalc |= OB_RECALC_OB;
+                       }
+                       
+                       if(ob->action) ob->recalc |= OB_RECALC_DATA;
+                       else if(ob->nlastrips.first) ob->recalc |= OB_RECALC_DATA;
+                       else if(ob->softflag & OB_SB_ENABLE) ob->recalc |= OB_RECALC_DATA;
+                       else {
+                               Mesh *me;
+                               Curve *cu;
+                               Lattice *lt;
+                               
+                               switch(ob->type) {
+                                       case OB_MESH:
+                                               me= ob->data;
+                                               if(me->key) ob->recalc |= OB_RECALC_DATA;
+                                               else if(ob->effect.first) {
+                                                       Effect *eff= ob->effect.first;
+                                                       if(eff->type==EFF_WAVE) ob->recalc |= OB_RECALC_DATA;
+                                               }
+                                               break;
+                                       case OB_CURVE:
+                                       case OB_SURF:
+                                               cu= ob->data;
+                                               if(cu->key) ob->recalc |= OB_RECALC_DATA;
+                                               break;
+                                       case OB_LATTICE:
+                                               lt= ob->data;
+                                               if(lt->key) ob->recalc |= OB_RECALC_DATA;
+                                               break;
+                               }
+                       }
+               //}
+       }
+       DAG_scene_flush_update(sce);
+}
+
+/* flag this object and all its relations to recalc */
+/* if you need to do more objects, tag object yourself and
+   use DAG_scene_flush_update() in end */
+void DAG_object_flush_update(Scene *sce, Object *ob, short flag)
+{
+       Base *base;
+       
+       if(ob==NULL) return;
+       ob->recalc |= flag;
+       
+       /* all users of this ob->data should be checked */
+       if(flag & OB_RECALC_DATA) {
+               ID *id= ob->data;
+               if(id && id->us>1) {
+                       for (base= sce->base.first; base; base= base->next) {
+                               if (ob->data==base->object->data) {
+                                       base->object->recalc |= OB_RECALC_DATA;
+                               }
+                       }
+               }
+       }
+       
+       DAG_scene_flush_update(sce);
+}
+
+/* ******************* DAG FOR ARMATURE POSE ***************** */
+
+/* we assume its an armature with pose */
+void DAG_pose_sort(Object *ob)
+{
+       bPose *pose= ob->pose;
+       bPoseChannel *pchan;
+       bConstraint *con;
+       DagNode *node;
+       DagNode *node2, *node3;
+       DagNode *rootnode;
+       DagForest *dag;
+       DagNodeQueue *nqueue;
+       DagAdjList *itA;
+       ListBase tempbase;
+       int skip = 0;
+       
+       dag = dag_init();
+       ugly_hack_sorry= 0;     // no ID structs
+
+       rootnode = dag_add_node(dag, NULL);     // node->ob becomes NULL
+       
+       /* we add the hierarchy and the constraints */
+       for(pchan = pose->chanbase.first; pchan; pchan= pchan->next) {
+               int addtoroot = 1;
+               
+               node = dag_get_node(dag, pchan);
+               
+               if(pchan->parent) {
+                       node2 = dag_get_node(dag, pchan->parent);
+                       dag_add_relation(dag, node2, node, 0);
+                       addtoroot = 0;
+               }
+               for (con = pchan->constraints.first; con; con=con->next){
+                       if (constraint_has_target(con)) {
+                               char *subtarget;
+                               Object *target = get_constraint_target(con, &subtarget);
+                               
+                               if (target==ob && subtarget) {
+                                       bPoseChannel *target= get_pose_channel(ob->pose, subtarget);
+                                       if(target) {
+                                               node2= dag_get_node(dag, target);
+                                               dag_add_relation(dag, node2, node, 0);
+                                               
+                                               if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
+                                                       bPoseChannel *par= pchan->parent;
+                                                       
+                                                       while(par) {
+                                                               node3= dag_get_node(dag, par);
+                                                               dag_add_relation(dag, node2, node3, 0);
+                                                               
+                                                               if(par->bone->flag & BONE_IK_TOPARENT)
+                                                                       par= par->parent;
+                                                               else break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               if (addtoroot == 1 )
+                       dag_add_relation(dag, rootnode, node, 0);
+       }
+
+       /* now we try to sort... */
+       tempbase.first= tempbase.last= NULL;
+
+       nqueue = queue_create(DAGQUEUEALLOC);
+       
+       /* tag nodes unchecked */
+       for(node = dag->DagNode.first; node; node= node->next) 
+               node->color = DAG_WHITE;
+       
+       node = dag->DagNode.first;
+       
+       node->color = DAG_GRAY;
+       push_stack(nqueue, node);  
+       
+       while(nqueue->count) {
+               
+               skip = 0;
+               node = get_top_node_queue(nqueue);
+               
+               itA = node->child;
+               while(itA != NULL) {
+                       if((itA->node->color == DAG_WHITE) ) {
+                               itA->node->color = DAG_GRAY;
+                               push_stack(nqueue,itA->node);
+                               skip = 1;
+                               break;
+                       } 
+                       itA = itA->next;
+               }                       
+               
+               if (!skip) {
+                       if (node) {
+                               node = pop_queue(nqueue);
+                               if (node->ob == NULL)   // we are done
+                                       break ;
+                               node->color = DAG_BLACK;
+                               
+                               /* put node in new list */
+                               BLI_remlink(&pose->chanbase, node->ob);
+                               BLI_addhead(&tempbase, node->ob);
+                       }       
+               }
+       }
+       
+       // temporal correction for circular dependancies
+       while(pose->chanbase.first) {
+               pchan= pose->chanbase.first;
+               BLI_remlink(&pose->chanbase, pchan);
+               BLI_addhead(&tempbase, pchan);
+
+               printf("cyclic %s\n", pchan->name);
+       }
+       
+       pose->chanbase = tempbase;
+       queue_delete(nqueue);
+       
+//     printf("\nordered\n");
+//     for(pchan = pose->chanbase.first; pchan; pchan= pchan->next) {
+//             printf(" %s\n", pchan->name);
+//     }
+       
+       free_forest( dag );
+       MEM_freeN( dag );
+       
+       ugly_hack_sorry= 1;
+}
+
+
 
index 3e4c670..b287626 100644 (file)
@@ -238,24 +238,6 @@ void freedisplist(ListBase *lb)
        }
 }
 
-static void freedisplist_object(Object *ob)
-{
-       freedisplist(&ob->disp);
-
-       if(ob->type==OB_MESH) {
-               Mesh *me= ob->data;
-               freedisplist(&me->disp);
-               if (me->derived) {
-                       me->derived->release(me->derived);
-                       me->derived = NULL;
-               }
-       }
-       else if(ob->type==OB_CURVE || ob->type==OB_SURF || ob->type==OB_FONT) {
-               Curve *cu= ob->data;
-               freedisplist(&cu->disp);
-       }
-}
-
 DispList *find_displist_create(ListBase *lb, int type)
 {
        DispList *dl;
@@ -1661,12 +1643,12 @@ void makeDispList(Object *ob)
                if (ob!=G.obedit) mesh_modifier(ob, 'e');
        }
        else if(ob->type==OB_MBALL) {
-               ob= find_basis_mball(ob);
+               if(ob==find_basis_mball(ob)) {
+                       metaball_polygonize(ob);
+                       tex_space_mball(ob);
 
-               metaball_polygonize(ob);
-               tex_space_mball(ob);
-
-               object_deform(ob);
+                       object_deform(ob);
+               }
        }
        else if(ob->type==OB_SURF) {
                
@@ -1760,6 +1742,7 @@ void makeDispList(Object *ob)
                if(ob!=G.obedit) object_deform(ob);
        }
        else if ELEM(ob->type, OB_CURVE, OB_FONT) {
+               int obedit= (G.obedit && G.obedit->data==ob->data);
                
                draw= ob->dt;
                cu= ob->data;
@@ -1767,21 +1750,23 @@ void makeDispList(Object *ob)
                if(dl_onlyzero && dispbase->first) return;
                freedisplist(dispbase);
                
+               BLI_freelistN(&(cu->bev));
+               
                if(cu->path) free_path(cu->path);
-               cu->path= 0;
+               cu->path= NULL;
                
-               BLI_freelistN(&(cu->bev));
+               if(ob->type==OB_FONT) text_to_curve(ob, 0);
                
-               if(ob!=G.obedit) curve_modifier(ob, 's');
+               if(!obedit) curve_modifier(ob, 's');
                
-               if(ob==G.obedit) {
+               if(obedit) {
                        if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase);
                        else curve_to_displist(&cu->nurb, dispbase);
-                       if(cu->flag & CU_PATH) makeBevelList(ob);
+                       makeBevelList(ob);  // always needed, so calc_curvepath() can work
                }
                else if(cu->ext1==0.0 && cu->ext2==0.0 && cu->bevobj==NULL && cu->width==1.0) {
                        curve_to_displist(&cu->nurb, dispbase);
-                       if(cu->flag & CU_PATH) makeBevelList(ob);
+                       makeBevelList(ob); // always needed, so calc_curvepath() can work
                }
                else {
                        
@@ -1893,10 +1878,12 @@ void makeDispList(Object *ob)
                                freedisplist(&dlbev);
                        }
                }
+               if(cu->flag & CU_PATH) calc_curvepath(ob);
 
-               if(ob!=G.obedit) curve_modifier(ob, 'e');
-               if(ob!=G.obedit) object_deform(ob);
-
+               if(!obedit) {
+                       curve_modifier(ob, 'e');
+                       object_deform(ob);
+               }
                tex_space_curve(cu);
 
        }
@@ -2203,142 +2190,6 @@ void imagestodisplist(void)
        allqueue(REDRAWVIEW3D, 0);
 }
 
-/* on frame change */
-/* new method: only frees displists, and relies on 
-   drawobject.c & convertscene.c to build it when needed
-*/
-void test_all_displists(void)
-{
-       Base *base;
-       Object *ob;
-       unsigned int lay;
-       int makedisp, freedisp;
-       
-       /* background */        
-       lay= G.scene->lay;
-       
-       /* clear flags, we use them because parent->parents are evaluated too */
-       base= G.scene->base.first;
-       while(base) {
-               if(base->lay & lay) {
-                       base->object->flag &= ~(BA_DISP_UPDATE|BA_WHERE_UPDATE);
-               }
-               if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
-               else base= base->next;
-       }
-       
-       base= G.scene->base.first;
-       while(base) {
-               if(base->lay & lay) {
-                       ob= base->object;
-                       makedisp= freedisp= 0;
-                       
-                       if(ob->type==OB_MBALL && (ob->ipo || ob->parent)) {
-                               // find metaball object holding the displist
-                               // WARNING: if more metaballs have IPO's the displist
-                               // is recalculated to often... do we free the displist
-                               // and rely on the drawobject.c to build it again when needed
-
-                               if(ob->disp.first == NULL) {
-                                       ob= find_basis_mball(ob);
-                               }
-                               makedisp= 1;
-                       }
-                       else if(ob->parent) {
-                               
-                               if (ob->parent->type == OB_LATTICE)
-                                       freedisp= 1;
-                               else if ((ob->parent->type==OB_ARMATURE) && (ob->partype == PARSKEL))
-                                       makedisp= 1;
-                               else if(ob->softflag & OB_SB_ENABLE)
-                                       makedisp= 1;
-                               else if ((ob->parent->type==OB_CURVE) && (ob->partype == PARSKEL))
-                                       freedisp= 1;
-                               else if(ob->partype==PARVERT1 || ob->partype==PARVERT3) {
-                                       if(ob->parent->parent) 
-                                               ob->parent->flag |= BA_DISP_UPDATE;
-                                       else if(ob->parent->effect.first)       // stupid test for wave
-                                               ob->parent->flag |= BA_DISP_UPDATE;
-                               }
-                       }
-
-                       if(ob->hooks.first) {
-                               ObHook *hook;
-                               for(hook= ob->hooks.first; hook; hook= hook->next) {
-                                       if(hook->parent) 
-                                               freedisp= 1;
-                                       break;
-                               }
-                       }
-                       
-                       if(ob->softflag & OB_SB_ENABLE) freedisplist_object(ob);
-                       /* warn, ob pointer changed in case of OB_MALL */
-
-                       if ELEM(ob->type, OB_CURVE, OB_SURF) {
-                               if(ob!=G.obedit) {
-                                       Curve *cu= ob->data;
-                                       
-                                       if(cu->key ) makedisp= 1;
-                                       if(cu->bevobj) {
-                                               Curve *cu1= cu->bevobj->data;
-                                               if(cu1->key ) freedisp= 1;
-                                       }
-                                       if(cu->taperobj) {
-                                               Curve *cu1= cu->taperobj->data;
-                                               if(cu1->key ) freedisp= 1;
-                                       }
-                               }
-                       }
-                       else if(ob->type==OB_FONT) {
-                               Curve *cu= ob->data;
-                               if(cu->textoncurve) {
-     &n