Merge with trunk r37677
authorJoerg Mueller <nexyon@gmail.com>
Mon, 20 Jun 2011 22:55:18 +0000 (22:55 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Mon, 20 Jun 2011 22:55:18 +0000 (22:55 +0000)
20 files changed:
1  2 
release/scripts/modules/bpy_types.py
release/scripts/startup/bl_operators/nla.py
release/scripts/startup/bl_ui/space_userpref.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenloader/intern/readfile.c
source/blender/collada/AnimationImporter.cpp
source/blender/collada/ArmatureImporter.cpp
source/blender/collada/CMakeLists.txt
source/blender/collada/DocumentImporter.cpp
source/blender/collada/SkinInfo.cpp
source/blender/editors/interface/resources.c
source/blender/editors/space_view3d/drawarmature.c
source/blender/editors/transform/transform_conversions.c
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_userdef.c
source/gameengine/Converter/BL_ActionActuator.cpp

@@@ -20,7 -20,6 +20,6 @@@
  
  from _bpy import types as bpy_types
  import _bpy
- from mathutils import Vector
  
  StructRNA = bpy_types.Struct.__bases__[0]
  StructMetaPropGroup = _bpy.StructMetaPropGroup
@@@ -144,18 -143,21 +143,21 @@@ class _GenericBone
      def x_axis(self):
          """ Vector pointing down the x-axis of the bone.
          """
+         from mathutils import Vector
          return Vector((1.0, 0.0, 0.0)) * self.matrix.to_3x3()
  
      @property
      def y_axis(self):
          """ Vector pointing down the x-axis of the bone.
          """
+         from mathutils import Vector
          return Vector((0.0, 1.0, 0.0)) * self.matrix.to_3x3()
  
      @property
      def z_axis(self):
          """ Vector pointing down the x-axis of the bone.
          """
+         from mathutils import Vector
          return Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
  
      @property
@@@ -409,16 -411,6 +411,16 @@@ class Text(bpy_types.ID)
  TypeMap = {}
  
  
 +class Sound(bpy_types.ID):
 +    __slots__ = ()
 +    
 +    @property
 +    def factory(self):
 +        """The aud.Factory object of the sound."""
 +        import aud
 +        return aud._sound_from_pointer(self.as_pointer())
 +
 +
  class RNAMeta(type):
      def __new__(cls, name, bases, classdict, **args):
          result = type.__new__(cls, name, bases, classdict)
  #
  # ##### END GPL LICENSE BLOCK #####
  
- # <pep8 compliant>
+ # <pep8-80 compliant>
  
  import bpy
  
  
- def pose_info():
+ def pose_frame_info(obj):
      from mathutils import Matrix
  
      info = {}
  
-     obj = bpy.context.object
      pose = obj.pose
  
      pose_items = pose.bones.items()
@@@ -51,7 -50,6 +50,6 @@@
          except:
              binfo["matrix_pose_inv"] = Matrix()
  
-         print(binfo["matrix_pose"])
          info[name] = binfo
  
      for name, pbone in pose_items:
              matrix = binfo_parent["matrix_pose_inv"] * matrix
              rest_matrix = binfo_parent["matrix_local_inv"] * rest_matrix
  
-         matrix = rest_matrix.inverted() * matrix
+         binfo["matrix_key"] = rest_matrix.inverted() * matrix
+     return info
  
-         binfo["matrix_key"] = matrix.copy()
  
+ def obj_frame_info(obj):
+     info = {}
+     # parent = obj.parent
+     info["matrix_key"] = obj.matrix_local.copy()
      return info
  
  
- def bake(frame_start, frame_end, step=1, only_selected=False):
+ def bake(frame_start,
+          frame_end, step=1,
+          only_selected=False,
+          do_pose=True,
+          do_object=True,
+          do_constraint_clear=False,
+          ):
      scene = bpy.context.scene
      obj = bpy.context.object
      pose = obj.pose
+     frame_back = scene.frame_current
+     if pose is None:
+         do_pose = False
  
-     info_ls = []
+     if do_pose is None and do_object is None:
+         return None
+     pose_info = []
+     obj_info = []
  
      frame_range = range(frame_start, frame_end + 1, step)
  
-     # could spped this up by applying steps here too...
+     # -------------------------------------------------------------------------
+     # Collect transformations
+     
+     # could speed this up by applying steps here too...
      for f in frame_range:
          scene.frame_set(f)
  
-         info = pose_info()
-         info_ls.append(info)
+         if do_pose:
+             pose_info.append(pose_frame_info(obj))
+         if do_object:
+             obj_info.append(obj_frame_info(obj))
          f += 1
  
+     # -------------------------------------------------------------------------
+     # Create action
+     # incase animation data hassnt been created
+     atd = obj.animation_data_create()
      action = bpy.data.actions.new("Action")
+     atd.action = action
  
-     bpy.context.object.animation_data.action = action
+     if do_pose:
+         pose_items = pose.bones.items()
+     else:
+         pose_items = []  # skip
  
-     pose_items = pose.bones.items()
+     # -------------------------------------------------------------------------
+     # Apply transformations to action
  
-     for name, pbone in pose_items:
+     # pose
+     for name, pbone in (pose_items if do_pose else ()):
          if only_selected and not pbone.bone.select:
              continue
  
+         if do_constraint_clear:
+             while pbone.constraints:
+                 pbone.constraints.remove(pbone.constraints[0])
          for f in frame_range:
-             matrix = info_ls[int((f - frame_start) / step)][name]["matrix_key"]
+             matrix = pose_info[(f - frame_start) // step][name]["matrix_key"]
  
-             #pbone.location = matrix.to_translation()
-             #pbone.rotation_quaternion = matrix.to_quaternion()
+             # pbone.location = matrix.to_translation()
+             # pbone.rotation_quaternion = matrix.to_quaternion()
              pbone.matrix_basis = matrix
  
              pbone.keyframe_insert("location", -1, f, name)
  
              pbone.keyframe_insert("scale", -1, f, name)
  
+     # object. TODO. multiple objects
+     if do_object:
+         if do_constraint_clear:
+             while obj.constraints:
+                 obj.constraints.remove(obj.constraints[0])
+         for f in frame_range:
+             matrix = obj_info[(f - frame_start) // step]["matrix_key"]
+             obj.matrix_local = matrix
+             obj.keyframe_insert("location", -1, f)
+             rotation_mode = obj.rotation_mode
+             if rotation_mode == 'QUATERNION':
+                 obj.keyframe_insert("rotation_quaternion", -1, f)
+             elif rotation_mode == 'AXIS_ANGLE':
+                 obj.keyframe_insert("rotation_axis_angle", -1, f)
+             else:  # euler, XYZ, ZXY etc
+                 obj.keyframe_insert("rotation_euler", -1, f)
+             obj.keyframe_insert("scale", -1, f)
+     scene.frame_set(frame_back)
      return action
  
  
- from bpy.props import IntProperty, BoolProperty
+ from bpy.props import IntProperty, BoolProperty, EnumProperty
  
  
  class BakeAction(bpy.types.Operator):
              default=1, min=1, max=120)
      only_selected = BoolProperty(name="Only Selected",
              default=True)
+     clear_consraints = BoolProperty(name="Clear Constraints",
+             default=False)
+     bake_types = EnumProperty(
+             name="Bake Data",
+             options={'ENUM_FLAG'},
+             items=(('POSE', "Pose", ""),
+                    ('OBJECT', "Object", ""),
+                    ),
+             default={'POSE'},
+             )
  
      def execute(self, context):
  
-         action = bake(self.frame_start, self.frame_end, self.step, self.only_selected)
+         action = bake(self.frame_start,
+                       self.frame_end,
+                       self.step,
+                       self.only_selected,
+                       'POSE' in self.bake_types,
+                       'OBJECT' in self.bake_types,
+                       self.clear_consraints,
+                       )
+         if action is None:
+             self.report({'INFO'}, "Nothing to bake")
+             return {'CANCELLED'}
  
          # basic cleanup, could move elsewhere
          for fcu in action.fcurves:
      def invoke(self, context, event):
          wm = context.window_manager
          return wm.invoke_props_dialog(self)
 +        
 +#################################
 +
 +class ClearUselessActions(bpy.types.Operator):
 +    '''Mark actions with no F-Curves for deletion after save+reload of file preserving "action libraries"'''
 +    bl_idname = "anim.clear_useless_actions"
 +    bl_label = "Clear Useless Actions"
 +    bl_options = {'REGISTER', 'UNDO'}
 +    
 +    only_unused = BoolProperty(name="Only Unused", 
 +            description="Only unused (Fake User only) actions get considered",
 +            default=True)
 +    
 +    @classmethod
 +    def poll(cls, context):
 +        return len(bpy.data.actions) != 0
 +        
 +    def execute(self, context):
 +        removed = 0
 +        
 +        for action in bpy.data.actions:
 +            # if only user is "fake" user...
 +            if ((self.only_unused is False) or 
 +                (action.use_fake_user and action.users == 1)):
 +                
 +                # if it has F-Curves, then it's a "action library" (i.e. walk, wave, jump, etc.) 
 +                # and should be left alone as that's what fake users are for!
 +                if not action.fcurves:
 +                    # mark action for deletion
 +                    action.user_clear()
 +                    removed += 1
 +        
 +        self.report({'INFO'}, "Removed %d empty and/or fake-user only Actions" % (removed))
 +        return {'FINISHED'}
@@@ -438,6 -438,8 +438,8 @@@ class USERPREF_PT_system(bpy.types.Pane
          col.label(text="OpenGL:")
          col.prop(system, "gl_clip_alpha", slider=True)
          col.prop(system, "use_mipmaps")
+         col.label(text="Anisotropic Filtering")
+         col.prop(system, "anisotropic_filter", text="")
          col.prop(system, "use_vertex_buffer_objects")
          #Anti-aliasing is disabled as it breaks broder/lasso select
          #col.prop(system, "use_antialiasing")
@@@ -743,7 -745,6 +745,7 @@@ class USERPREF_PT_file(bpy.types.Panel)
  
          col.prop(paths, "save_version")
          col.prop(paths, "recent_files")
 +        col.prop(paths, "use_update_recent_files_on_load")
          col.prop(paths, "use_save_preview_images")
          col.label(text="Auto Save:")
          col.prop(paths, "use_auto_save_temporary_files")
@@@ -98,6 -98,8 +98,8 @@@ class VIEW3D_HT_header(bpy.types.Header
              row.prop(toolsettings, "use_snap_peel_object", text="")
          elif toolsettings.snap_element == 'FACE':
              row.prop(toolsettings, "use_snap_project", text="")
+             if toolsettings.use_snap_project and obj.mode == 'EDIT':
+                 row.prop(toolsettings, "use_snap_project_self", text="")
  
          # OpenGL render
          row = layout.row(align=True)
@@@ -181,10 -183,6 +183,10 @@@ class VIEW3D_MT_transform(bpy.types.Men
  
          layout.operator("object.randomize_transform")
          layout.operator("object.align")
 +        
 +        layout.separator()
 +        
 +        layout.operator("object.anim_transforms_to_deltas")
  
  
  class VIEW3D_MT_mirror(bpy.types.Menu):
@@@ -85,6 -85,8 +85,6 @@@ bAction *add_empty_action(const char na
        bAction *act;
        
        act= alloc_libblock(&G.main->action, ID_AC, name);
 -      act->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore
 -      act->id.us++;
        
        return act;
  }     
@@@ -198,6 -200,9 +198,6 @@@ bAction *copy_action (bAction *src
                }
        }
        
 -      dst->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore
 -      dst->id.us++;
 -      
        return dst;
  }
  
@@@ -1123,7 -1128,7 +1123,7 @@@ void copy_pose_result(bPose *to, bPose 
  /* For the calculation of the effects of an Action at the given frame on an object 
   * This is currently only used for the Action Constraint 
   */
- void what_does_obaction (Scene *UNUSED(scene), Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe)
+ void what_does_obaction (Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe)
  {
        bActionGroup *agrp= action_groups_find_named(act, groupname);
        
@@@ -424,7 -424,7 +424,7 @@@ void constraint_mat_convertspace (Objec
  /* ------------ General Target Matrix Tools ---------- */
  
  /* function that sets the given matrix based on given vertex group in mesh */
- static void contarget_get_mesh_mat (Scene *scene, Object *ob, const char *substring, float mat[][4])
+ static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat[][4])
  {
        DerivedMesh *dm = NULL;
        Mesh *me= ob->data;
                freeDM= 1;
        }
        else {
-               /* when not in EditMode, use the 'final' derived mesh 
-                *      - check if the custom data masks for derivedFinal mean that we can just use that
-                *        (this is more effficient + sufficient for most cases)
-                */
-               if (!(ob->lastDataMask & CD_MASK_MDEFORMVERT)) {
-                       dm = mesh_get_derived_final(scene, ob, CD_MASK_MDEFORMVERT);
-                       freeDM= 1;
-               }
-               else 
-                       dm = (DerivedMesh *)ob->derivedFinal;
+               /* when not in EditMode, use the 'final' derived mesh, depsgraph
+                * ensures we build with CD_MDEFORMVERT layer */
+               dm = (DerivedMesh *)ob->derivedFinal;
        }
        
        /* only continue if there's a valid DerivedMesh */
@@@ -587,7 -580,7 +580,7 @@@ static void contarget_get_lattice_mat (
  
  /* generic function to get the appropriate matrix for most target cases */
  /* The cases where the target can be object data have not been implemented */
- static void constraint_target_to_mat4 (Scene *scene, Object *ob, const char *substring, float mat[][4], short from, short to, float headtail)
+ static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], short from, short to, float headtail)
  {
        /*      Case OBJECT */
        if (!strlen(substring)) {
         *              way as constraints can only really affect things on object/bone level.
         */
        else if (ob->type == OB_MESH) {
-               contarget_get_mesh_mat(scene, ob, substring, mat);
+               contarget_get_mesh_mat(ob, substring, mat);
                constraint_mat_convertspace(ob, NULL, mat, from, to);
        }
        else if (ob->type == OB_LATTICE) {
@@@ -684,10 -677,10 +677,10 @@@ static bConstraintTypeInfo CTI_CONSTRNA
  /* This function should be used for the get_target_matrix member of all 
   * constraints that are not picky about what happens to their target matrix.
   */
- static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+ static void default_get_tarmat (bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime))
  {
        if (VALID_CONS_TARGET(ct))
-               constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
+               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
        else if (ct)
                unit_m4(ct->matrix);
  }
@@@ -1159,7 -1152,7 +1152,7 @@@ static void kinematic_get_tarmat (bCons
        bKinematicConstraint *data= con->data;
        
        if (VALID_CONS_TARGET(ct)) 
-               constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
+               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
        else if (ct) {
                if (data->flag & CONSTRAINT_IK_AUTO) {
                        Object *ob= cob->ob;
@@@ -2046,7 -2039,7 +2039,7 @@@ static void pycon_get_tarmat (bConstrai
                /* firstly calculate the matrix the normal way, then let the py-function override
                 * this matrix if it needs to do so
                 */
-               constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
+               constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
                
                /* only execute target calculation if allowed */
  #ifdef WITH_PYTHON
@@@ -2165,7 -2158,7 +2158,7 @@@ static void actcon_get_tarmat (bConstra
                unit_m4(ct->matrix);
                
                /* get the transform matrix of the target */
-               constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
+               constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
                
                /* determine where in transform range target is */
                /* data->type is mapped as follows for backwards compatability:
                        tchan->rotmode= pchan->rotmode;
                        
                        /* evaluate action using workob (it will only set the PoseChannel in question) */
-                       what_does_obaction(cob->scene, cob->ob, &workob, pose, data->act, pchan->name, t);
+                       what_does_obaction(cob->ob, &workob, pose, data->act, pchan->name, t);
                        
                        /* convert animation to matrices for use here */
                        pchan_calc_mat(tchan);
                        
                        /* evaluate using workob */
                        // FIXME: we don't have any consistent standards on limiting effects on object...
-                       what_does_obaction(cob->scene, cob->ob, &workob, NULL, data->act, NULL, t);
+                       what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, t);
                        object_to_mat4(&workob, ct->matrix);
                }
                else {
@@@ -2648,7 -2641,7 +2641,7 @@@ static void distlimit_evaluate (bConstr
                        /* if inside, then move to surface */
                        if (dist <= data->dist) {
                                clamp_surf= 1;
 -                              sfac= data->dist / dist;
 +                              if (dist != 0.0f) sfac= data->dist / dist;
                        }
                        /* if soft-distance is enabled, start fading once owner is dist+softdist from the target */
                        else if (data->flag & LIMITDIST_USESOFT) {
                        /* if outside, then move to surface */
                        if (dist >= data->dist) {
                                clamp_surf= 1;
 -                              sfac= data->dist / dist;
 +                              if (dist != 0.0f) sfac= data->dist / dist;
                        }
                        /* if soft-distance is enabled, start fading once owner is dist-soft from the target */
                        else if (data->flag & LIMITDIST_USESOFT) {
                                // FIXME: there's a problem with "jumping" when this kicks in
                                if (dist >= (data->dist - data->soft)) {
                                        sfac = (float)( data->soft*(1.0f - expf(-(dist - data->dist)/data->soft)) + data->dist );
 -                                      sfac /= dist;
 +                                      if (dist != 0.0f) sfac /= dist;
                                        
                                        clamp_surf= 1;
                                }
                else {
                        if (IS_EQF(dist, data->dist)==0) {
                                clamp_surf= 1;
 -                              sfac= data->dist / dist;
 +                              if (dist != 0.0f) sfac= data->dist / dist;
                        }
                }
                
@@@ -4427,34 -4420,6 +4420,34 @@@ void get_constraint_target_matrix (stru
                unit_m4(mat);
        }
  }
 +
 +/* Get the list of targets required for solving a constraint */
 +void get_constraint_targets_for_solving (bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
 +{
 +      bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
 +      
 +      if (cti && cti->get_constraint_targets) {
 +              bConstraintTarget *ct;
 +              
 +              /* get targets 
 +               *      - constraints should use ct->matrix, not directly accessing values
 +               *      - ct->matrix members have not yet been calculated here! 
 +               */
 +              cti->get_constraint_targets(con, targets);
 +              
 +              /* set matrices 
 +               *      - calculate if possible, otherwise just initialise as identity matrix 
 +               */
 +              if (cti->get_target_matrix) {
 +                      for (ct= targets->first; ct; ct= ct->next) 
 +                              cti->get_target_matrix(con, cob, ct, ctime);
 +              }
 +              else {
 +                      for (ct= targets->first; ct; ct= ct->next)
 +                              unit_m4(ct->matrix);
 +              }
 +      }
 +}
   
  /* ---------- Evaluation ----------- */
  
@@@ -4499,7 -4464,27 +4492,7 @@@ void solve_constraints (ListBase *conli
                constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
                
                /* prepare targets for constraint solving */
 -              if (cti->get_constraint_targets) {
 -                      bConstraintTarget *ct;
 -                      
 -                      /* get targets 
 -                       *      - constraints should use ct->matrix, not directly accessing values
 -                       *      - ct->matrix members have not yet been calculated here! 
 -                       */
 -                      cti->get_constraint_targets(con, &targets);
 -                      
 -                      /* set matrices 
 -                       *      - calculate if possible, otherwise just initialise as identity matrix 
 -                       */
 -                      if (cti->get_target_matrix) {
 -                              for (ct= targets.first; ct; ct= ct->next) 
 -                                      cti->get_target_matrix(con, cob, ct, ctime);
 -                      }
 -                      else {
 -                              for (ct= targets.first; ct; ct= ct->next)
 -                                      unit_m4(ct->matrix);
 -                      }
 -              }
 +              get_constraint_targets_for_solving(con, cob, &targets, ctime);
                
                /* Solve the constraint and put result in cob->matrix */
                cti->evaluate_constraint(con, cob, &targets);
@@@ -4321,6 -4321,7 +4321,7 @@@ static void direct_link_object(FileDat
                MEM_freeN(hook);
        }
        
+       ob->customdata_mask= 0;
        ob->bb= NULL;
        ob->derivedDeform= NULL;
        ob->derivedFinal= NULL;
@@@ -11662,42 -11663,8 +11663,42 @@@ static void do_versions(FileData *fd, L
                                }
                        }
                }
 +              
 +              {
 +                      /* convert fcurve actuator to action actuator */
 +                      Object *ob;
 +                      bActuator *act;
 +                      bIpoActuator *ia;
 +                      bActionActuator *aa;
 +
 +                      for (ob= main->object.first; ob; ob= ob->id.next) {
 +                              for (act= ob->actuators.first; act; act= act->next) {
 +                                      if (act->type == ACT_IPO) {
 +                                              // Create the new actuator
 +                                              ia= act->data;
 +                                              aa= MEM_callocN(sizeof(bActionActuator), "fcurve -> action actuator do_version");
 +
 +                                              // Copy values
 +                                              aa->type = ia->type;
 +                                              aa->flag = ia->flag;
 +                                              aa->sta = ia->sta;
 +                                              aa->end = ia->end;
 +                                              strcpy(aa->name, ia->name);
 +                                              strcpy(aa->frameProp, ia->frameProp);
 +                                              aa->act = ob->adt->action;
 +
 +                                              // Get rid of the old actuator
 +                                              MEM_freeN(ia);
 +
 +                                              // Assign the new actuator
 +                                              act->data = aa;
 +                                              act->type= act->otype= ACT_ACTION;
 +                                              
 +                                      }
 +                              }
 +                      }
 +              }
        }
 -      
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
  
  
  #include <algorithm>
  
- // use this for retrieving bone names, since these must be unique
+ // first try node name, if not available (since is optional), fall back to original id
  template<class T>
  static const char *bc_get_joint_name(T *node)
  {
-       const std::string& id = node->getOriginalId();
-       return id.size() ? id.c_str() : node->getName().c_str();
+       const std::string& id = node->getName();
+       return id.size() ? id.c_str() : node->getOriginalId().c_str();
  }
  
  FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path)
@@@ -89,15 -89,12 +89,15 @@@ void AnimationImporter::animation_to_fc
  {
        COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues();
        COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues();
 -      // COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
 -      // COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
 +   
 +      if( curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ) {
 +      COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
 +    COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
 +      }
        float fps = (float)FPS;
        size_t dim = curve->getOutDimension();
        unsigned int i;
 -
 +      
        std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()];
  
        switch (dim) {
                                fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
                                // fcu->rna_path = BLI_strdupn(path, strlen(path));
                                fcu->array_index = 0;
 -                              //fcu->totvert = curve->getKeyCount();
 +                              fcu->totvert = curve->getKeyCount();
                        
                                // create beztriple for each key
                                for (unsigned int j = 0; j < curve->getKeyCount(); j++) {
                                        BezTriple bez;
                                        memset(&bez, 0, sizeof(BezTriple));
  
 -                                      // intangent
 -                                      // bez.vec[0][0] = get_float_value(intan, j * 6 + i + i) * fps;
 -                                      // bez.vec[0][1] = get_float_value(intan, j * 6 + i + i + 1);
 -
 +                                      
                                        // input, output
                                        bez.vec[1][0] = bc_get_float_value(input, j) * fps; 
                                        bez.vec[1][1] = bc_get_float_value(output, j * dim + i);
  
 -                                      // outtangent
 -                                      // bez.vec[2][0] = get_float_value(outtan, j * 6 + i + i) * fps;
 -                                      // bez.vec[2][1] = get_float_value(outtan, j * 6 + i + i + 1);
  
 -                                      bez.ipo = U.ipo_new; /* use default interpolation mode here... */
 +                                      if( curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ) 
 +                                      {
 +                                              COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
 +                        COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
 +
 +                                              // intangent
 +                                               bez.vec[0][0] = bc_get_float_value(intan, (j * 2 * dim ) + (2 * i)) * fps;
 +                                               bez.vec[0][1] = bc_get_float_value(intan, (j * 2 * dim )+ (2 * i) + 1);
 +
 +                                               // outtangent
 +                                               bez.vec[2][0] = bc_get_float_value(outtan, (j * 2 * dim ) + (2 * i)) * fps;
 +                                               bez.vec[2][1] = bc_get_float_value(outtan, (j * 2 * dim )+ (2 * i) + 1);
 +                                           bez.ipo = BEZT_IPO_BEZ;
 +                                               //bez.h1 = bez.h2 = HD_AUTO;   
 +                                      }
 +                                      else 
 +                                      {
 +                                              bez.h1 = bez.h2 = HD_AUTO; 
 +                                              bez.ipo = BEZT_IPO_LIN;
 +                                      }
 +                                      // bez.ipo = U.ipo_new; /* use default interpolation mode here... */
                                        bez.f1 = bez.f2 = bez.f3 = SELECT;
 -                                      bez.h1 = bez.h2 = HD_AUTO;
 +                                      
                                        insert_bezt_fcurve(fcu, &bez, 0);
                                }
  
                unused_curves.push_back(*it);
  }
  
 +
  void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
  {
        for (unsigned int i = 0; i < cu->totvert; i++) {
                // TODO convert handles too
                cu->bezt[i].vec[1][1] *= M_PI / 180.0f;
 +              cu->bezt[i].vec[0][1] *= M_PI / 180.0f;
 +              cu->bezt[i].vec[2][1] *= M_PI / 180.0f;
 +              cu->bezt[i].vec[1][0];
        }
  }
  
@@@ -298,11 -277,10 +298,11 @@@ bool AnimationImporter::write_animation
  bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList* animlist) 
  {
        const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId();
 -
 +    
        animlist_map[animlist_id] = animlist;
 -
 +    
  #if 0
 +
        // should not happen
        if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) {
                return true;
        // what does this AnimationList animate?
        Animation& animated = uid_animated_map[animlist_id];
        Object *ob = animated.ob;
 -
 +    
        char rna_path[100];
        char joint_path[100];
        bool is_joint = false;
  
        // if ob is NULL, it should be a JOINT
        if (!ob) {
 +              
                ob = armature_importer->get_armature_for_joint(animated.node);
  
                if (!ob) {
 -                      fprintf(stderr, "Cannot find armature for node %s\n", get_joint_name(animated.node));
 +//                    fprintf(stderr, "Cannot find armature for node %s\n", get_joint_name(animated.node));
                        return true;
                }
  
  
                is_joint = true;
        }
 -      
 +      printf("object for animlist: %s found\n", animlist->getUniqueId().toAscii().c_str());
        const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
  
        switch (animated.tm->getTransformationType()) {
@@@ -535,320 -512,66 +535,320 @@@ virtual void AnimationImporter::change_
  }
  #endif
  
 -// prerequisites:
 -// animlist_map - map animlist id -> animlist
 -// curve_map - map anim id -> curve(s)
 -Object *AnimationImporter::translate_animation(COLLADAFW::Node *node,
 -                                                      std::map<COLLADAFW::UniqueId, Object*>& object_map,
 -                                                      std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
 -                                                      COLLADAFW::Transformation::TransformationType tm_type,
 -                                                      Object *par_job)
 +
 +//sets the rna_path and array index to curve
 +void AnimationImporter::modify_fcurve(std::vector<FCurve*>* curves , char* rna_path , int array_index )
 +{   
 +      std::vector<FCurve*>::iterator it;
 +      int i;
 +      for (it = curves->begin(), i = 0; it != curves->end(); it++, i++) {
 +              FCurve *fcu = *it;
 +              fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
 +              
 +              if (array_index == -1) fcu->array_index = i;
 +              else fcu->array_index = array_index;
 +
 +              unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
 +      }
 +}
 +
 +void AnimationImporter::find_frames( std::vector<float>* frames , std::vector<FCurve*>* curves)
  {
 -      bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
 +      std::vector<FCurve*>::iterator iter;
 +              for (iter = curves->begin(); iter != curves->end(); iter++) {
 +                      FCurve *fcu = *iter;
 +        
 +              for (unsigned int k = 0; k < fcu->totvert; k++) {
 +                      //get frame value from bezTriple
 +                      float fra = fcu->bezt[k].vec[1][0];
 +                      //if frame already not added add frame to frames
 +                      if (std::find(frames->begin(), frames->end(), fra) == frames->end())
 +                              frames->push_back(fra);
 +                                                      
 +              }
 +              }
 +}
 +
 +//creates the rna_paths and array indices of fcurves from animations using transformation and bound animation class of each animation.
 +void AnimationImporter:: Assign_transform_animations(std::vector<float>* frames, 
 +                                                                                                       COLLADAFW::Transformation * transform , 
 +                                                                                                       const COLLADAFW::AnimationList::AnimationBinding * binding,
 +                                                                                                       std::vector<FCurve*>* curves, bool is_joint, char * joint_path)
 +{
 +      COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
        bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
 -      bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
 +      bool is_rotation = tm_type  == COLLADAFW::Transformation::ROTATE;
 +      
 +      //to check if the no of curves are valid
 +      bool xyz = ((tm_type == COLLADAFW::Transformation::TRANSLATE ||tm_type  == COLLADAFW::Transformation::SCALE) && binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
 +                        
 +      
 +      if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) {
 +              fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves->size());
 +              return;
 +      }
 +    
 +      //find key frames of the animation and accumulates them to frames of the transformation.
 +      find_frames (frames , curves );
  
 +      char rna_path[100];
 +      //char joint_path[100];
 +      
 +                                              
 +      switch (tm_type) {
 +              case COLLADAFW::Transformation::TRANSLATE:
 +              case COLLADAFW::Transformation::SCALE:
 +                      {
 +                              bool loc = tm_type == COLLADAFW::Transformation::TRANSLATE;
 +                              if (is_joint)
 +                                      BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale");
 +                              else
 +                                      BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path));
 +
 +                              switch (binding->animationClass) {
 +                                      case COLLADAFW::AnimationList::POSITION_X:
 +                                              modify_fcurve(curves, rna_path, 0 );
 +                                              break;
 +                                      case COLLADAFW::AnimationList::POSITION_Y:
 +                                              modify_fcurve(curves, rna_path, 1 );
 +                                              break;
 +                                      case COLLADAFW::AnimationList::POSITION_Z:
 +                                              modify_fcurve(curves, rna_path, 2 );
 +                                              break;
 +                                      case COLLADAFW::AnimationList::POSITION_XYZ:
 +                                              modify_fcurve(curves, rna_path, -1 );
 +                                              break;
 +                                      default:
 +                                              fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
 +                                                              binding->animationClass, loc ? "TRANSLATE" : "SCALE");
 +                                      }
 +              break;
 +                      }
 +              
 +              
 +              case COLLADAFW::Transformation::ROTATE:
 +                      {
 +                              if (is_joint)
 +                                      BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path);
 +                              else
 +                                      BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path));
 +                std::vector<FCurve*>::iterator iter;
 +                              for (iter = curves->begin(); iter != curves->end(); iter++) {
 +                                      FCurve* fcu = *iter;
 +                                      
 +                                      //if transform is rotation the fcurves values must be turned in to radian.
 +                                      if (is_rotation)
 +                                              fcurve_deg_to_rad(fcu);          
 +                              }                                       
 +                              COLLADAFW::Rotate* rot = (COLLADAFW::Rotate*)transform;
 +                              COLLADABU::Math::Vector3& axis = rot->getRotationAxis();
 +                      
 +                              switch (binding->animationClass) {
 +                                      case COLLADAFW::AnimationList::ANGLE:
 +                                              if (COLLADABU::Math::Vector3::UNIT_X == axis) {
 +                                                      modify_fcurve(curves, rna_path, 0 );
 +                                              }
 +                                              else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
 +                                                      modify_fcurve(curves, rna_path, 1 );
 +                                              }
 +                                              else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
 +                                                      modify_fcurve(curves, rna_path, 2 );
 +                                              }
 +                                              break;
 +                                      case COLLADAFW::AnimationList::AXISANGLE:
 +                                              // TODO convert axis-angle to quat? or XYZ?
 +                                      default:
 +                                              fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n",
 +                                                              binding->animationClass);
 +                                      }
 +                      break;
 +                      }
 +                      
 +              case COLLADAFW::Transformation::MATRIX:
 +              case COLLADAFW::Transformation::SKEW:
 +              case COLLADAFW::Transformation::LOOKAT:
 +                      fprintf(stderr, "Animation of MATRIX, SKEW and LOOKAT transformations is not supported yet.\n");
 +                      break;
 +              }
 +      
 +}
 +
 +void AnimationImporter::translate_Animations_NEW ( COLLADAFW::Node * node , 
 +                                                                                                 std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
 +                                                                                                 std::map<COLLADAFW::UniqueId, Object*>& object_map )
 +{
 +      bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
 +      
        COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
 -      Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()];
 +      Object *ob = is_joint ? armature_importer->get_armature_for_joint(root) : object_map[node->getUniqueId()];
 +      
        const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
 +    
 +      if ( ! is_object_animated(node) ) return ;  
  
 +    char joint_path[200];
 +
 +      if ( is_joint ) 
 +      armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
 +      
 +      bAction * act;
 +      bActionGroup *grp = NULL;
 +    
 +      if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID*)&ob->id, 1);
 +                  else act = ob->adt->action;
 +                              //Get the list of animation curves of the object
 +    
 +      ListBase *AnimCurves = &(act->curves);
 +      
        if (!ob) {
                fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
 -              return NULL;
 +              return;
        }
  
 -      // frames at which to sample
 -      std::vector<float> frames;
 +      
 +      /*float irest_dae[4][4];
 +      float rest[4][4], irest[4][4];
 +
 +      if (is_joint) {
 +              get_joint_rest_mat(irest_dae, root, node);
 +              invert_m4(irest_dae);
 +
 +              Bone *bone = get_named_bone((bArmature*)ob->data, bone_name);
 +              if (!bone) {
 +                      fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
 +                      return;
 +              }
 +
 +              unit_m4(rest);
 +              copy_m4_m4(rest, bone->arm_mat);
 +              invert_m4_m4(irest, rest);
 +      }*/
 +    
 +      const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
 +      
 +      //for each transformation in node 
 +      for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
 +              COLLADAFW::Transformation *transform = nodeTransforms[i];
 +              COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
 +
 +              bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
 +              bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
 +                      
 +              const COLLADAFW::UniqueId& listid = transform->getAnimationList();
 +              
 +              //might not be needed
 +              std::vector<float> frames;
 +                      
 +              //check if transformation has animations    
 +              if (animlist_map.find(listid) == animlist_map.end()) continue ; 
 +              else 
 +                      {
 +                              //transformation has animations
 +                              const COLLADAFW::AnimationList *animlist = animlist_map[listid];
 +                              const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
 +                //all the curves belonging to the current binding
 +                              std::vector<FCurve*> animcurves;    
 +                              for (unsigned int j = 0; j < bindings.getCount(); j++) {
 +                                       animcurves = curve_map[bindings[j].animation];
 +                                      //calculate rnapaths and array index of fcurves according to transformation and animation class
 +                                       Assign_transform_animations(&frames,transform, &bindings[j], &animcurves, is_joint, joint_path ); 
 +                                      
 +                                       std::vector<FCurve*>::iterator iter;
 +                                  //Add the curves of the current animation to the object
 +                                              for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
 +                                                      FCurve * fcu = *iter;
 +                                                       if (ob->type == OB_ARMATURE) 
 +                                                              add_bone_fcurve( ob, node , fcu );
 +                                                       else 
 +                                                       BLI_addtail(AnimCurves, fcu);  
 +                                              }                               
 +                              }
 +                       std::sort(frames.begin(), frames.end());
 +                      }
 +              if (is_rotation || is_matrix) {
 +                      if (is_joint) 
 +                      {
 +                              bPoseChannel *chan = get_pose_channel(ob->pose, bone_name);
 +                              chan->rotmode = ROT_MODE_EUL;
 +                      }
 +                      else 
 +                      {
 +                              ob->rotmode = ROT_MODE_EUL;
 +                      }
 +              }
 +      }
 +      
 +}
 +
 +//Check if object is animated by checking if animlist_map holds the animlist_id of node transforms
 +bool AnimationImporter::is_object_animated ( const COLLADAFW::Node * node ) 
 +{
 +      bool exists = false;
 +      const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
 +      
 +      //for each transformation in node 
 +      for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
 +              COLLADAFW::Transformation *transform = nodeTransforms[i];
 +              const COLLADAFW::UniqueId& listid = transform->getAnimationList();
 +              
 +              //check if transformation has animations    
 +              if (animlist_map.find(listid) == animlist_map.end()) continue ;
 +              else 
 +              {
 +                      exists = true;
 +                      break;
 +              }
 +      }
 +
 +      return exists;
 +}
  
 +//XXX Is not used anymore.
 +void AnimationImporter::find_frames_old(std::vector<float> * frames, COLLADAFW::Node * node , COLLADAFW::Transformation::TransformationType tm_type)
 +{
 +      bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
 +      bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
        // for each <rotate>, <translate>, etc. there is a separate Transformation
 -      const COLLADAFW::TransformationPointerArray& tms = node->getTransformations();
 +      const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
  
        unsigned int i;
 -
        // find frames at which to sample plus convert all rotation keys to radians
 -      for (i = 0; i < tms.getCount(); i++) {
 -              COLLADAFW::Transformation *tm = tms[i];
 -              COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
 +      for (i = 0; i < nodeTransforms.getCount(); i++) {
 +              COLLADAFW::Transformation *transform = nodeTransforms[i];
 +              COLLADAFW::Transformation::TransformationType nodeTmType = transform->getTransformationType();
  
 -              if (type == tm_type) {
 -                      const COLLADAFW::UniqueId& listid = tm->getAnimationList();
  
 +              if (nodeTmType == tm_type) {
 +                      //get animation bindings for the current transformation
 +                      const COLLADAFW::UniqueId& listid = transform->getAnimationList();
 +                      //if transform is animated its animlist must exist.
                        if (animlist_map.find(listid) != animlist_map.end()) {
 +                              
                                const COLLADAFW::AnimationList *animlist = animlist_map[listid];
                                const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
 -
 +                
                                if (bindings.getCount()) {
 +                                      //for each AnimationBinding get the fcurves which animate the transform
                                        for (unsigned int j = 0; j < bindings.getCount(); j++) {
                                                std::vector<FCurve*>& curves = curve_map[bindings[j].animation];
 -                                              bool xyz = ((type == COLLADAFW::Transformation::TRANSLATE || type == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
 +                                              bool xyz = ((nodeTmType == COLLADAFW::Transformation::TRANSLATE || nodeTmType == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
  
                                                if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) {
                                                        std::vector<FCurve*>::iterator iter;
  
                                                        for (iter = curves.begin(); iter != curves.end(); iter++) {
                                                                FCurve *fcu = *iter;
 -
 +                                
 +                                                              //if transform is rotation the fcurves values must be turned in to radian.
                                                                if (is_rotation)
                                                                        fcurve_deg_to_rad(fcu);
  
                                                                for (unsigned int k = 0; k < fcu->totvert; k++) {
 +                                                                      //get frame value from bezTriple
                                                                        float fra = fcu->bezt[k].vec[1][0];
 -                                                                      if (std::find(frames.begin(), frames.end(), fra) == frames.end())
 -                                                                              frames.push_back(fra);
 +                                                                      //if frame already not added add frame to frames
 +                                                                      if (std::find(frames->begin(), frames->end(), fra) == frames->end())
 +                                                                              frames->push_back(fra);
                                                                }
                                                        }
                                                }
                        }
                }
        }
 +}
 +
  
 +// prerequisites:
 +// animlist_map - map animlist id -> animlist
 +// curve_map - map anim id -> curve(s)
 +Object *AnimationImporter::translate_animation(COLLADAFW::Node *node,
 +                                                      std::map<COLLADAFW::UniqueId, Object*>& object_map,
 +                                                      std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
 +                                                      COLLADAFW::Transformation::TransformationType tm_type,
 +                                                      Object *par_job)
 +{
 +      
 +      bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
 +      bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
 +      bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
 +      
 +      COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
 +      Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()];
 +      const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
 +      if (!ob) {
 +              fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
 +              return NULL;
 +      }
 +
 +      // frames at which to sample
 +      std::vector<float> frames;
 +      
 +      find_frames_old(&frames, node , tm_type);
 +      
 +      unsigned int i;
 +      
        float irest_dae[4][4];
        float rest[4][4], irest[4][4];
  
                        BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
                else
                        strcpy(rna_path, tm_str);
 -
                newcu[i] = create_fcurve(axis, rna_path);
  
  #ifdef ARMATURE_TEST
@@@ -1134,7 -827,8 +1134,8 @@@ void AnimationImporter::evaluate_transf
  
                unit_m4(m);
  
-               if (!evaluate_animation(tm, m, fra, node->getOriginalId().c_str())) {
+               std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
+               if (!evaluate_animation(tm, m, fra, nodename.c_str())) {
                        switch (type) {
                        case COLLADAFW::Transformation::ROTATE:
                                dae_rotate_to_mat4(tm, m);
  
  #include "ArmatureImporter.h"
  
- // use this for retrieving bone names, since these must be unique
+ // use node name, or fall back to original id if not present (name is optional)
  template<class T>
  static const char *bc_get_joint_name(T *node)
  {
-       const std::string& id = node->getOriginalId();
-       return id.size() ? id.c_str() : node->getName().c_str();
+       const std::string& id = node->getName();
+       return id.size() ? id.c_str() : node->getOriginalId().c_str();
  }
  
  ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, AnimationImporterBase *anim, Scene *sce) :
@@@ -78,67 -78,6 +78,67 @@@ JointData *ArmatureImporter::get_joint_
        return &joint_index_to_joint_info_map[joint_index];
  }
  #endif
 +void ArmatureImporter::create_unskinned_bone( COLLADAFW::Node *node, EditBone *parent, int totchild,
 +                               float parent_mat[][4], bArmature *arm)
 +{
 +      float mat[4][4];
 +   float obmat[4][4];
 +
 +      // object-space
 +      get_node_mat(obmat, node, NULL, NULL);
 +
 +      // get world-space
 +      if (parent)
 +              mul_m4_m4m4(mat, obmat, parent_mat);
 +      else
 +              copy_m4_m4(mat, obmat);
 +
 +      EditBone *bone = ED_armature_edit_bone_add(arm, (char*)bc_get_joint_name(node));
 +      totbone++;
 +
 +      if (parent) bone->parent = parent;
 +
 +      // set head
 +      copy_v3_v3(bone->head, mat[3]);
 +
 +      // set tail, don't set it to head because 0-length bones are not allowed
 +      float vec[3] = {0.0f, 0.5f, 0.0f};
 +      add_v3_v3v3(bone->tail, bone->head, vec);
 +
 +      // set parent tail
 +      if (parent && totchild == 1) {
 +              copy_v3_v3(parent->tail, bone->head);
 +
 +              // not setting BONE_CONNECTED because this would lock child bone location with respect to parent
 +              // bone->flag |= BONE_CONNECTED;
 +
 +              // XXX increase this to prevent "very" small bones?
 +              const float epsilon = 0.000001f;
 +
 +              // derive leaf bone length
 +              float length = len_v3v3(parent->head, parent->tail);
 +              if ((length < leaf_bone_length || totbone == 0) && length > epsilon) {
 +                      leaf_bone_length = length;
 +              }
 +
 +              // treat zero-sized bone like a leaf bone
 +              if (length <= epsilon) {
 +                      add_leaf_bone(parent_mat, parent);
 +              }
 +
 +      }
 +
 +      COLLADAFW::NodePointerArray& children = node->getChildNodes();
 +      for (unsigned int i = 0; i < children.getCount(); i++) {
 +              create_unskinned_bone( children[i], bone, children.getCount(), mat, arm);
 +      }
 +
 +      // in second case it's not a leaf bone, but we handle it the same way
 +      if (!children.getCount() || children.getCount() > 1) {
 +              add_leaf_bone(mat, bone);
 +      }
 +
 +}
  
  void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
                                 float parent_mat[][4], bArmature *arm)
@@@ -361,47 -300,6 +361,47 @@@ ArmatureJoints& ArmatureImporter::get_a
        return armature_joints.back();
  }
  #endif
 +void ArmatureImporter::create_armature_bones( )
 +{
 +      std::vector<COLLADAFW::Node*>::iterator ri;
 +      //if there is an armature created for root_joint next root_joint
 +      for (ri = root_joints.begin(); ri != root_joints.end(); ri++) {
 +                      if ( get_armature_for_joint(*ri) != NULL ) continue;
 +          
 +        //add armature object for current joint
 +              //Object *ob_arm = add_object(scene, OB_ARMATURE);
 +
 +              Object *ob_arm = joint_parent_map[(*ri)->getUniqueId()];
 +              //ob_arm->type = OB_ARMATURE;
 +              ED_armature_to_edit(ob_arm);
 +
 +              // min_angle = 360.0f;          // minimum angle between bone head-tail and a row of bone matrix
 +
 +              // create unskinned bones
 +              /*
 +                 TODO:
 +                 check if bones have already been created for a given joint
 +              */
 +     leaf_bone_length = FLT_MAX;
 +              create_unskinned_bone(*ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature*)ob_arm->data);
 +
 +              fix_leaf_bones();
 +
 +      // exit armature edit mode
 +      
 +
 +      //if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && ob_arm->parent!=NULL)
 +      //      ob_arm->parent = joint_parent_map[(*ri)->getUniqueId()];
 +      
 +      unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
 +
 +      ED_armature_from_edit(ob_arm);
 +      ED_armature_edit_free(ob_arm);
 +      DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB|OB_RECALC_DATA);
 +      }
 +
 +      
 +}
  
  void ArmatureImporter::create_armature_bones(SkinInfo& skin)
  {
        if (shared)
                ob_arm = skin.set_armature(shared);
        else
 -              ob_arm = skin.create_armature(scene);
 +              ob_arm = skin.create_armature(scene); //once for every armature
  
        // enter armature edit mode
        ED_armature_to_edit(ob_arm);
        DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB|OB_RECALC_DATA);
  
        // set_leaf_bone_shapes(ob_arm);
 -      // set_euler_rotmode();
 +    // set_euler_rotmode();
  }
  
  
  // root - if this joint is the top joint in hierarchy, if a joint
  // is a child of a node (not joint), root should be true since
  // this is where we build armature bones from
 -void ArmatureImporter::add_joint(COLLADAFW::Node *node, bool root, Object *parent)
 +
 +void ArmatureImporter::add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce)
  {
        joint_by_uid[node->getUniqueId()] = node;
        if (root) {
                root_joints.push_back(node);
  
 -              if (parent)
 +              if (parent) {
 +                                      
                        joint_parent_map[node->getUniqueId()] = parent;
 +              }
        }
  }
  
@@@ -577,9 -472,6 +577,9 @@@ void ArmatureImporter::make_armatures(b
                // free memory stolen from SkinControllerData
                skin.free();
        }
 +
 +      create_armature_bones();
 +
  }
  
  #if 0
@@@ -674,12 -566,7 +674,12 @@@ Object *ArmatureImporter::get_armature_
                if (skin.uses_joint_or_descendant(node))
                        return skin.get_armature();
        }
 -
 +   
 +       std::map<COLLADAFW::UniqueId, Object*>::iterator arm;
 +      for (arm = unskinned_armature_map.begin(); arm != unskinned_armature_map.end(); arm++) {
 +              if(arm->first == node->getUniqueId() )
 +                      return arm->second;
 +      }
        return NULL;
  }
  
@@@ -44,25 -44,24 +44,25 @@@ set(INC_SY
  
  if(APPLE)
        list(APPEND INC_SYS
-               ${OPENCOLLADA_INC}/COLLADAStreamWriter
-               ${OPENCOLLADA_INC}/COLLADABaseUtils
-               ${OPENCOLLADA_INC}/COLLADAFramework
-               ${OPENCOLLADA_INC}/COLLADASaxFrameworkLoader
-               ${OPENCOLLADA_INC}/GeneratedSaxParser 
+               ${OPENCOLLADA_INCLUDE_DIR}/COLLADAStreamWriter
+               ${OPENCOLLADA_INCLUDE_DIR}/COLLADABaseUtils
+               ${OPENCOLLADA_INCLUDE_DIR}/COLLADAFramework
+               ${OPENCOLLADA_INCLUDE_DIR}/COLLADASaxFrameworkLoader
+               ${OPENCOLLADA_INCLUDE_DIR}/GeneratedSaxParser
        )
  else()
        list(APPEND INC_SYS
-               ${OPENCOLLADA_INC}/COLLADAStreamWriter/include
-               ${OPENCOLLADA_INC}/COLLADABaseUtils/include
-               ${OPENCOLLADA_INC}/COLLADAFramework/include
-               ${OPENCOLLADA_INC}/COLLADASaxFrameworkLoader/include 
-               ${OPENCOLLADA_INC}/GeneratedSaxParser/include 
+               ${OPENCOLLADA_INCLUDE_DIR}/COLLADAStreamWriter/include
+               ${OPENCOLLADA_INCLUDE_DIR}/COLLADABaseUtils/include
+               ${OPENCOLLADA_INCLUDE_DIR}/COLLADAFramework/include
+               ${OPENCOLLADA_INCLUDE_DIR}/COLLADASaxFrameworkLoader/include
+               ${OPENCOLLADA_INCLUDE_DIR}/GeneratedSaxParser/include
        )
  endif()
  
  set(SRC
        AnimationImporter.cpp
 +      AnimationExporter.cpp
        ArmatureExporter.cpp
        ArmatureImporter.cpp
        CameraExporter.cpp
@@@ -85,7 -84,6 +85,7 @@@
        collada_utils.cpp
  
        AnimationImporter.h
 +      AnimationExporter.h     
        ArmatureExporter.h
        ArmatureImporter.h
        CameraExporter.h
@@@ -250,13 -250,12 +250,13 @@@ void DocumentImporter::translate_anim_r
        unsigned int i;
        Object *ob;
  
 -      for (i = 0; i < 4; i++)
 -              ob = anim_importer.translate_animation(node, object_map, root_map, types[i]);
 +      //for (i = 0; i < 4; i++)
 +              //ob = 
 +      anim_importer.translate_Animations_NEW(node, root_map, object_map);
  
        COLLADAFW::NodePointerArray &children = node->getChildNodes();
        for (i = 0; i < children.getCount(); i++) {
 -              translate_anim_recursive(children[i], node, ob);
 +              translate_anim_recursive(children[i], node, NULL);
        }
  }
  
@@@ -310,7 -309,7 +310,7 @@@ Object* DocumentImporter::create_lamp_o
        return ob;
  }
  
- Object* DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
+ Object* DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, Object *par_ob, bool is_library_node)
  {
        Object *obn = copy_object(source_ob);
        obn->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
                        Object *new_child = NULL;
                        if (inodes.getCount()) { // \todo loop through instance nodes
                                const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
-                               new_child = create_instance_node(object_map[id], node_map[id], child_node, sce, is_library_node);
+                               new_child = create_instance_node(object_map[id], node_map[id], child_node, sce, NULL, is_library_node);
                        }
                        else {
-                               new_child = create_instance_node(object_map[child_id], child_node, NULL, sce, is_library_node);
+                               new_child = create_instance_node(object_map[child_id], child_node, NULL, sce, NULL, is_library_node);
                        }
                        bc_set_parent(new_child, obn, mContext, true);
  
  
        // when we have an instance_node, don't return the object, because otherwise
        // its correct location gets overwritten in write_node(). Fixes bug #26012.
-       if(instance_node) return NULL;
+       if(instance_node) {
+               if (par_ob && obn)
+                       bc_set_parent(obn, par_ob, mContext);
+               return NULL;
+       }
        else return obn;
  }
  
@@@ -378,14 -382,7 +383,14 @@@ void DocumentImporter::write_node (COLL
        bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
  
        if (is_joint) {
 -              armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par);
 +              if ( par ) {
 +              Object * empty = par;
 +              par = add_object(sce, OB_ARMATURE);
 +              bc_set_parent(par,empty->parent, mContext);
 +              //remove empty : todo
 +              object_map[parent_node->getUniqueId()] = par;
 +              }
 +              armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
        }
        else {
                COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
                COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
                COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
                COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
-               int geom_done = 0;
-               int camera_done = 0;
-               int lamp_done = 0;
-               int controller_done = 0;
-               int inst_done = 0;
+               size_t geom_done = 0;
+               size_t camera_done = 0;
+               size_t lamp_done = 0;
+               size_t controller_done = 0;
+               size_t inst_done = 0;
  
                // XXX linking object with the first <instance_geometry>, though a node may have more of them...
                // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
                                Object *source_ob = object_map[node_id];
                                COLLADAFW::Node *source_node = node_map[node_id];
  
-                               ob = create_instance_node(source_ob, source_node, node, sce, is_library_node);
+                               ob = create_instance_node(source_ob, source_node, node, sce, par, is_library_node);
                        }
                        ++inst_done;
                }
                // check if object is not NULL
                if (!ob) return;
                
-               rename_id(&ob->id, (char*)node->getOriginalId().c_str());
+               std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
+               rename_id(&ob->id, (char*)nodename.c_str());
  
                object_map[node->getUniqueId()] = ob;
                node_map[node->getUniqueId()] = node;
@@@ -526,7 -524,7 +532,7 @@@ bool DocumentImporter::writeMaterial( c
        if(mImportStage!=General)
                return true;
                
-       const std::string& str_mat_id = cmat->getOriginalId();
+       const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
        Material *ma = add_material((char*)str_mat_id.c_str());
        
        this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
@@@ -678,6 -676,18 +684,18 @@@ void DocumentImporter::write_profile_CO
                        i++;
                }
        }
+       
+       if(ef->getOpacity().isTexture()) {
+               COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
+               mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
+               if(mtex != NULL) {
+                       mtex->mapto = MAP_ALPHA;
+                       mtex->tex->imaflag |= TEX_USEALPHA;
+                       i++;
+                       ma->spectra = ma->alpha = 0;
+                       ma->mode |= MA_ZTRANSP|MA_TRANSP;
+               }
+       }
        // TRANSPARENT
        // color
  //    if (ef->getOpacity().isColor()) {
  #include "SkinInfo.h"
  #include "collada_utils.h"
  
- // use this for retrieving bone names, since these must be unique
+ // use name, or fall back to original id if name not present (name is optional)
  template<class T>
  static const char *bc_get_joint_name(T *node)
  {
-       const std::string& id = node->getOriginalId();
-       return id.size() ? id.c_str() : node->getName().c_str();
+       const std::string& id = node->getName();
+       return id.size() ? id.c_str() : node->getOriginalId().c_str();
  }
  
  // This is used to store data passed in write_controller_data.
@@@ -308,15 -308,11 +308,15 @@@ void SkinInfo::find_root_joints(const s
                                          std::vector<COLLADAFW::Node*>& result)
  {
        std::vector<COLLADAFW::Node*>::const_iterator it;
 +      // for each root_joint
        for (it = root_joints.begin(); it != root_joints.end(); it++) {
                COLLADAFW::Node *root = *it;
                std::vector<JointData>::iterator ji;
 +              //for each joint_data in this skin
                for (ji = joint_data.begin(); ji != joint_data.end(); ji++) {
 +                      //get joint node from joint map
                        COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid];
 +                      //find if joint node is in the tree belonging to the root_joint
                        if (find_node_in_tree(joint, root)) {
                                if (std::find(result.begin(), result.end(), root) == result.end())
                                        result.push_back(root);
@@@ -663,7 -663,7 +663,7 @@@ void ui_theme_init_default(void
  
        SETCOL(btheme->tipo.handle_vertex,              0, 0, 0, 255);
        SETCOL(btheme->tipo.handle_vertex_select, 255, 133, 0, 255);
 -      btheme->tipo.handle_vertex_size= 3;
 +      btheme->tipo.handle_vertex_size= 4;
        
        SETCOL(btheme->tipo.ds_channel,         82, 96, 110, 255);
        SETCOL(btheme->tipo.ds_subchannel,      124, 137, 150, 255);
@@@ -1580,6 -1580,8 +1580,8 @@@ void init_userdef_do_versions(void
                U.dragthreshold= 5;
        if (U.widget_unit==0)
                U.widget_unit= (U.dpi * 20 + 36)/72;
+       if (U.anisotropic_filter <= 0)
+               U.anisotropic_filter = 1;
  
        /* funny name, but it is GE stuff, moves userdef stuff to engine */
  // XXX        space_set_commmandline_options();
@@@ -1217,87 -1217,6 +1217,87 @@@ static void draw_b_bone(int dt, int arm
        }
  }
  
 +static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments)
 +{
 +      if ((segments > 1) && (pchan)) {
 +              float dlen= length/(float)segments;
 +              Mat4 *bbone = bbones;
 +              int a;
 +              
 +              for (a=0; a<segments; a++, bbone++) {
 +                      glPushMatrix();
 +                      glMultMatrixf(bbone->mat);
 +                      
 +                      glBegin(GL_LINES);
 +                      glVertex3f(0.0f, 0.0f, 0.0f);
 +                      glVertex3f(0.0f, dlen, 0.0f);
 +                      glEnd(); // GL_LINES
 +                      
 +                      glPopMatrix();
 +              }
 +      }
 +      else {
 +              glPushMatrix();
 +              
 +              glBegin(GL_LINES);
 +              glVertex3f(0.0f, 0.0f, 0.0f);
 +              glVertex3f(0.0f, length, 0.0f);
 +              glEnd();
 +              
 +              glPopMatrix();
 +      }
 +}
 +
 +static void draw_wire_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
 +{
 +      Mat4 *bbones = NULL;
 +      int segments = 0;
 +      float length;
 +      
 +      if (pchan) {
 +              segments= pchan->bone->segments;
 +              length= pchan->bone->length;
 +              
 +              if (segments > 1)
 +                      bbones = b_bone_spline_setup(pchan, 0);
 +      }
 +      else 
 +              length= ebone->length;
 +      
 +      /* draw points only if... */
 +      if (armflag & ARM_EDITMODE) {
 +              /* move to unitspace */
 +              glPushMatrix();
 +              glScalef(length, length, length);
 +              draw_bone_points(dt, armflag, boneflag, id);
 +              glPopMatrix();
 +              length *= 0.95f;        // make vertices visible
 +      }
 +      
 +      /* this chunk not in object mode */
 +      if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
 +              if (id != -1)
 +                      glLoadName((GLuint) id|BONESEL_BONE);
 +              
 +              draw_wire_bone_segments(pchan, bbones, length, segments);
 +              
 +              /* further we send no names */
 +              if (id != -1)
 +                      glLoadName(id & 0xFFFF);        /* object tag, for bordersel optim */
 +      }
 +      
 +      /* colors for modes */
 +      if (armflag & ARM_POSEMODE) {
 +              set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
 +      }
 +      else if (armflag & ARM_EDITMODE) {
 +              set_ebone_glColor(boneflag);
 +      }
 +      
 +      /* draw normal */
 +      draw_wire_bone_segments(pchan, bbones, length, segments);
 +}
 +
  static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, float length)
  {
        
@@@ -1658,7 -1577,7 +1658,7 @@@ static void bone_matrix_translate_y(flo
  }
  
  /* assumes object is Armature with pose */
- static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, short ghost)
+ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, const short is_ghost, const short is_outline)
  {
        RegionView3D *rv3d= ar->regiondata;
        Object *ob= base->object;
                                        int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
                                        glPushMatrix();
                                        
 -                                      if(use_custom && pchan->custom_tx) {
 +                                      if (use_custom && pchan->custom_tx) {
                                                glMultMatrixf(pchan->custom_tx->pose_mat);
                                        } 
                                        else {
                                        }
                                        else if (arm->drawtype==ARM_LINE)
                                                ;       /* nothing in solid */
 +                                      else if (arm->drawtype==ARM_WIRE)
 +                                              ;       /* nothing in solid */
                                        else if (arm->drawtype==ARM_ENVELOPE)
                                                draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
                                        else if (arm->drawtype==ARM_B_BONE)
                /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
                 * stick bones and/or wire custom-shapes are drawn in next loop 
                 */
 -              if ((arm->drawtype != ARM_LINE) && (draw_wire == 0)) {
 +              if (ELEM(arm->drawtype,ARM_LINE,ARM_WIRE)==0 && (draw_wire == 0)) {
                        /* object tag, for bordersel optim */
                        glLoadName(index & 0xFFFF);     
                        index= -1;
                                                        }
                                                        
                                                        /* prepare colors */
-                                                       if(ghost) {
+                                                       if(is_ghost) {
                                                                /* 13 October 2009, Disabled this to make ghosting show the right colors (Aligorith) */
                                                        }
                                                        else if (arm->flag & ARM_POSEMODE)      
                        if (index != -1) 
                                index+= 0x10000;        // pose bones count in higher 2 bytes only
                }
 -              /* stick bones have not been drawn yet so dont clear object selection in this case */
 -              if ((arm->drawtype != ARM_LINE) && draw_wire) {
 +              /* stick or wire bones have not been drawn yet so dont clear object selection in this case */
 +              if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)==0 && draw_wire) {
                        /* object tag, for bordersel optim */
                        glLoadName(index & 0xFFFF);     
                        index= -1;
        /* wire draw over solid only in posemode */
        if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || (arm->drawtype==ARM_LINE)) {
                /* draw line check first. we do selection indices */
 -              if (arm->drawtype==ARM_LINE) {
 +              if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) {
                        if (arm->flag & ARM_POSEMODE) 
                                index= base->selcol;
                }
                                        }
                                        else if (arm->drawtype==ARM_LINE)
                                                draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
 +                                      else if (arm->drawtype==ARM_WIRE)
 +                                              draw_wire_bone(dt, arm->flag, flag, constflag, index, pchan, NULL);
                                        else if (arm->drawtype==ARM_B_BONE)
                                                draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
                                        else
                draw_pose_dofs(ob);
  
        /* finally names and axes */
-       if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
+       if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES) && is_outline == 0) {
                /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */
                if ((G.f & G_PICKSEL) == 0) {
                        float vec[3];
@@@ -2098,7 -2013,7 +2098,7 @@@ static void draw_ebones(View3D *v3d, AR
        }
        
        /* if solid we draw it first */
 -      if ((dt > OB_WIRE) && (arm->drawtype!=ARM_LINE)) {
 +      if ((dt > OB_WIRE) && (arm->drawtype != ARM_LINE)) {
                for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) {
                        if (eBone->layer & arm->layer) {
                                if ((eBone->flag & BONE_HIDDEN_A)==0) {
                                                draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
                                        else if(arm->drawtype==ARM_B_BONE)
                                                draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
 +                                      else if (arm->drawtype==ARM_WIRE)
 +                                              draw_wire_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
                                        else {
                                                draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
                                        }
        /* if wire over solid, set offset */
        index= -1;
        glLoadName(-1);
 -      if (arm->drawtype==ARM_LINE) {
 +      if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) {
                if(G.f & G_PICKSEL)
                        index= 0;
        }
                                        
                                        if (arm->drawtype == ARM_LINE) 
                                                draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
 +                                      else if (arm->drawtype==ARM_WIRE)
 +                                              draw_wire_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
                                        else if (arm->drawtype == ARM_B_BONE)
                                                draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
                                        else
        
        /* restore */
        if(index!=-1) glLoadName(-1);
 -      if (arm->drawtype==ARM_LINE);
 +      if ELEM(arm->drawtype,ARM_LINE,ARM_WIRE);
        else if (dt>OB_WIRE) bglPolygonOffset(rv3d->dist, 0.0f);
        
        /* finally names and axes */
@@@ -2348,7 -2259,7 +2348,7 @@@ static void draw_ghost_poses_range(Scen
                
                BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                where_is_pose(scene, ob);
-               draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE);
+               draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
        }
        glDisable(GL_BLEND);
        if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@@ -2427,7 -2338,7 +2427,7 @@@ static void draw_ghost_poses_keys(Scen
                
                BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                where_is_pose(scene, ob);
-               draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE);
+               draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
        }
        glDisable(GL_BLEND);
        if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@@ -2497,7 -2408,7 +2497,7 @@@ static void draw_ghost_poses(Scene *sce
                        if (CFRA != cfrao) {
                                BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                                where_is_pose(scene, ob);
-                               draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE);
+                               draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
                        }
                }
                
                        if (CFRA != cfrao) {
                                BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
                                where_is_pose(scene, ob);
-                               draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE);
+                               draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
                        }
                }
        }
  /* ********************************** Armature Drawing - Main ************************* */
  
  /* called from drawobject.c, return 1 if nothing was drawn */
- int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag)
+ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag, const short is_outline)
  {
        Object *ob= base->object;
        bArmature *arm= ob->data;
                                        }
                                }       
                        }
-                       draw_pose_bones(scene, v3d, ar, base, dt, FALSE);
+                       draw_pose_bones(scene, v3d, ar, base, dt, FALSE, is_outline);
                        arm->flag &= ~ARM_POSEMODE; 
                        
                        if(ob->mode & OB_MODE_POSE)
@@@ -3131,18 -3131,12 +3131,18 @@@ static void createTransActionData(bCont
                float min=999999999.0f, max=-999999999.0f;
                int i;
                
 -              td= (t->data + 1);
 -              for (i=1; i < count; i+=3, td+=3) {
 +              td= t->data;
 +              for (i=0; i < count; i++, td++) {
                        if (min > *(td->val)) min= *(td->val);
                        if (max < *(td->val)) max= *(td->val);
                }
                
 +              if (min == max) {
 +                      /* just use the current frame ranges */
 +                      min = (float)PSFRA;
 +                      max = (float)PEFRA;
 +              }
 +              
                /* minx/maxx values used by TimeSlide are stored as a
                 * calloced 2-float array in t->customData. This gets freed
                 * in postTrans (T_FREE_CUSTOMDATA).
@@@ -3731,27 -3725,8 +3731,8 @@@ void flushTransGraphData(TransInfo *t
   * seq->depth must be set before running this function so we know if the strips
   * are root level or not
   */
- #define XXX_DURIAN_ANIM_TX_HACK
  static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count, int *flag)
  {
-  
- #ifdef XXX_DURIAN_ANIM_TX_HACK
-       /* hack */
-       if((seq->flag & SELECT)==0 && seq->type & SEQ_EFFECT) {
-               Sequence *seq_t[3];
-               int i;
-               seq_t[0]= seq->seq1;
-               seq_t[1]= seq->seq2;
-               seq_t[2]= seq->seq3;
-               for(i=0; i<3; i++) {
-                       if (seq_t[i] && ((seq_t[i])->flag & SELECT) && !(seq_t[i]->flag & SEQ_LOCK) && !(seq_t[i]->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)))
-                               seq->flag |= SELECT;
-               }
-       }
- #endif
        /* for extend we need to do some tricks */
        if (t->mode == TFM_TIME_EXTEND) {
  
@@@ -4111,6 -4086,7 +4092,7 @@@ static void freeSeqData(TransInfo *t
  
  static void createTransSeqData(bContext *C, TransInfo *t)
  {
+ #define XXX_DURIAN_ANIM_TX_HACK
  
        View2D *v2d= UI_view2d_fromcontext(C);
        Scene *scene= t->scene;
                t->frame_side = 'B';
        }
  
+ #ifdef XXX_DURIAN_ANIM_TX_HACK
+       {
+               Sequence *seq;
+               for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+                       /* hack */
+                       if((seq->flag & SELECT)==0 && seq->type & SEQ_EFFECT) {
+                               Sequence *seq_user;
+                               int i;
+                               for(i=0; i<3; i++) {
+                                       seq_user= *((&seq->seq1) + i);
+                                       if (seq_user && (seq_user->flag & SELECT) && !(seq_user->flag & SEQ_LOCK) && !(seq_user->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL))) {
+                                               seq->flag |= SELECT;
+                                       }
+                               }
+                       }
+               }
+       }
+ #endif
  
        count = SeqTransCount(t, ed->seqbasep, 0);
  
  
        /* loop 2: build transdata array */
        SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
+ #undef XXX_DURIAN_ANIM_TX_HACK
  }
  
  
@@@ -5083,10 -5079,6 +5085,6 @@@ void special_aftertrans_update(bContex
  #if 0 // TRANSFORM_FIX_ME
        if(resetslowpar)
                reset_slowparents();
-       /* note; should actually only be done for all objects when a lamp is moved... (ton) */
-       if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
-               reshadeall_displist();
  #endif
  }
  
@@@ -375,7 -375,7 +375,7 @@@ typedef struct UserDef 
        short scrcastwait;              /* milliseconds between screencast snapshots */
        
        short widget_unit;              /* defaults to 20 for 72 DPI setting */
-       short pad[3];                   
+       short anisotropic_filter;
  
        char versemaster[160];
        char verseuser[160];
        short autokey_flag;             /* flags for autokeying */
        
        short text_render, pad9;                /*options for text rendering*/
-       float pad10;
  
        struct ColorBand coba_weight;   /* from texture.h */
  
@@@ -436,7 -435,6 +435,7 @@@ extern UserDef U; /* from blenkernel bl
  #define USER_NONEGFRAMES              (1 << 24)
  #define USER_TXT_TABSTOSPACES_DISABLE (1 << 25)
  #define USER_TOOLTIPS_PYTHON    (1 << 26)
 +#define USER_NO_RECENTLOAD_UPDATE (1 << 27)
  
  /* helper macro for checking frame clamping */
  #define FRAMENUMBER_MIN_CLAMP(cfra) \
@@@ -534,7 -534,6 +534,7 @@@ extern StructRNA RNA_ThemeWidgetColors
  extern StructRNA RNA_ThemeWidgetStateColors;
  extern StructRNA RNA_TimelineMarker;
  extern StructRNA RNA_Timer;
 +extern StructRNA RNA_TitleCardSequence;
  extern StructRNA RNA_ToolSettings;
  extern StructRNA RNA_TouchSensor;
  extern StructRNA RNA_TrackToConstraint;
@@@ -717,6 -716,7 +717,7 @@@ int RNA_property_boolean_get_default_in
  int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop);
  void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value);
  void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values);
+ void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2]);
  int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index);
  void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values);
  void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value);
@@@ -727,6 -727,7 +728,7 @@@ int RNA_property_int_get_default_index(
  float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop);
  void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value);
  void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values);
+ void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2]);
  float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index);
  void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values);
  void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value);
@@@ -1643,6 -1643,43 +1643,43 @@@ void RNA_property_int_get_array(Pointer
                memset(values, 0, sizeof(int)*prop->totarraylength);
  }
  
+ void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
+ {
+       const int array_len= RNA_property_array_length(ptr, prop);
+       if(array_len <= 0) {
+               values[0]= 0;
+               values[1]= 0;
+       }
+       else if (array_len == 1) {
+               RNA_property_int_get_array(ptr, prop, values);
+               values[1]= values[0];
+       }
+       else {
+               int arr_stack[32];
+               int *arr;
+               int i;
+               if(array_len > 32) {
+                       arr= MEM_mallocN(sizeof(int) * array_len, "RNA_property_int_get_array_range");
+               }
+               else {
+                       arr= arr_stack;
+               }
+               RNA_property_int_get_array(ptr, prop, arr);
+               values[0]= values[1]= arr[0];
+               for(i= 1; i < array_len; i++) {
+                       values[0]= MIN2(values[0], arr[i]);
+                       values[1]= MAX2(values[1], arr[i]);
+               }
+               if(arr != arr_stack) {
+                       MEM_freeN(arr);
+               }
+       }
+ }
  int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
  {
        int tmp[RNA_MAX_ARRAY_LENGTH];
@@@ -1839,6 -1876,43 +1876,43 @@@ void RNA_property_float_get_array(Point
                memset(values, 0, sizeof(float)*prop->totarraylength);
  }
  
+ void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
+ {
+       const int array_len= RNA_property_array_length(ptr, prop);
+       if(array_len <= 0) {
+               values[0]= 0.0f;
+               values[1]= 0.0f;
+       }
+       else if (array_len == 1) {
+               RNA_property_float_get_array(ptr, prop, values);
+               values[1]= values[0];
+       }
+       else {
+               float arr_stack[32];
+               float *arr;
+               int i;
+               if(array_len > 32) {
+                       arr= MEM_mallocN(sizeof(float) * array_len, "RNA_property_float_get_array_range");
+               }
+               else {
+                       arr= arr_stack;
+               }
+               RNA_property_float_get_array(ptr, prop, arr);
+               values[0]= values[1]= arr[0];
+               for(i= 1; i < array_len; i++) {
+                       values[0]= MIN2(values[0], arr[i]);
+                       values[1]= MAX2(values[1], arr[i]);
+               }
+               if(arr != arr_stack) {
+                       MEM_freeN(arr);
+               }
+       }
+ }
  float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
  {
        float tmp[RNA_MAX_ARRAY_LENGTH];
@@@ -3114,7 -3188,7 +3188,7 @@@ static char *rna_path_token(const char 
                /* 2 kinds of lookups now, quoted or unquoted */
                quote= *p;
  
 -              if(quote != '"')
 +              if(quote != '"') /* " - this comment is hack for Aligorith's text editor's sanity */
                        quote= 0;
  
                if(quote==0) {
@@@ -117,6 -117,12 +117,12 @@@ static void rna_userdef_mipmap_update(M
        rna_userdef_update(bmain, scene, ptr);
  }
  
+ static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+ {
+       GPU_set_anisotropic(U.anisotropic_filter);
+       rna_userdef_update(bmain, scene, ptr);
+ }
  static void rna_userdef_gl_texture_limit_update(Main *bmain, Scene *scene, PointerRNA *ptr)
  {
        GPU_free_images();
@@@ -2109,19 -2115,22 +2115,22 @@@ static void rna_def_userdef_view(Blende
        prop= RNA_def_property(srna, "manipulator_size", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "tw_size");
        RNA_def_property_range(prop, 2, 40);
+       RNA_def_property_int_default(prop, 15);
        RNA_def_property_ui_text(prop, "Manipulator Size", "Diameter of widget, in 10 pixel units");
        RNA_def_property_update(prop, 0, "rna_userdef_update");
  
        prop= RNA_def_property(srna, "manipulator_handle_size", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "tw_handlesize");
        RNA_def_property_range(prop, 2, 40);
+       RNA_def_property_int_default(prop, 25);
        RNA_def_property_ui_text(prop, "Manipulator Handle Size", "Size of widget handles as percentage of widget radius");
        RNA_def_property_update(prop, 0, "rna_userdef_update");
  
        prop= RNA_def_property(srna, "manipulator_hotspot", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "tw_hotspot");
        RNA_def_property_range(prop, 4, 40);
-       RNA_def_property_ui_text(prop, "Manipulator Hotspot", "Hotspot in pixels for clicking widget handles");
+       RNA_def_property_int_default(prop, 14);
+       RNA_def_property_ui_text(prop, "Manipulator Hotspot", "Pixel distance around the handles to accept mouse clicks");
  
        prop= RNA_def_property(srna, "object_origin_size", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "obcenter_dia");
@@@ -2346,6 -2355,14 +2355,14 @@@ static void rna_def_userdef_system(Blen
                {128, "CLAMP_128", 0, "128", ""},
                {0, NULL, 0, NULL, NULL}};
  
+       static EnumPropertyItem anisotropic_items[]  ={
+               {1, "FILTER_0", 0, "Off", ""},
+               {2, "FILTER_2", 0, "2x", ""},
+               {4, "FILTER_4", 0, "4x", ""},
+               {8, "FILTER_8", 0, "8x", ""},
+               {16, "FILTER_16", 0, "16x", ""},
+               {0, NULL, 0, NULL, NULL}};
        static EnumPropertyItem audio_mixing_samples_items[] = {
                {256, "SAMPLES_256", 0, "256", "Set audio mixing buffer size to 256 samples"},
                {512, "SAMPLES_512", 0, "512", "Set audio mixing buffer size to 512 samples"},
        prop= RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_AA);
        RNA_def_property_ui_text(prop, "Anti-aliasing", "Use anti-aliasing for the 3D view (may impact redraw performance)");
+       prop= RNA_def_property(srna, "anisotropic_filter", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter");
+       RNA_def_property_enum_items(prop, anisotropic_items);
+       RNA_def_property_enum_default(prop, 1);
+       RNA_def_property_ui_text(prop, "Anisotropic Filter", "The quality of the anisotropic filtering (values greater than 1.0 enable anisotropic filtering)");
+       RNA_def_property_update(prop, 0, "rna_userdef_anisotropic_update");
        
        prop= RNA_def_property(srna, "gl_texture_limit", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "glreslimit");
@@@ -2878,11 -2902,7 +2902,11 @@@ static void rna_def_userdef_filepaths(B
        prop= RNA_def_property(srna, "recent_files", PROP_INT, PROP_NONE);
        RNA_def_property_range(prop, 0, 30);
        RNA_def_property_ui_text(prop, "Recent Files", "Maximum number of recently opened files to remember");
 -
 +      
 +      prop= RNA_def_property(srna, "use_update_recent_files_on_load", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_NO_RECENTLOAD_UPDATE);
 +      RNA_def_property_ui_text(prop, "Update Recent on Load", "When enabled, opening files will update the recent files list. Otherwise, updates only occur when saving");
 +      
        prop= RNA_def_property(srna, "use_save_preview_images", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SAVE_PREVIEWS);
        RNA_def_property_ui_text(prop, "Save Preview Images", "Enables automatic saving of preview images in the .blend file");
@@@ -36,7 -36,6 +36,7 @@@
  #include "BL_ActionActuator.h"
  #include "BL_ArmatureObject.h"
  #include "BL_SkinDeformer.h"
 +#include "BL_Action.h"
  #include "KX_GameObject.h"
  #include "STR_HashedString.h"
  #include "MEM_guardedalloc.h"
@@@ -144,90 -143,7 +144,90 @@@ void BL_ActionActuator::SetLocalTime(fl
                m_localtime = m_endframe - delta_time;
  }
  
 +bool BL_ActionActuator::Update(double curtime, bool frame)
 +{
 +      bool bNegativeEvent = false;
 +      bool bPositiveEvent = false;
 +      KX_GameObject *obj = (KX_GameObject*)GetParent();
 +      short play_mode = BL_Action::ACT_MODE_PLAY;
 +      float start = m_startframe, end = m_endframe;
 +
 +      // If we don't have an action, we can't do anything
 +      if (!m_action)
 +              return false;
 +
 +      // Don't do anything if we're not "active"
 +      if (!frame)
 +              return true;
 +      
 +      // Convert playmode
 +      if (m_playtype == ACT_ACTION_LOOP_END)
 +              play_mode = BL_Action::ACT_MODE_LOOP;
 +      else if (m_playtype == ACT_ACTION_LOOP_STOP)
 +              play_mode = BL_Action::ACT_MODE_LOOP;
 +      else if (m_playtype == ACT_ACTION_PINGPONG)
 +              play_mode = BL_Action::ACT_MODE_PING_PONG;
 +      else if (m_playtype == ACT_ACTION_FROM_PROP)
 +      {
 +              CValue* prop = GetParent()->GetProperty(m_propname);
 +
 +              play_mode = BL_Action::ACT_MODE_PLAY;
 +              start = end = prop->GetNumber();
 +              m_is_going = false;
 +      }
 +
 +      // Handle events
 +      bNegativeEvent = m_negevent;
 +      bPositiveEvent = m_posevent;
 +      RemoveAllEvents();
 +
 +      if (!m_is_going && bPositiveEvent)
 +      {               
 +              m_is_going = true;
 +              obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_blendin, play_mode, 0, m_ipo_flags);
 +              if (m_end_reset)
 +                      obj->SetActionFrame(m_layer, m_localtime);
 +      }
 +      else if (m_is_going && bNegativeEvent)
 +      {
 +              m_is_going = false;
 +              
 +              if (!m_end_reset)
 +              {
 +                      obj->StopAction(m_layer);
 +                      return false;
 +              }
 +
 +              m_localtime = obj->GetActionFrame(m_layer);
 +              obj->StopAction(m_layer); // Stop the action after getting the frame
 +      }
 +
 +      // Handle a frame property if it's defined
 +      if (m_framepropname[0] != 0)
 +      {
 +              CValue* oldprop = obj->GetProperty(m_framepropname);
 +              CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer));
 +              if (oldprop)
 +                      oldprop->SetValue(newval);
 +              else
 +                      obj->SetProperty(m_framepropname, newval);
 +
 +              newval->Release();
 +      }
 +      if (m_playtype == ACT_ACTION_FROM_PROP)
 +      {
 +              return true;
 +      }
 +      // Handle a finished animation
 +      else if (m_is_going && obj->IsActionDone(m_layer))
 +      {
 +              return false;
 +      }
 +
 +      return true;
 +}
  
 +#if 0 // Kept around as reference for now
  bool BL_ActionActuator::Update(double curtime, bool frame)
  {
        bool bNegativeEvent = false;
                        
  // 2.5x - could also do this but looks too high level, constraints use this, it works ok.
  //                            Object workob; /* evaluate using workob */
- //                            what_does_obaction((Scene *)obj->GetScene(), obj->GetArmatureObject(), &workob, m_pose, m_action, NULL, m_localtime);
+ //                            what_does_obaction(obj->GetArmatureObject(), &workob, m_pose, m_action, NULL, m_localtime);
                        }
  
                        // done getting the pose from the action
        }
        return keepgoing;
  };
 +#endif
  
  #ifdef WITH_PYTHON