Merge from trunk -r 25003:25745.
authorArystanbek Dyussenov <arystan.d@gmail.com>
Tue, 5 Jan 2010 19:21:59 +0000 (19:21 +0000)
committerArystanbek Dyussenov <arystan.d@gmail.com>
Tue, 5 Jan 2010 19:21:59 +0000 (19:21 +0000)
1  2 
CMakeLists.txt
config/linux2-config.py
config/win32-vc-config.py
config/win64-vc-config.py
source/blender/collada/DocumentExporter.cpp
source/blender/collada/DocumentImporter.cpp
source/blender/windowmanager/intern/wm_operators.c

diff --combined CMakeLists.txt
@@@ -79,7 -79,7 +79,7 @@@ OPTION(WITH_LZMA          "Enable best 
  OPTION(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation" OFF)
  OPTION(WITH_BUILDINFO     "Include extra build details" ON)
  OPTION(WITH_INSTALL       "Install accompanying scripts and language files needed to run blender" ON)
 -OPTION(WITH_OPENCOLLADA               "Enable OpenCollada Support (http://www.opencollada.org/)"      OFF)
 +OPTION(WITH_OPENCOLLADA               "Enable OpenCollada Support (http://www.opencollada.org/)"      ON)
  
  # Unix defaults to OpenMP On
  IF (UNIX)
@@@ -437,7 -437,7 +437,7 @@@ IF(APPLE
                IF(CMAKE_OSX_ARCHITECTURES MATCHES i386)
                        SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-8.x.i386)
                ELSE(CMAKE_OSX_ARCHITECTURES MATCHES i386)
-                       SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-6.1-powerpc)
+                       SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-8.0.0-powerpc)
                ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES i386)
        ENDIF(WITH_LIBS10.5)
        
diff --combined config/linux2-config.py
@@@ -151,7 -151,7 +151,7 @@@ BF_OPENGL_LIB = 'GL GLU X11 Xi
  BF_OPENGL_LIBPATH = '/usr/X11R6/lib'
  BF_OPENGL_LIB_STATIC = '${BF_OPENGL_LIBPATH}/libGL.a ${BF_OPENGL_LIBPATH}/libGLU.a ${BF_OPENGL_LIBPATH}/libXxf86vm.a ${BF_OPENGL_LIBPATH}/libX11.a ${BF_OPENGL_LIBPATH}/libXi.a ${BF_OPENGL_LIBPATH}/libXext.a ${BF_OPENGL_LIBPATH}/libXxf86vm.a'
  
 -WITH_BF_COLLADA = False
 +WITH_BF_COLLADA = True
  BF_COLLADA = '#source/blender/collada'
  BF_COLLADA_INC = '${BF_COLLADA}'
  BF_COLLADA_LIB = 'bf_collada'
@@@ -167,6 -167,10 +167,10 @@@ BF_EXPAT_LIBPATH = '/usr/lib
  
  WITH_BF_OPENMP = True
  
+ #Ray trace optimization
+ WITH_BF_RAYOPTIMIZATION = False
+ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
  ##
  CC = 'gcc'
  CXX = 'g++'
@@@ -138,7 -138,7 +138,7 @@@ BF_FFTW3_LIBPATH = '${BF_FFTW3}/lib
  WITH_BF_REDCODE = False  
  BF_REDCODE_INC = '#extern'
  
 -WITH_BF_COLLADA = False
 +WITH_BF_COLLADA = True
  BF_COLLADA = '#source/blender/collada'
  BF_COLLADA_INC = '${BF_COLLADA}'
  BF_COLLADA_LIB = 'bf_collada'
@@@ -148,6 -148,10 +148,10 @@@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}
  BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver xml2 pcre'
  BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
  
+ #Ray trace optimization
+ WITH_BF_RAYOPTIMIZATION = False
+ BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE']
  WITH_BF_STATICOPENGL = False
  BF_OPENGL_INC = '${BF_OPENGL}/include'
  BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
@@@ -155,6 -159,7 +159,7 @@@ BF_OPENGL_LIB = 'opengl32 glu32
  BF_OPENGL_LIB_STATIC = [ '${BF_OPENGL}/lib/libGL.a', '${BF_OPENGL}/lib/libGLU.a',
                           '${BF_OPENGL}/lib/libXmu.a', '${BF_OPENGL}/lib/libXext.a',
                           '${BF_OPENGL}/lib/libX11.a', '${BF_OPENGL}/lib/libXi.a' ]
+                          
  CC = 'cl.exe'
  CXX = 'cl.exe'
  
@@@ -151,7 -151,7 +151,7 @@@ BF_FFTW3_LIBPATH = '${BF_FFTW3}/lib
  WITH_BF_REDCODE = False  
  BF_REDCODE_INC = '#extern'
  
 -WITH_BF_COLLADA = False
 +WITH_BF_COLLADA = True
  BF_COLLADA = '#source/blender/collada'
  BF_COLLADA_INC = '${BF_COLLADA}'
  BF_COLLADA_LIB = 'bf_collada'
@@@ -161,6 -161,10 +161,10 @@@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}
  BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver xml2 pcre'
  BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
  
+ #Ray trace optimization
+ WITH_BF_RAYOPTIMIZATION = False
+ BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE','/arch:SSE2']
  WITH_BF_STATICOPENGL = False
  BF_OPENGL_INC = '${BF_OPENGL}/include'
  BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
@@@ -21,8 -21,7 +21,8 @@@ extern "C
  {
  #include "BKE_DerivedMesh.h"
  #include "BKE_fcurve.h"
- #include "BLI_util.h"
 +#include "BKE_animsys.h"
+ #include "BLI_path_util.h"
  #include "BLI_fileops.h"
  #include "ED_keyframing.h"
  }
@@@ -37,7 -36,6 +37,7 @@@
  #include "BKE_armature.h"
  #include "BKE_image.h"
  #include "BKE_utildefines.h"
 +#include "BKE_object.h"
  
  #include "BLI_math.h"
  #include "BLI_string.h"
@@@ -200,12 -198,6 +200,12 @@@ static std::string get_camera_id(Objec
        return translate_id(id_name(ob)) + "-camera";
  }
  
 +std::string get_joint_id(Bone *bone, Object *ob_arm)
 +{
 +      return translate_id(id_name(ob_arm) + "_" + bone->name);
 +}
 +
 +
  /*
    Utilities to avoid code duplication.
    Definition can take some time to understand, but they should be useful.
@@@ -859,6 -851,11 +859,6 @@@ private
                return ob_arm;
        }
  
 -      std::string get_joint_id(Bone *bone, Object *ob_arm)
 -      {
 -              return translate_id(id_name(ob_arm) + "_" + bone->name);
 -      }
 -
        std::string get_joint_sid(Bone *bone)
        {
                char name[100];
@@@ -1541,23 -1538,9 +1541,23 @@@ public
                        if (t->mapto & MAP_REF) {
                                ep.setReflective(createTexture(ima, uvname, sampler));
                        }
 +                      // alpha
                        if (t->mapto & MAP_ALPHA) {
                                ep.setTransparent(createTexture(ima, uvname, sampler));
                        }
 +                      // extension:
 +                      // Normal map --> Must be stored with <extra> tag as different technique, 
 +                      // since COLLADA doesn't support normal maps, even in current COLLADA 1.5.
 +                      if (t->mapto & MAP_NORM) {
 +                              COLLADASW::Texture texture(key);
 +                              texture.setTexcoord(uvname);
 +                              texture.setSampler(*sampler);
 +                              // technique FCOLLADA, with the <bump> tag, is most likely the best understood,
 +                              // most widespread de-facto standard.
 +                              texture.setProfileName("FCOLLADA");
 +                              texture.setChildElementName("bump");                            
 +                              ep.setExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture));
 +                      }
                }
                // performs the actual writing
                ep.addProfileElements();
@@@ -1737,9 -1720,9 +1737,9 @@@ public
  class AnimationExporter: COLLADASW::LibraryAnimations
  {
        Scene *scene;
 -      std::map<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map;
 -      std::map<bActionGroup*, std::vector<FCurve*> > rotfcurves_actionGroup_map;
 +
  public:
 +
        AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) {}
  
        void exportAnimations(Scene *sce)
                closeLibrary();
        }
  
 -      // create <animation> for each transform axis
 +      // called for each exported object
 +      void operator() (Object *ob) 
 +      {
 +              if (!ob->adt || !ob->adt->action) return;
 +              
 +              FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
 +              
 +              if (ob->type == OB_ARMATURE) {
 +                      if (!ob->data) return;
 +
 +                      bArmature *arm = (bArmature*)ob->data;
 +                      for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next)
 +                              write_bone_animation(ob, bone);
 +              }
 +              else {
 +                      while (fcu) {
 +                              // TODO "rotation_quaternion" is also possible for objects (although euler is default)
 +                              if ((!strcmp(fcu->rna_path, "location") || !strcmp(fcu->rna_path, "scale")) ||
 +                                      (!strcmp(fcu->rna_path, "rotation_euler") && ob->rotmode == ROT_MODE_EUL))
 +                                      dae_animation(fcu, id_name(ob));
 +
 +                              fcu = fcu->next;
 +                      }
 +              }
 +      }
 +
 +protected:
 +
 +      void dae_animation(FCurve *fcu, std::string ob_name)
 +      {
 +              const char *axis_names[] = {"X", "Y", "Z"};
 +              const char *axis_name = NULL;
 +              char anim_id[200];
 +              char anim_name[200];
 +              
 +              if (fcu->array_index < 3)
 +                      axis_name = axis_names[fcu->array_index];
 +
 +              BLI_snprintf(anim_id, sizeof(anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(),
 +                                       fcu->rna_path, axis_names[fcu->array_index]);
 +              BLI_snprintf(anim_name, sizeof(anim_name), "%s.%s.%s", 
 +                                       (char*)ob_name.c_str(), fcu->rna_path, axis_names[fcu->array_index]);
 +
 +              // check rna_path is one of: rotation, scale, location
 +
 +              openAnimation(anim_id, anim_name);
 +
 +              // create input source
 +              std::string input_id = create_source_from_fcurve(Sampler::INPUT, fcu, anim_id, axis_name);
 +
 +              // create output source
 +              std::string output_id = create_source_from_fcurve(Sampler::OUTPUT, fcu, anim_id, axis_name);
 +
 +              // create interpolations source
 +              std::string interpolation_id = create_interpolation_source(fcu->totvert, anim_id, axis_name);
 +
 +              std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
 +              COLLADASW::LibraryAnimations::Sampler sampler(sampler_id);
 +              std::string empty;
 +              sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id));
 +              sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id));
 +
 +              // this input is required
 +              sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
 +
 +              addSampler(sampler);
 +
 +              std::string target = translate_id(ob_name)
 +                      + "/" + get_transform_sid(fcu->rna_path, -1, axis_name);
 +              addChannel(COLLADABU::URI(empty, sampler_id), target);
 +
 +              closeAnimation();
 +      }
 +
 +      void write_bone_animation(Object *ob_arm, Bone *bone)
 +      {
 +              if (!ob_arm->adt)
 +                      return;
 +
 +              for (int i = 0; i < 3; i++)
 +                      sample_and_write_bone_animation(ob_arm, bone, i);
 +
 +              for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next)
 +                      write_bone_animation(ob_arm, child);
 +      }
 +
 +      void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
 +      {
 +              bArmature *arm = (bArmature*)ob_arm->data;
 +              int flag = arm->flag;
 +              std::vector<float> fra;
 +              char prefix[256];
 +
 +              BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
 +
 +              bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
 +              if (!pchan)
 +                      return;
 +
 +              switch (transform_type) {
 +              case 0:
 +                      find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
 +                      break;
 +              case 1:
 +                      find_frames(ob_arm, fra, prefix, "scale");
 +                      break;
 +              case 2:
 +                      find_frames(ob_arm, fra, prefix, "location");
 +                      break;
 +              default:
 +                      return;
 +              }
  
 -      float convert_time(float frame) {
 +              // exit rest position
 +              if (flag & ARM_RESTPOS) {
 +                      arm->flag &= ~ARM_RESTPOS;
 +                      where_is_pose(scene, ob_arm);
 +              }
 +
 +              if (fra.size()) {
 +                      float *v = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
 +                      sample_animation(v, fra, transform_type, bone, ob_arm);
 +
 +                      if (transform_type == 0) {
 +                              // write x, y, z curves separately if it is rotation
 +                              float *c = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
 +                              for (int i = 0; i < 3; i++) {
 +                                      for (int j = 0; j < fra.size(); j++)
 +                                              c[j] = v[j * 3 + i];
 +
 +                                      dae_bone_animation(fra, c, transform_type, i, id_name(ob_arm), bone->name);
 +                              }
 +                              MEM_freeN(c);
 +                      }
 +                      else {
 +                              // write xyz at once if it is location or scale
 +                              dae_bone_animation(fra, v, transform_type, -1, id_name(ob_arm), bone->name);
 +                      }
 +
 +                      MEM_freeN(v);
 +              }
 +
 +              // restore restpos
 +              if (flag & ARM_RESTPOS) 
 +                      arm->flag = flag;
 +              where_is_pose(scene, ob_arm);
 +      }
 +
 +      void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm)
 +      {
 +              bPoseChannel *pchan, *parchan = NULL;
 +              bPose *pose = ob_arm->pose;
 +
 +              pchan = get_pose_channel(pose, bone->name);
 +
 +              if (!pchan)
 +                      return;
 +
 +              parchan = pchan->parent;
 +
 +              enable_fcurves(ob_arm->adt->action, bone->name);
 +
 +              std::vector<float>::iterator it;
 +              for (it = frames.begin(); it != frames.end(); it++) {
 +                      float mat[4][4], ipar[4][4];
 +
 +                      float ctime = bsystem_time(scene, ob_arm, *it, 0.0f);
 +
 +                      BKE_animsys_evaluate_animdata(&ob_arm->id, ob_arm->adt, *it, ADT_RECALC_ANIM);
 +                      where_is_pose_bone(scene, ob_arm, pchan, ctime);
 +
 +                      // compute bone local mat
 +                      if (bone->parent) {
 +                              invert_m4_m4(ipar, parchan->pose_mat);
 +                              mul_m4_m4m4(mat, pchan->pose_mat, ipar);
 +                      }
 +                      else
 +                              copy_m4_m4(mat, pchan->pose_mat);
 +
 +                      switch (type) {
 +                      case 0:
 +                              mat4_to_eul(v, mat);
 +                              break;
 +                      case 1:
 +                              mat4_to_size(v, mat);
 +                              break;
 +                      case 2:
 +                              copy_v3_v3(v, mat[3]);
 +                              break;
 +                      }
 +
 +                      v += 3;
 +              }
 +
 +              enable_fcurves(ob_arm->adt->action, NULL);
 +      }
 +
 +      // dae_bone_animation -> add_bone_animation
 +      // (blend this into dae_bone_animation)
 +      void dae_bone_animation(std::vector<float> &fra, float *v, int tm_type, int axis, std::string ob_name, std::string bone_name)
 +      {
 +              const char *axis_names[] = {"X", "Y", "Z"};
 +              const char *axis_name = NULL;
 +              char anim_id[200];
 +              char anim_name[200];
 +              bool is_rot = tm_type == 0;
 +              
 +              if (!fra.size())
 +                      return;
 +
 +              char rna_path[200];
 +              BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
 +                                       tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
 +
 +              if (axis > -1)
 +                      axis_name = axis_names[axis];
 +              
 +              std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name);
 +              
 +              BLI_snprintf(anim_id, sizeof(anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(),
 +                                       (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str());
 +              BLI_snprintf(anim_name, sizeof(anim_name), "%s.%s.%s",
 +                                       (char*)ob_name.c_str(), (char*)bone_name.c_str(), (char*)transform_sid.c_str());
 +
 +              // TODO check rna_path is one of: rotation, scale, location
 +
 +              openAnimation(anim_id, anim_name);
 +
 +              // create input source
 +              std::string input_id = create_source_from_vector(Sampler::INPUT, fra, is_rot, anim_id, axis_name);
 +
 +              // create output source
 +              std::string output_id;
 +              if (axis == -1)
 +                      output_id = create_xyz_source(v, fra.size(), anim_id);
 +              else
 +                      output_id = create_source_from_array(Sampler::OUTPUT, v, fra.size(), is_rot, anim_id, axis_name);
 +
 +              // create interpolations source
 +              std::string interpolation_id = create_interpolation_source(fra.size(), anim_id, axis_name);
 +
 +              std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
 +              COLLADASW::LibraryAnimations::Sampler sampler(sampler_id);
 +              std::string empty;
 +              sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id));
 +              sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id));
 +
 +              // TODO create in/out tangents source
 +
 +              // this input is required
 +              sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
 +
 +              addSampler(sampler);
 +
 +              std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
 +              addChannel(COLLADABU::URI(empty, sampler_id), target);
 +
 +              closeAnimation();
 +      }
 +
 +      float convert_time(float frame)
 +      {
                return FRA2TIME(frame);
        }
  
 -      float convert_angle(float angle) {
 +      float convert_angle(float angle)
 +      {
                return COLLADABU::Math::Utils::radToDegF(angle);
        }
  
 -      std::string get_semantic_suffix(Sampler::Semantic semantic) {
 +      std::string get_semantic_suffix(Sampler::Semantic semantic)
 +      {
                switch(semantic) {
                case Sampler::INPUT:
                        return INPUT_SOURCE_ID_SUFFIX;
        }
  
        void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
 -                                                         Sampler::Semantic semantic, bool rotation, const char *axis) {
 +                                                         Sampler::Semantic semantic, bool is_rot, const char *axis)
 +      {
                switch(semantic) {
                case Sampler::INPUT:
                        param.push_back("TIME");
                        break;
                case Sampler::OUTPUT:
 -                      if (rotation) {
 +                      if (is_rot) {
                                param.push_back("ANGLE");
                        }
                        else {
 -                              param.push_back(axis);
 +                              if (axis) {
 +                                      param.push_back(axis);
 +                              }
 +                              else {
 +                                      param.push_back("X");
 +                                      param.push_back("Y");
 +                                      param.push_back("Z");
 +                              }
                        }
                        break;
                case Sampler::IN_TANGENT:
                }
        }
  
 -      std::string create_source(Sampler::Semantic semantic, FCurve *fcu, std::string& anim_id, const char *axis_name)
 +      std::string create_source_from_fcurve(Sampler::Semantic semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
        {
                std::string source_id = anim_id + get_semantic_suffix(semantic);
  
                return source_id;
        }
  
 -      std::string create_interpolation_source(FCurve *fcu, std::string& anim_id, const char *axis_name)
 +      std::string create_source_from_array(Sampler::Semantic semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
        {
 -              std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION);
 -
 -              //bool is_rotation = !strcmp(fcu->rna_path, "rotation");
 +              std::string source_id = anim_id + get_semantic_suffix(semantic);
  
 -              COLLADASW::NameSource source(mSW);
 +              COLLADASW::FloatSourceF source(mSW);
                source.setId(source_id);
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
 -              source.setAccessorCount(fcu->totvert);
 +              source.setAccessorCount(tot);
                source.setAccessorStride(1);
                
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
 -              param.push_back("INTERPOLATION");
 +              add_source_parameters(param, semantic, is_rot, axis_name);
  
                source.prepareToAppendValues();
  
 -              for (int i = 0; i < fcu->totvert; i++) {
 -                      // XXX
 -                      source.appendValues(LINEAR_NAME);
 +              for (int i = 0; i < tot; i++) {
 +                      float val = v[i];
 +                      if (semantic == Sampler::INPUT)
 +                              val = convert_time(val);
 +                      else if (is_rot)
 +                              val = convert_angle(val);
 +                      source.appendValues(val);
                }
  
                source.finish();
                return source_id;
        }
  
 -      std::string get_transform_sid(char *rna_path, const char *axis_name)
 +      std::string create_source_from_vector(Sampler::Semantic semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name)
        {
 -              // if (!strcmp(rna_path, "rotation"))
 -//                    return std::string(rna_path) + axis_name;
 -
 -//            return std::string(rna_path) + "." + axis_name;
 -              std::string new_rna_path;
 -              
 -              if (strstr(rna_path, "rotation")) {
 -                      new_rna_path = "rotation";
 -                      return new_rna_path + axis_name;
 -              }
 -              else if (strstr(rna_path, "location")) {
 -                      new_rna_path = strstr(rna_path, "location");
 -                      return new_rna_path + "." + axis_name;
 -              }
 -              else if (strstr(rna_path, "scale")) {
 -                      new_rna_path = strstr(rna_path, "scale");
 -                      return new_rna_path + "." + axis_name;
 -              }
 -              return NULL;
 -      }
 +              std::string source_id = anim_id + get_semantic_suffix(semantic);
  
 -      void add_animation(FCurve *fcu, std::string ob_name)
 -      {
 -              const char *axis_names[] = {"X", "Y", "Z"};
 -              const char *axis_name = NULL;
 -              char c_anim_id[100]; // careful!
 -              char c_anim_name[100]; // careful!
 +              COLLADASW::FloatSourceF source(mSW);
 +              source.setId(source_id);
 +              source.setArrayId(source_id + ARRAY_ID_SUFFIX);
 +              source.setAccessorCount(fra.size());
 +              source.setAccessorStride(1);
                
 -              if (fcu->array_index < 3)
 -                      axis_name = axis_names[fcu->array_index];
 -
 -              BLI_snprintf(c_anim_id, sizeof(c_anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(),
 -                      fcu->rna_path, axis_names[fcu->array_index]);
 -              std::string anim_id(c_anim_id);
 -              BLI_snprintf(c_anim_name, sizeof(c_anim_name), "%s.%s.%s", 
 -                      (char*)ob_name.c_str(), fcu->rna_path, axis_names[fcu->array_index]);
 -              std::string anim_name = c_anim_name;
 +              COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
 +              add_source_parameters(param, semantic, is_rot, axis_name);
  
 -              // check rna_path is one of: rotation, scale, location
 +              source.prepareToAppendValues();
  
 -              openAnimation(anim_id, anim_name);
 +              std::vector<float>::iterator it;
 +              for (it = fra.begin(); it != fra.end(); it++) {
 +                      float val = *it;
 +                      if (semantic == Sampler::INPUT)
 +                              val = convert_time(val);
 +                      else if (is_rot)
 +                              val = convert_angle(val);
 +                      source.appendValues(val);
 +              }
  
 -              // create input source
 -              std::string input_id = create_source(Sampler::INPUT, fcu, anim_id, axis_name);
 +              source.finish();
  
 -              // create output source
 -              std::string output_id = create_source(Sampler::OUTPUT, fcu, anim_id, axis_name);
 +              return source_id;
 +      }
  
 -              // create interpolations source
 -              std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name);
 +      // only used for sources with OUTPUT semantic
 +      std::string create_xyz_source(float *v, int tot, const std::string& anim_id)
 +      {
 +              Sampler::Semantic semantic = Sampler::OUTPUT;
 +              std::string source_id = anim_id + get_semantic_suffix(semantic);
  
 -              std::string sampler_id = anim_id + SAMPLER_ID_SUFFIX;
 -              COLLADASW::LibraryAnimations::Sampler sampler(sampler_id);
 -              std::string empty;
 -              sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id));
 -              sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id));
 +              COLLADASW::FloatSourceF source(mSW);
 +              source.setId(source_id);
 +              source.setArrayId(source_id + ARRAY_ID_SUFFIX);
 +              source.setAccessorCount(tot);
 +              source.setAccessorStride(3);
 +              
 +              COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
 +              add_source_parameters(param, semantic, false, NULL);
  
 -              // this input is required
 -              sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
 +              source.prepareToAppendValues();
  
 -              addSampler(sampler);
 +              for (int i = 0; i < tot; i++) {
 +                      source.appendValues(*v, *(v + 1), *(v + 2));
 +                      v += 3;
 +              }
  
 -              std::string target = translate_id(ob_name)
 -                      + "/" + get_transform_sid(fcu->rna_path, axis_name);
 -              addChannel(COLLADABU::URI(empty, sampler_id), target);
 +              source.finish();
  
 -              closeAnimation();
 +              return source_id;
        }
 -      
 -      void add_bone_animation(FCurve *fcu, std::string ob_name, std::string bone_name)
 +
 +      std::string create_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
        {
 -              const char *axis_names[] = {"X", "Y", "Z"};
 -              const char *axis_name = NULL;
 -              char c_anim_id[100]; // careful!
 -              char c_anim_name[100]; // careful!
 +              std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION);
  
 -              if (fcu->array_index < 3)
 -                      axis_name = axis_names[fcu->array_index];
 -              
 -              std::string transform_sid = get_transform_sid(fcu->rna_path, axis_name);
 +              COLLADASW::NameSource source(mSW);
 +              source.setId(source_id);
 +              source.setArrayId(source_id + ARRAY_ID_SUFFIX);
 +              source.setAccessorCount(tot);
 +              source.setAccessorStride(1);
                
 -              BLI_snprintf(c_anim_id, sizeof(c_anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(),
 -                      (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str());
 -              std::string anim_id(c_anim_id);
 -              BLI_snprintf(c_anim_name, sizeof(c_anim_name), "%s.%s.%s",
 -                      (char*)ob_name.c_str(), (char*)bone_name.c_str(), (char*)transform_sid.c_str());
 -              std::string anim_name(c_anim_name);
 -
 -              // check rna_path is one of: rotation, scale, location
 -
 -              openAnimation(anim_id, anim_name);
 -
 -              // create input source
 -              std::string input_id = create_source(Sampler::INPUT, fcu, anim_id, axis_name);
 +              COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
 +              param.push_back("INTERPOLATION");
  
 -              // create output source
 -              std::string output_id = create_source(Sampler::OUTPUT, fcu, anim_id, axis_name);
 +              source.prepareToAppendValues();
  
 -              // create interpolations source
 -              std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name);
 +              for (int i = 0; i < tot; i++) {
 +                      source.appendValues(LINEAR_NAME);
 +              }
  
 -              std::string sampler_id = anim_id + SAMPLER_ID_SUFFIX;
 -              COLLADASW::LibraryAnimations::Sampler sampler(sampler_id);
 -              std::string empty;
 -              sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id));
 -              sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id));
 +              source.finish();
  
 -              // this input is required
 -              sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
 +              return source_id;
 +      }
  
 -              addSampler(sampler);
 +      std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name)
 +      {
 +              if (rna_path) {
 +                      char *name = extract_transform_name(rna_path);
  
 -              std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
 -              addChannel(COLLADABU::URI(empty, sampler_id), target);
 +                      if (strstr(name, "rotation"))
 +                              return std::string("rotation") + axis_name;
 +                      else if (!strcmp(name, "location") || !strcmp(name, "scale"))
 +                              return std::string(name);
 +              }
 +              else {
 +                      if (tm_type == 0)
 +                              return std::string("rotation") + axis_name;
 +                      else
 +                              return tm_type == 1 ? "scale" : "location";
 +              }
  
 -              closeAnimation();
 +              return NULL;
        }
 -      
 -      FCurve *create_fcurve(int array_index, char *rna_path)
 +
 +      char *extract_transform_name(char *rna_path)
        {
 -              FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
 -              
 -              fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
 -              fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
 -              fcu->array_index = array_index;
 -              return fcu;
 -      }
 -      
 -      void create_bezt(FCurve *fcu, float frame, float output)
 -      {
 -              BezTriple bez;
 -              memset(&bez, 0, sizeof(BezTriple));
 -              bez.vec[1][0] = frame;
 -              bez.vec[1][1] = output;
 -              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);
 -              calchandles_fcurve(fcu);
 +              char *dot = strrchr(rna_path, '.');
 +              return dot ? (dot + 1) : rna_path;
        }
 -      
 -      void change_quat_to_eul(Object *ob, bActionGroup *grp, char *grpname)
 +
 +      void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
        {
 -              std::vector<FCurve*> &rot_fcurves = rotfcurves_actionGroup_map[grp];
 -              
 -              FCurve *quatcu[4] = {NULL, NULL, NULL, NULL};
 -              int i;
 -              
 -              for (i = 0; i < rot_fcurves.size(); i++)
 -                      quatcu[rot_fcurves[i]->array_index] = rot_fcurves[i];
 -              
 -              char *rna_path = rot_fcurves[0]->rna_path;
 -              
 -              FCurve *eulcu[3] = {
 -                      create_fcurve(0, rna_path),
 -                      create_fcurve(1, rna_path),
 -                      create_fcurve(2, rna_path)
 -              };
 -              
 -              for (i = 0; i < 4; i++) {
 -                      
 -                      FCurve *cu = quatcu[i];
 -                      
 -                      if (!cu) continue;
 -                      
 -                      for (int j = 0; j < cu->totvert; j++) {
 -                              float frame = cu->bezt[j].vec[1][0];
 -                              
 -                              float quat[4] = {
 -                                      quatcu[0] ? evaluate_fcurve(quatcu[0], frame) : 0.0f,
 -                                      quatcu[1] ? evaluate_fcurve(quatcu[1], frame) : 0.0f,
 -                                      quatcu[2] ? evaluate_fcurve(quatcu[2], frame) : 0.0f,
 -                                      quatcu[3] ? evaluate_fcurve(quatcu[3], frame) : 0.0f
 -                              };
 -                              
 -                              float eul[3];
 -                              
 -                              quat_to_eul( eul,quat);
 -                              
 -                              for (int k = 0; k < 3; k++)
 -                                      create_bezt(eulcu[k], frame, eul[k]);
 +              FCurve *fcu= (FCurve*)ob->adt->action->curves.first;
 +
 +              for (; fcu; fcu = fcu->next) {
 +                      if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix)))
 +                              continue;
 +
 +                      char *name = extract_transform_name(fcu->rna_path);
 +                      if (!strcmp(name, tm_name)) {
 +                              for (int i = 0; i < fcu->totvert; i++) {
 +                                      float f = fcu->bezt[i].vec[1][0];
 +                                      if (std::find(fra.begin(), fra.end(), f) == fra.end())
 +                                              fra.push_back(f);
 +                              }
                        }
                }
 -              
 -              for (i = 0; i < 3; i++) {
 -                      add_bone_animation(eulcu[i], id_name(ob), std::string(grpname));
 -                      free_fcurve(eulcu[i]);
 -              }
        }
  
 -      // called for each exported object
 -      void operator() (Object *ob) 
 +      void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
        {
 -              if (!ob->adt || !ob->adt->action) return;
 -              
 -              FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
 -              
 -              if (ob->type == OB_ARMATURE) {
 -                      
 -                      while (fcu) {
 -                              
 -                              if (strstr(fcu->rna_path, ".rotation")) 
 -                                      rotfcurves_actionGroup_map[fcu->grp].push_back(fcu);
 -                              else fcurves_actionGroup_map[fcu->grp].push_back(fcu);
 -                              
 -                              fcu = fcu->next;
 -                      }
 -                      
 -                      for (bPoseChannel *pchan = (bPoseChannel*)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
 -                              int i;
 -                              char *grpname = pchan->name;
 -                              bActionGroup *grp = action_groups_find_named(ob->adt->action, grpname);
 -                              
 -                              if (!grp) continue;
 -                              
 -                              // write animation for location & scaling
 -                              if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end()) continue;
 -                              
 -                              std::vector<FCurve*> &fcurves = fcurves_actionGroup_map[grp];
 -                              for (i = 0; i < fcurves.size(); i++)
 -                                      add_bone_animation(fcurves[i], id_name(ob), std::string(grpname));
 -                              
 -                              // ... for rotation
 -                              if (rotfcurves_actionGroup_map.find(grp) == rotfcurves_actionGroup_map.end())
 -                                      continue;
 -                              
 -                              // if rotation mode is euler - no need to convert it
 -                              if (pchan->rotmode == ROT_MODE_EUL) {
 -                                      
 -                                      std::vector<FCurve*> &rotfcurves = rotfcurves_actionGroup_map[grp];
 -                                      
 -                                      for (i = 0; i < rotfcurves.size(); i++) 
 -                                              add_bone_animation(rotfcurves[i], id_name(ob), std::string(grpname));
 -                              }
 -                              
 -                              // convert rotation to euler & write animation
 -                              else change_quat_to_eul(ob, grp, grpname);
 +              if (rotmode > 0)
 +                      find_frames(ob, fra, prefix, "rotation_euler");
 +              else if (rotmode == ROT_MODE_QUAT)
 +                      find_frames(ob, fra, prefix, "rotation_quaternion");
 +              else if (rotmode == ROT_MODE_AXISANGLE)
 +                      ;
 +      }
 +
 +      // enable fcurves driving a specific bone, disable all the rest
 +      // if bone_name = NULL enable all fcurves
 +      void enable_fcurves(bAction *act, char *bone_name)
 +      {
 +              FCurve *fcu;
 +              char prefix[200];
 +
 +              if (bone_name)
 +                      BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
 +
 +              for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) {
 +                      if (bone_name) {
 +                              if (!strncmp(fcu->rna_path, prefix, strlen(prefix)))
 +                                      fcu->flag &= ~FCURVE_DISABLED;
 +                              else
 +                                      fcu->flag |= FCURVE_DISABLED;
                        }
 -              }
 -              else {
 -                      while (fcu) {
 -                              
 -                              if (!strcmp(fcu->rna_path, "location") ||
 -                                      !strcmp(fcu->rna_path, "scale") ||
 -                                      !strcmp(fcu->rna_path, "rotation_euler")) {
 -                                      
 -                                      add_animation(fcu, id_name(ob));
 -                              }
 -                              
 -                              fcu = fcu->next;
 +                      else {
 +                              fcu->flag &= ~FCURVE_DISABLED;
                        }
                }
        }
@@@ -2383,12 -2192,3 +2383,12 @@@ void DocumentExporter::exportCurrentSce
  void DocumentExporter::exportScenes(const char* filename)
  {
  }
 +
 +/*
 +
 +NOTES:
 +
 +* AnimationExporter::sample_animation enables all curves on armature, this is undesirable for a user
 +
 + */
 +
@@@ -43,8 -43,6 +43,8 @@@ extern "C
  #include "ED_armature.h"
  #include "ED_mesh.h" // ED_vgroup_vert_add, ...
  #include "ED_anim_api.h"
 +#include "ED_object.h"
 +
  #include "WM_types.h"
  #include "WM_api.h"
  
@@@ -54,7 -52,7 +54,7 @@@
  #include "BKE_texture.h"
  #include "BKE_fcurve.h"
  #include "BKE_depsgraph.h"
- #include "BLI_util.h"
+ #include "BLI_path_util.h"
  #include "BKE_displist.h"
  #include "BLI_math.h"
  #include "BKE_scene.h"
@@@ -84,7 -82,6 +84,7 @@@
  #include "DNA_mesh_types.h"
  #include "DNA_material_types.h"
  #include "DNA_scene_types.h"
 +#include "DNA_modifier_types.h"
  
  #include "MEM_guardedalloc.h"
  
@@@ -500,24 -497,20 +500,24 @@@ private
                void link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid,
                                                   TransformReader *tm)
                {
 +                      Object workob;
 +                      Scene *scene = CTX_data_scene(C);
 +
 +                      ModifierData *md = ED_object_modifier_add(NULL, scene, ob, NULL, eModifierType_Armature);
 +                      ((ArmatureModifierData *)md)->object = ob_arm;
 +
                        tm->decompose(bind_shape_matrix, ob->loc, ob->rot, NULL, ob->size);
  
                        ob->parent = ob_arm;
 -                      ob->partype = PARSKEL;
 +                      ob->partype = PAROBJECT;
 +
 +                      what_does_parent(scene, ob, &workob);
 +                      invert_m4_m4(ob->parentinv, workob.obmat);
 +
                        ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
  
                        ((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP;
  
 -                      // we need armature matrix here... where do we get it from I wonder...
 -                      // root node/joint? or node with <instance_controller>?
 -                      float parmat[4][4];
 -                      unit_m4(parmat);
 -                      invert_m4_m4(ob->parentinv, parmat);
 -
                        // create all vertex groups
                        std::vector<JointData>::iterator it;
                        int joint_index;
                                }
                        }
  
 -                      DAG_scene_sort(CTX_data_scene(C));
 +                      DAG_scene_sort(scene);
                        DAG_ids_flush_update(0);
                        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
                }
                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;
  
@@@ -2440,7 -2430,7 +2440,7 @@@ public
  
                        Bone *bone = get_named_bone((bArmature*)ob->data, bone_name);
                        if (!bone) {
 -                              fprintf(stderr, "cannot find bone \"%s\"", bone_name);
 +                              fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
  #ifdef ARMATURE_TEST
                                return NULL;
  #else
  
                // use bind matrix if available or calc "current" world mat
                if (!armature_importer->get_joint_bind_mat(m, node)) {
 -                      float temp[4][4];
 -                      get_node_mat(temp, node, NULL, NULL);
 -                      mul_m4_m4m4(m, temp, par);
 +                      if (par) {
 +                              float temp[4][4];
 +                              get_node_mat(temp, node, NULL, NULL);
 +                              mul_m4_m4m4(m, temp, par);
 +                      }
 +                      else {
 +                              get_node_mat(m, node, NULL, NULL);
 +                      }
                }
  
                COLLADAFW::NodePointerArray& children = node->getChildNodes();
@@@ -193,6 -193,7 +193,7 @@@ static int wm_macro_end(wmOperator *op
        if (retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED)) {
                if (op->customdata) {
                        MEM_freeN(op->customdata);
+                       op->customdata = NULL;
                }
        }
  
@@@ -353,6 -354,28 +354,28 @@@ wmOperatorType *WM_operatortype_append_
        return ot;
  }
  
+ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType*, void*), void *userdata)
+ {
+       wmOperatorType *ot;
+       ot= MEM_callocN(sizeof(wmOperatorType), "operatortype");
+       ot->srna= RNA_def_struct(&BLENDER_RNA, "", "OperatorProperties");
+       ot->flag= OPTYPE_MACRO;
+       ot->exec= wm_macro_exec;
+       ot->invoke= wm_macro_invoke;
+       ot->modal= wm_macro_modal;
+       ot->cancel= wm_macro_cancel;
+       ot->poll= NULL;
+       opfunc(ot, userdata);
+       RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description:"(undocumented operator)");
+       RNA_def_struct_identifier(ot->srna, ot->idname);
+       BLI_addtail(&global_ops, ot);
+ }
  wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char *idname)
  {
        wmOperatorTypeMacro *otmacro= MEM_callocN(sizeof(wmOperatorTypeMacro), "wmOperatorTypeMacro");
@@@ -594,10 -617,13 +617,13 @@@ int WM_menu_invoke(bContext *C, wmOpera
        else if (RNA_property_type(prop) != PROP_ENUM) {
                printf("WM_menu_invoke: %s \"type\" is not an enum property\n", op->type->idname);
        }
+       else if (RNA_property_is_set(op->ptr, RNA_property_identifier(prop))) {
+               return op->type->exec(C, op);
+       }
        else {
                pup= uiPupMenuBegin(C, op->type->name, 0);
                layout= uiPupMenuLayout(pup);
-               uiItemsEnumO(layout, op->type->idname, (char*)RNA_property_identifier(prop));
+               uiItemsFullEnumO(layout, op->type->idname, (char*)RNA_property_identifier(prop), op->ptr->data, WM_OP_EXEC_REGION_WIN, 0);
                uiPupMenuEnd(C, pup);
        }
  
@@@ -609,10 -635,16 +635,16 @@@ int WM_operator_confirm_message(bContex
  {
        uiPopupMenu *pup;
        uiLayout *layout;
+       IDProperty *properties= op->ptr->data;
+       if(properties && properties->len)
+               properties= IDP_CopyProperty(op->ptr->data);
+       else
+               properties= NULL;
  
        pup= uiPupMenuBegin(C, "OK?", ICON_QUESTION);
        layout= uiPupMenuLayout(pup);
-       uiItemO(layout, message, 0, op->type->idname);
+       uiItemFullO(layout, message, 0, op->type->idname, properties, WM_OP_EXEC_REGION_WIN, 0);
        uiPupMenuEnd(C, pup);
        
        return OPERATOR_CANCELLED;
@@@ -659,6 -691,8 +691,8 @@@ void WM_operator_properties_filesel(wmO
        RNA_def_property_flag(prop, PROP_HIDDEN);
        prop= RNA_def_boolean(ot->srna, "filter_text", (filter & TEXTFILE), "Filter text files", "");
        RNA_def_property_flag(prop, PROP_HIDDEN);
+       prop= RNA_def_boolean(ot->srna, "filter_btx", (filter & BTXFILE), "Filter btx files", "");
+       RNA_def_property_flag(prop, PROP_HIDDEN);
        prop= RNA_def_boolean(ot->srna, "filter_folder", (filter & FOLDERFILE), "Filter folders", "");
        RNA_def_property_flag(prop, PROP_HIDDEN);
  
        RNA_def_property_flag(prop, PROP_HIDDEN);
  }
  
+ void WM_operator_properties_select_all(wmOperatorType *ot) {
+       static EnumPropertyItem select_all_actions[] = {
+                       {SEL_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle selection for all elements"},
+                       {SEL_SELECT, "SELECT", 0, "Select", "Select all elements"},
+                       {SEL_DESELECT, "DESELECT", 0, "Deselect", "Deselect all elements"},
+                       {SEL_INVERT, "INVERT", 0, "Invert", "Invert selection of all elements"},
+                       {0, NULL, 0, NULL, NULL}
+       };
+       RNA_def_enum(ot->srna, "action", select_all_actions, SEL_TOGGLE, "Action", "Selection action to execute");
+ }
  void WM_operator_properties_gesture_border(wmOperatorType *ot, int extend)
  {
        RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
  
        if(extend)
-               RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first.");
+               RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first.");
  }
  
  
@@@ -730,8 -776,11 +776,11 @@@ static uiBlock *wm_block_create_redo(bC
        layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, 20, style);
        uiItemL(layout, op->type->name, 0);
  
-       if(op->type->ui)
-               op->type->ui((bContext*)C, op, layout);
+       if(op->type->ui) {
+               op->layout= layout;
+               op->type->ui((bContext*)C, op);
+               op->layout= NULL;
+       }
        else
                uiDefAutoButsRNA(C, layout, &ptr, columns);
  
        return block;
  }
  
+ static uiBlock *wm_operator_create_ui(bContext *C, ARegion *ar, void *userData)
+ {
+       struct { wmOperator *op; int width; int height; } * data = userData;
+       wmWindowManager *wm= CTX_wm_manager(C);
+       wmOperator *op= data->op;
+       PointerRNA ptr;
+       uiBlock *block;
+       uiLayout *layout;
+       uiStyle *style= U.uistyles.first;
+       block= uiBeginBlock(C, ar, "opui_popup", UI_EMBOSS);
+       uiBlockClearFlag(block, UI_BLOCK_LOOP);
+       uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT);
+       if(!op->properties) {
+               IDPropertyTemplate val = {0};
+               op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties");
+       }
+       RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+       layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, style);
+       if(op->type->ui) {
+               op->layout= layout;
+               op->type->ui((bContext*)C, op);
+               op->layout= NULL;
+       }
+       uiPopupBoundsBlock(block, 4.0f, 0, 0);
+       uiEndBlock(C, block);
+       return block;
+ }
  int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *event)
  {
        int retval= OPERATOR_CANCELLED;
        return retval;
  }
  
+ void WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
+ {
+       struct { wmOperator *op; int width; int height; } data;
+       data.op = op;
+       data.width = width;
+       data.height = height;
+       uiPupBlock(C, wm_operator_create_ui, &data);
+ }
  int WM_operator_redo_popup(bContext *C, wmOperator *op)
  {
        uiPupBlock(C, wm_block_create_redo, op);
        return OPERATOR_CANCELLED;
  }
  
 +
  /* ***************** Debug menu ************************* */
  
  static uiBlock *wm_block_create_menu(bContext *C, ARegion *ar, void *arg_op)
        layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 300, 20, style);
        uiItemL(layout, op->type->name, 0);
  
-       if(op->type->ui)
-               op->type->ui(C, op, layout);
+       if(op->type->ui) {
+               op->layout= layout;
+               op->type->ui(C, op);
+               op->layout= NULL;
+       }
        else
                uiDefAutoButsRNA(C, layout, op->ptr, 2);
        
@@@ -836,6 -931,8 +932,8 @@@ static uiBlock *wm_block_create_splash(
        uiBut *but;
        uiLayout *layout, *split, *col;
        uiStyle *style= U.uistyles.first;
+       struct RecentFile *recent;
+       int i;
        
        block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
        uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1);
  
        uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
        
-       split = uiLayoutSplit(layout, 0);
+       split = uiLayoutSplit(layout, 0, 0);
        col = uiLayoutColumn(split, 0);
        uiItemL(col, "Links", 0);
        uiItemO(col, NULL, ICON_URL, "HELP_OT_release_logs");
        
        col = uiLayoutColumn(split, 0);
        uiItemL(col, "Recent", 0);
-       uiItemsEnumO(col, "WM_OT_open_recentfile_splash", "file");
+       for(recent = G.recent_files.first, i=0; (i<6) && (recent); recent = recent->next, i++) {
+               char *display_name= BLI_last_slash(recent->filename);
+               if(display_name)        display_name++; /* skip the slash */
+               else                            display_name= recent->filename;
+               uiItemStringO(col, display_name, ICON_FILE_BLEND, "WM_OT_open_mainfile", "path", recent->filename);
+       }
        uiItemS(col);
  
        uiCenteredBoundsBlock(block, 0.0f);
@@@ -935,7 -1038,7 +1039,7 @@@ static uiBlock *wm_block_search_menu(bC
        block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
        uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT);
        
-       but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, "");
+       but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, 0, 0, "");
        uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
        
        /* fake button, it holds space for search items */
@@@ -1005,7 -1108,7 +1109,7 @@@ static void WM_OT_call_menu(wmOperatorT
  
        ot->invoke= wm_call_menu_invoke;
  
-       RNA_def_string(ot->srna, "name", "", BKE_ST_MAXNAME, "Name", "Name of the new sequence strip");
+       RNA_def_string(ot->srna, "name", "", BKE_ST_MAXNAME, "Name", "Name of the menu");
  }
  
  /* ************ window / screen operator definitions ************** */
@@@ -1044,126 -1147,6 +1148,6 @@@ static void WM_OT_read_homefile(wmOpera
        RNA_def_boolean(ot->srna, "factory", 0, "Factory Settings", "");
  }
  
- /* ********* recent file *********** */
- static int recentfile_exec(bContext *C, wmOperator *op)
- {
-       int event= RNA_enum_get(op->ptr, "file");
-       // XXX wm in context is not set correctly after WM_read_file -> crash
-       // do it before for now, but is this correct with multiple windows?
-       if(event>0) {
-               if (G.sce[0] && (event==1)) {
-                       WM_event_add_notifier(C, NC_WINDOW, NULL);
-                       WM_read_file(C, G.sce, op->reports);
-               }
-               else {
-                       struct RecentFile *recent = BLI_findlink(&(G.recent_files), event-1);
-                       if(recent) {
-                               WM_event_add_notifier(C, NC_WINDOW, NULL);
-                               WM_read_file(C, recent->filename, op->reports);
-                       }
-               }
-       }
-       return 0;
- }
- static int wm_recentfile_invoke(bContext *C, wmOperator *op, wmEvent *event)
- {
-       uiPopupMenu *pup;
-       uiLayout *layout;
-       pup= uiPupMenuBegin(C, "Open Recent", 0);
-       layout= uiPupMenuLayout(pup);
-       uiItemsEnumO(layout, op->type->idname, "file");
-       uiPupMenuEnd(C, pup);
-       
-       return OPERATOR_CANCELLED;
- }
- static EnumPropertyItem *open_recentfile_itemf(bContext *C, PointerRNA *ptr, int *free)
- {
-       EnumPropertyItem tmp = {0, "", 0, "", ""};
-       EnumPropertyItem *item= NULL;
-       struct RecentFile *recent;
-       int totitem= 0, i;
-       /* dynamically construct enum */
-       for(recent = G.recent_files.first, i=0; (i<U.recent_files) && (recent); recent = recent->next, i++) {
-               tmp.value= i+1;
-               tmp.icon= ICON_FILE_BLEND;
-               tmp.identifier= recent->filename;
-               tmp.name= BLI_short_filename(recent->filename);
-               RNA_enum_item_add(&item, &totitem, &tmp);
-       }
-       RNA_enum_item_end(&item, &totitem);
-       *free= 1;
-       return item;
- }
- static void WM_OT_open_recentfile(wmOperatorType *ot)
- {
-       PropertyRNA *prop;
-       static EnumPropertyItem file_items[]= {
-               {0, NULL, 0, NULL, NULL}};
-       ot->name= "Open Recent File";
-       ot->idname= "WM_OT_open_recentfile";
-       ot->description="Open recent files list.";
-       
-       ot->invoke= wm_recentfile_invoke;
-       ot->exec= recentfile_exec;
-       ot->poll= WM_operator_winactive;
-       
-       prop= RNA_def_enum(ot->srna, "file", file_items, 1, "File", "");
-       RNA_def_enum_funcs(prop, open_recentfile_itemf);
- }
- static EnumPropertyItem *open_recentfile_splash_itemf(bContext *C, PointerRNA *ptr, int *free)
- {
-       EnumPropertyItem tmp = {0, "", 0, "", ""};
-       EnumPropertyItem *item= NULL;
-       struct RecentFile *recent;
-       int totitem= 0, i;
-       
-       /* dynamically construct enum */
-       for(recent = G.recent_files.first, i=0; (i<6) && (recent); recent = recent->next, i++) {
-               tmp.value= i+1;
-               tmp.icon= ICON_FILE_BLEND;
-               tmp.identifier= recent->filename;
-               tmp.name= BLI_last_slash(recent->filename);
-               if(tmp.name) tmp.name += 1;
-               else tmp.name = recent->filename;
-               RNA_enum_item_add(&item, &totitem, &tmp);
-       }
-       
-       RNA_enum_item_end(&item, &totitem);
-       *free= 1;
-       
-       return item;
- }
- static void WM_OT_open_recentfile_splash(wmOperatorType *ot)
- {
-       PropertyRNA *prop;
-       static EnumPropertyItem file_items[]= {
-               {0, NULL, 0, NULL, NULL}};
-       
-       ot->name= "Open Recent File";
-       ot->idname= "WM_OT_open_recentfile_splash";
-       ot->description="Open recent files list.";
-       
-       ot->exec= recentfile_exec;
-       ot->poll= WM_operator_winactive;
-       
-       prop= RNA_def_enum(ot->srna, "file", file_items, 1, "File", "");
-       RNA_def_enum_funcs(prop, open_recentfile_splash_itemf);
- }
  /* *************** open file **************** */
  
  static void open_set_load_ui(wmOperator *op)
@@@ -1544,6 -1527,10 +1528,10 @@@ static int wm_save_mainfile_invoke(bCon
  {
        char name[FILE_MAX];
  
+       /* cancel if no active window */
+       if (CTX_wm_window(C) == NULL)
+               return OPERATOR_CANCELLED;
        save_set_compress(op);
        
        BLI_strncpy(name, G.sce, FILE_MAX);
@@@ -1566,7 -1553,7 +1554,7 @@@ static void WM_OT_save_mainfile(wmOpera
        
        ot->invoke= wm_save_mainfile_invoke;
        ot->exec= wm_save_as_mainfile_exec;
-       ot->poll= WM_operator_winactive;
+       ot->poll= NULL;
        
        WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER);
        RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file.");
@@@ -1944,7 -1931,7 +1932,7 @@@ int WM_gesture_circle_modal(bContext *C
                case GESTURE_MODAL_CANCEL:
                case GESTURE_MODAL_CONFIRM:
                        wm_gesture_end(C, op);
-                       return OPERATOR_CANCELLED;
+                       return OPERATOR_FINISHED; /* use finish or we dont get an undo */
                }
        }
  //    // Allow view navigation???
@@@ -2301,7 -2288,7 +2289,7 @@@ int WM_radial_control_modal(bContext *C
                
                if(event->ctrl) {
                        if(mode == WM_RADIALCONTROL_STRENGTH)
-                               new_value = ((int)(new_value * 100) / 10*10) / 100.0f;
+                               new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
                        else
                                new_value = ((int)new_value + 5) / 10*10;
                }
@@@ -2428,7 -2415,6 +2416,7 @@@ void WM_OT_radial_control_partial(wmOpe
        RNA_def_int_vector(ot->srna, "initial_mouse", 2, NULL, INT_MIN, INT_MAX, "initial_mouse", "", INT_MIN, INT_MAX);
  }
  
 +
  /* ************************** timer for testing ***************** */
  
  /* uses no type defines, fully local testing function anyway... ;) */
@@@ -2469,8 -2455,10 +2457,10 @@@ static int redraw_timer_exec(bContext *
                                CTX_wm_area_set(C, sa);
  
                                for(ar_iter= sa->regionbase.first; ar_iter; ar_iter= ar_iter->next) {
-                                       CTX_wm_region_set(C, ar_iter);
-                                       ED_region_do_draw(C, ar_iter);
+                                       if(ar_iter->swinid) {
+                                               CTX_wm_region_set(C, ar_iter);
+                                               ED_region_do_draw(C, ar_iter);
+                                       }
                                }
                        }
  
@@@ -2566,9 -2554,13 +2556,13 @@@ void wm_operatortype_free(void
  {
        wmOperatorType *ot;
        
-       for(ot= global_ops.first; ot; ot= ot->next)
+       for(ot= global_ops.first; ot; ot= ot->next) {
                if(ot->macro.first)
                        wm_operatortype_free_macro(ot);
+               if(ot->ext.srna) /* python operator, allocs own string */
+                       MEM_freeN(ot->idname);
+       }
        
        BLI_freelistN(&global_ops);
  }
@@@ -2581,8 -2573,6 +2575,6 @@@ void wm_operatortype_init(void
        WM_operatortype_append(WM_OT_save_homefile);
        WM_operatortype_append(WM_OT_window_fullscreen_toggle);
        WM_operatortype_append(WM_OT_exit_blender);
-       WM_operatortype_append(WM_OT_open_recentfile);
-       WM_operatortype_append(WM_OT_open_recentfile_splash);
        WM_operatortype_append(WM_OT_open_mainfile);
        WM_operatortype_append(WM_OT_link_append);
        WM_operatortype_append(WM_OT_recover_last_session);
        WM_operatortype_append(WM_OT_debug_menu);
        WM_operatortype_append(WM_OT_splash);
        WM_operatortype_append(WM_OT_search_menu);
 -      WM_operatortype_append(WM_OT_call_menu);
  
  #ifdef WITH_COLLADA
        /* XXX: move these */
        WM_operatortype_append(WM_OT_collada_import);
  #endif
  
 +      WM_operatortype_append(WM_OT_call_menu);
  }
  
  /* called in transform_ops.c, on each regeneration of keymaps  */
@@@ -2713,13 -2703,13 +2705,13 @@@ static void gesture_border_modal_keymap
  void wm_window_keymap(wmKeyConfig *keyconf)
  {
        wmKeyMap *keymap= WM_keymap_find(keyconf, "Window", 0, 0);
-       wmKeyMapItem *km;
+       wmKeyMapItem *kmi;
        
        /* note, this doesn't replace existing keymap items */
        WM_keymap_verify_item(keymap, "WM_OT_window_duplicate", WKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
        #ifdef __APPLE__
        WM_keymap_add_item(keymap, "WM_OT_read_homefile", NKEY, KM_PRESS, KM_OSKEY, 0);
-       WM_keymap_add_item(keymap, "WM_OT_open_recentfile", OKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0);
+       WM_keymap_add_menu(keymap, "INFO_MT_file_open_recent", OKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0);
        WM_keymap_add_item(keymap, "WM_OT_open_mainfile", OKEY, KM_PRESS, KM_OSKEY, 0);
        WM_keymap_add_item(keymap, "WM_OT_save_mainfile", SKEY, KM_PRESS, KM_OSKEY, 0);
        WM_keymap_add_item(keymap, "WM_OT_save_as_mainfile", SKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0);
        #endif
        WM_keymap_add_item(keymap, "WM_OT_read_homefile", NKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0); 
-       WM_keymap_add_item(keymap, "WM_OT_open_recentfile", OKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
+       WM_keymap_add_menu(keymap, "INFO_MT_file_open_recent", OKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
        WM_keymap_add_item(keymap, "WM_OT_open_mainfile", OKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "WM_OT_open_mainfile", F1KEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "WM_OT_link_append", OKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
-       km= WM_keymap_add_item(keymap, "WM_OT_link_append", F1KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_boolean_set(km->ptr, "link", FALSE);
+       kmi= WM_keymap_add_item(keymap, "WM_OT_link_append", F1KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_boolean_set(kmi->ptr, "link", FALSE);
  
        WM_keymap_add_item(keymap, "WM_OT_save_mainfile", SKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "WM_OT_save_mainfile", WKEY, KM_PRESS, KM_CTRL, 0);
        /* Space switching */
  
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F2KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was DXF export */
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "LOGIC_EDITOR");
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F3KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "NODE_EDITOR");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F2KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was DXF export */
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "LOGIC_EDITOR");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F4KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was data browser */
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "CONSOLE");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F3KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "NODE_EDITOR");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F5KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "VIEW_3D");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F4KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was data browser */
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "CONSOLE");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F6KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "GRAPH_EDITOR");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F5KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "VIEW_3D");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F7KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "PROPERTIES");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F6KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "GRAPH_EDITOR");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F8KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "SEQUENCE_EDITOR");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F7KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "PROPERTIES");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F9KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "OUTLINER");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F8KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "SEQUENCE_EDITOR");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F9KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "OUTLINER");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F9KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "OUTLINER");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F10KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "IMAGE_EDITOR");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F10KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "IMAGE_EDITOR");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F11KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "TEXT_EDITOR");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F11KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "TEXT_EDITOR");
  
-       km = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F12KEY, KM_PRESS, KM_SHIFT, 0);
-       RNA_string_set(km->ptr, "path", "area.type");
-       RNA_string_set(km->ptr, "value", "DOPESHEET_EDITOR");
+       kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F12KEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_string_set(kmi->ptr, "path", "area.type");
+       RNA_string_set(kmi->ptr, "value", "DOPESHEET_EDITOR");
  
        gesture_circle_modal_keymap(keyconf);
        gesture_border_modal_keymap(keyconf);