svn merge -r39558:39800 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorCampbell Barton <ideasman42@gmail.com>
Tue, 13 Sep 2011 06:39:17 +0000 (06:39 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 13 Sep 2011 06:39:17 +0000 (06:39 +0000)
19 files changed:
1  2 
release/scripts/startup/bl_ui/properties_data_mesh.py
release/scripts/startup/bl_ui/space_view3d.py
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/editors/armature/editarmature.c
source/blender/editors/include/ED_view3d.h
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_ops.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_scene.c

index d824ec3d589413e66951c78adc020fcdceb4ce03,75df7dad5f2fc3be25a4c6df3cccc0e15cbdb936..7503959480b50c608ffcfe0be7ca5d2e68e1562a
@@@ -73,7 -73,7 +73,7 @@@ class DATA_PT_context_mesh(MeshButtonsP
          ob = context.object
          mesh = context.mesh
          space = context.space_data
-         layout.prop(context.scene.tool_settings, "mesh_select_mode", index=0, text="Vertex")
          if ob:
              layout.template_ID(ob, "data")
          elif mesh:
@@@ -135,8 -135,7 +135,8 @@@ class DATA_PT_vertex_groups(MeshButtons
  
          ob = context.object
          group = ob.vertex_groups.active
 -
 +        
 +        
          rows = 2
          if group:
              rows = 5
          row.template_list(ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
  
          col = row.column(align=True)
 +        # Jason was here, this was replaced by hardcoded list view checkboxes. #
 +        #col.prop(group, "flag")
 +        
          col.operator("object.vertex_group_add", icon='ZOOMIN', text="")
          col.operator("object.vertex_group_remove", icon='ZOOMOUT', text="")
          col.menu("MESH_MT_vertex_group_specials", icon='DOWNARROW_HLT', text="")
          if group:
              row = layout.row()
              row.prop(group, "name")
 +        #Jason was here
 +        # add buttons to make it faster to lock/unlock vgroups
 +        if ob.mode == 'WEIGHT_PAINT' and len(ob.vertex_groups) > 0:
 +            row = layout.row()
 +            sub = row.row(align=True)
 +            sub.operator("object.vertex_group_lock_all", text="Lock All")
 +            sub.operator("object.vertex_group_invert_locks", text="Invert Locks")
 +            sub.operator("object.vertex_group_unlock_all", text="Unlock All")
  
          if ob.mode == 'EDIT' and len(ob.vertex_groups) > 0:
              row = layout.row()
index 1ae934732eda889e60f09171053b9f0915613ae9,9f96df1eb6694b23695da46c0d080e093eae6bc4..c9817cdf90591e40bce815be316ea6dbbe26a8c5
@@@ -180,6 -180,10 +180,10 @@@ class VIEW3D_MT_transform(Menu)
          layout.operator("object.randomize_transform")
          layout.operator("object.align")
  
+         layout.separator()
+         layout.operator("object.anim_transforms_to_deltas")
  
  class VIEW3D_MT_mirror(Menu):
      bl_label = "Mirror"
@@@ -1068,8 -1072,6 +1072,8 @@@ class VIEW3D_MT_paint_weight(Menu)
          layout.operator("object.vertex_group_invert", text="Invert")
          layout.operator("object.vertex_group_clean", text="Clean")
          layout.operator("object.vertex_group_levels", text="Levels")
 +        #Jason
 +        layout.operator("object.vertex_group_fix", text="Fix Deforms")
  
          layout.separator()
  
@@@ -1261,11 -1263,15 +1265,15 @@@ class VIEW3D_MT_pose_transform(Menu)
  
          layout.operator("pose.transforms_clear", text="All")
  
+         layout.separator()
          layout.operator("pose.loc_clear", text="Location")
          layout.operator("pose.rot_clear", text="Rotation")
          layout.operator("pose.scale_clear", text="Scale")
  
-         layout.label(text="Origin")
+         layout.separator()
+         layout.operator("pose.user_transforms_clear", text="Reset unkeyed")
  
  
  class VIEW3D_MT_pose_slide(Menu):
@@@ -2075,9 -2081,11 +2083,11 @@@ class VIEW3D_PT_view3d_properties(Panel
          col.prop(view, "lens")
          col.label(text="Lock to Object:")
          col.prop(view, "lock_object", text="")
-         if view.lock_object and view.lock_object.type == 'ARMATURE':
-             col.prop_search(view, "lock_bone", view.lock_object.data, "bones", text="")
-         elif not view.lock_object:
+         lock_object = view.lock_object
+         if lock_object:
+             if lock_object.type == 'ARMATURE':
+                 col.prop_search(view, "lock_bone", lock_object.data, "edit_bones" if lock_object.mode == 'EDIT' else "bones", text="")
+         else:
              col.prop(view, "lock_cursor", text="Lock to Cursor")
  
          col = layout.column()
index cc1e9b0c2042ca92939c79f1f3f1586acf8f90c9,b71593add961fbdb2ca5157b6cf89e19772c5d06..23d896abdbba7d5e1c76db285fde90ff9e23e11b
@@@ -643,8 -643,6 +643,8 @@@ class VIEW3D_PT_tools_brush(PaintPanel
          elif context.weight_paint_object and brush:
              layout.prop(context.tool_settings, "vertex_group_weight", text="Weight", slider=True)
              layout.prop(context.tool_settings, "use_auto_normalize", text="Auto Normalize")
 +            # Jason was here
 +            layout.prop(context.tool_settings, "use_multipaint", text="Multi-Paint")
  
              col = layout.column()
  
@@@ -1051,13 -1049,12 +1051,13 @@@ class VIEW3D_PT_tools_weightpaint(View3
          ob = context.active_object
  
          col = layout.column()
-         col.active = ob.vertex_groups.active != None
+         col.active = ob.vertex_groups.active is not None
          col.operator("object.vertex_group_normalize_all", text="Normalize All")
          col.operator("object.vertex_group_normalize", text="Normalize")
          col.operator("object.vertex_group_invert", text="Invert")
          col.operator("object.vertex_group_clean", text="Clean")
          col.operator("object.vertex_group_levels", text="Levels")
 +        col.operator("object.vertex_group_fix", text="Fix Deforms")
  
  
  class VIEW3D_PT_tools_weightpaint_options(View3DPanel, Panel):
index a3e6c081fb7eb28191a421c2e6ac4d0e75cc7062,6e17b056685e9d5cc789040f90f0204862b4a64b..a109d5722abdd70bec7857ed13b7d6ee228faa76
@@@ -222,9 -222,6 +222,9 @@@ struct DerivedMesh 
        /* Draw all vertices as bgl points (no options) */
        void (*drawVerts)(DerivedMesh *dm);
  
 +      /* Jason Draw all selected vertices as bgl points (no options) */
 +      void (*drawSelectedVerts)(DerivedMesh *dm);
 +
        /* Draw edges in the UV mesh (if exists) */
        void (*drawUVEdges)(DerivedMesh *dm);
  
                                                        int (*setDrawOptions)(void *userData, int index,
                                                                                                  int *drawSmooth_r),
                                                        void *userData, int useColors,
-                                                       int (*setMaterial)(int, void *attribs));
+                                                       int (*setMaterial)(int, void *attribs),
+                                                       int (*compareDrawOptions)(void *userData, int cur_index, int next_index));
  
        /* Draw mapped faces using MTFace 
         *  o Drawing options too complicated to enumerate, look at code.
index 941a151689678c90f896d2268244d69e90f6e29f,ff7f2586767b30c017350412f3aec58b6f223c7f..4b6d51dfbda6bd7bb9ad92b4379dd8f619a7cff6
@@@ -40,9 -40,6 +40,9 @@@
  #include "DNA_cloth_types.h"
  #include "DNA_key_types.h"
  #include "DNA_meshdata_types.h"
 +// Jason
 +#include "DNA_armature_types.h"
 +
  #include "DNA_object_types.h"
  #include "DNA_scene_types.h" // N_T
  
@@@ -75,8 -72,6 +75,8 @@@
  #include "GPU_material.h"
  
  #include "ED_sculpt.h" /* for ED_sculpt_modifiers_changed */
 +// Jason was here, this is for multi-paint
 +#include "ED_armature.h"
  
  ///////////////////////////////////
  ///////////////////////////////////
@@@ -642,7 -637,8 +642,8 @@@ static void emDM_foreachMappedFaceCente
  }
  
  /* note, material function is ignored for now. */
- static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int UNUSED(useColors), int (*setMaterial)(int, void *attribs))
+ static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int UNUSED(useColors), int (*setMaterial)(int, void *attribs),
+                       int (*compareDrawOptions)(void *userData, int cur_index, int next_index))
  {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
        EditFace *efa;
        
        (void)setMaterial; /* unused */
  
+       /* currently unused -- each original face is handled separately */
+       (void)compareDrawOptions;
        if (emdm->vertexCos) {
                EditVert *eve;
  
@@@ -1608,50 -1607,19 +1612,50 @@@ void weight_to_rgb(float input, float *
        }
  }
  
 -static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col)
 +static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col, char *dg_flags, int selected, int unselected, int multipaint, int auto_normalize)
  {
        Mesh *me = ob->data;
 -      float colf[4], input = 0.0f;
 +      float colf[4], input = 0.0f;// Jason
        int i;
 +      char make_black = FALSE;
 +      char was_a_nonzero = FALSE;
  
        if (me->dvert) {
 -              for (i=0; i<me->dvert[vert].totweight; i++)
 -                      if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
 -                              input+=me->dvert[vert].dw[i].weight;            
 -      }
 +              for (i=0; i<me->dvert[vert].totweight; i++) {
 +                      // Jason was here
 +                      // in multipaint, get the average if auto normalize is inactive
 +                      // get the sum if it is active
 +                      if(multipaint && selected > 1) {
 +                              if(dg_flags[me->dvert[vert].dw[i].def_nr]) {
 +                                      if(me->dvert[vert].dw[i].weight) {
 +                                              input+=me->dvert[vert].dw[i].weight;
 +                                              was_a_nonzero = TRUE;
 +                                      }
 +                              }
 +                      } else if (me->dvert[vert].dw[i].def_nr==ob->actdef-1) {
 +                              input+=me->dvert[vert].dw[i].weight;
 +                      }
 +              }
 +              
 +              // Jason was here
 +              // make it black if the selected groups have no weight on a vertex
 +              if(!make_black && multipaint && selected > 1) {
 +                      if(!was_a_nonzero) {
 +                              make_black = TRUE;
 +                      } else if (!auto_normalize){
 +                              // get the average
 +                              input /= selected;
 +                      }
  
 -      CLAMP(input, 0.0f, 1.0f);
 +              }
 +      }
 +      
 +      if(make_black) {
 +              input = -1;
 +      }else {
 +              CLAMP(input, 0.0f, 1.0f);
 +      }
 +      
        
        if(coba)
                do_colorband(coba, input, colf);
@@@ -1670,69 -1638,26 +1674,69 @@@ void vDM_ColorBand_store(ColorBand *cob
  {
        stored_cb= coba;
  }
 -
 -static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm)
 +/* TODO move duplicates to header */
 +/* Jason was here duplicate function in paint_vertex.c*/
 +static char* get_selected_defgroups(Object *ob, int defcnt) {
 +      bPoseChannel *chan;
 +      bPose *pose;
 +      bDeformGroup *defgroup;
 +      //Bone *bone;
 +      char *dg_flags = MEM_callocN(defcnt*sizeof(char), "dg_selected_flags");
 +      int i;
 +      Object *armob = ED_object_pose_armature(ob);
 +
 +      if(armob) {
 +              pose = armob->pose;
 +              for (chan=pose->chanbase.first; chan; chan=chan->next) {
 +                      for (i = 0, defgroup = ob->defbase.first; i < defcnt && defgroup; defgroup = defgroup->next, i++) {
 +                              if(!strcmp(defgroup->name, chan->bone->name)) {
 +                                      dg_flags[i] = (chan->bone->flag & BONE_SELECTED);
 +                              }
 +                      }
 +              }
 +      }
 +      
 +      return dg_flags;
 +}
 +/* TODO move duplicates to header */
 +/* Jason was here duplicate function */
 +static int count_true(char *list, int len)
 +{
 +      int i;
 +      int cnt = 0;
 +      for(i = 0; i < len; i++) {
 +              if (list[i]) {
 +                      cnt++;
 +              }
 +      }
 +      return cnt;
 +}
 +static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int multipaint, int auto_normalize)
  {
        Mesh *me = ob->data;
        MFace *mf = me->mface;
        ColorBand *coba= stored_cb;     /* warning, not a local var */
        unsigned char *wtcol;
        int i;
 -      
 +      // Jason was here
 +      int defcnt = BLI_countlist(&ob->defbase);
 +      char *dg_flags = get_selected_defgroups(ob, defcnt);
 +      int selected = count_true(dg_flags, defcnt);
 +      int unselected = defcnt - selected;
 +
        wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
        
        memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
        for (i=0; i<me->totface; i++, mf++) {
 -              calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]); 
 -              calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]); 
 -              calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]); 
 +              calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4], dg_flags, selected, unselected, multipaint, auto_normalize); 
 +              calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4], dg_flags, selected, unselected, multipaint, auto_normalize); 
 +              calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4], dg_flags, selected, unselected, multipaint, auto_normalize); 
                if (mf->v4)
 -                      calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]); 
 +                      calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4], dg_flags, selected, unselected, multipaint, auto_normalize); 
        }
 -      
 +      // Jason
 +      MEM_freeN(dg_flags);
 +
        CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData);
  }
  
@@@ -1939,7 -1864,7 +1943,7 @@@ static void mesh_calc_modifiers(Scene *
                                }
  
                                if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
 -                                      add_weight_mcol_dm(ob, dm);
 +                                      add_weight_mcol_dm(ob, dm, scene->toolsettings->multipaint, scene->toolsettings->auto_normalize);// Jason
  
                                /* Constructive modifiers need to have an origindex
                                 * otherwise they wont have anywhere to copy the data from.
                CDDM_calc_normals(finaldm);
  
                if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
 -                      add_weight_mcol_dm(ob, finaldm);
 +                      add_weight_mcol_dm(ob, finaldm, scene->toolsettings->multipaint, scene->toolsettings->auto_normalize);// Jason
        } else if(dm) {
                finaldm = dm;
        } else {
                }
  
                if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
 -                      add_weight_mcol_dm(ob, finaldm);
 +                      add_weight_mcol_dm(ob, finaldm, scene->toolsettings->multipaint, scene->toolsettings->auto_normalize);// Jason
        }
  
        /* add an orco layer if needed */
@@@ -2336,7 -2261,7 +2340,7 @@@ static void clear_mesh_caches(Object *o
  static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
  {
        Object *obact = scene->basact?scene->basact->object:NULL;
 -      int editing = paint_facesel_test(ob);
 +      int editing = paint_facesel_test(ob) || paint_vertsel_test(ob);// Jason: paint_vertsel_test
        /* weight paint and face select need original indices because of selection buffer drawing */
        int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)));
  
index 5c7ffa5adc3af3bb45b26f6fa4807b779fa24b4f,5eb97630e83d16fd03ddde1018b2cd846e4b27bd..0dde94bc639b589467b229e9bc74ff12eb9266cc
@@@ -268,44 -268,6 +268,44 @@@ static void cdDM_update_normals_from_pb
  
        BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
  }
 +// Jason
 +static void cdDM_drawSelectedVerts(DerivedMesh *dm)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
 +      MVert *mv = cddm->mvert;
 +      int i;
 +      if( GPU_buffer_legacy(dm) ) {
 +              char prev_sel= 0; /* always invalid */;
 +
 +              glBegin(GL_POINTS);
 +              for(i = 0; i < dm->numVertData; i++, mv++) {
 +                      if(!(mv->flag & ME_HIDE)) {
 +                              const char sel= mv->flag & 1;
 +                              if(prev_sel != sel) {
 +                                      prev_sel= sel;
 +
 +                                      // TODO define selected color
 +                                      if(sel) {
 +                                              glColor3f(1.0f, 1.0f, 0.0f);
 +                                      }else {
 +                                              glColor3f(0.0f, 0.0f, 0.0f);
 +                                      }
 +                              }
 +
 +                              glVertex3fv(mv->co);
 +                      }
 +              }
 +              glEnd();
 +      }
 +      else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
 +              GPU_vertex_setup(dm);
 +              if( !GPU_buffer_legacy(dm) ) {
 +                      if(dm->drawObject->tot_triangle_point)  glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point);
 +                      else                                                    glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point);
 +              }
 +              GPU_buffer_unbind();
 +      }
 +}
  
  static void cdDM_drawVerts(DerivedMesh *dm)
  {
@@@ -881,7 -843,8 +881,8 @@@ static void cdDM_drawFacesTex(DerivedMe
        cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
  }
  
- static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs))
+ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs),
+                       int (*compareDrawOptions)(void *userData, int cur_index, int next_index))
  {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
        MVert *mv = cddm->mvert;
                                        MFace *mface= mf + actualFace;
                                        int drawSmooth= (mface->flag & ME_SMOOTH);
                                        int draw = 1;
+                                       int flush = 0;
  
                                        if(i != tottri-1)
                                                next_actualFace= dm->drawObject->triangle_to_mface[i+1];
                                        /* Goal is to draw as long of a contiguous triangle
                                           array as possible, so draw when we hit either an
                                           invisible triangle or at the end of the array */
-                                       if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
-                                               if(prevstart != i)
-                                                       /* Add one to the length (via `draw')
-                                                          if we're drawing at the end of the array */
-                                                       glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
+                                       /* flush buffer if current triangle isn't drawable or it's last triangle... */
+                                       flush= !draw || i == tottri - 1;
+                                       /* ... or when material setting is dissferent  */
+                                       flush|= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
+                                       if(!flush && compareDrawOptions) {
+                                               int next_orig= (index==NULL) ? next_actualFace : index[next_actualFace];
+                                               /* also compare draw options and flush buffer if they're different
+                                                  need for face selection highlight in edit mode */
+                                               flush|= compareDrawOptions(userData, orig, next_orig) == 0;
+                                       }
+                                       if(flush) {
+                                               int first= prevstart*3;
+                                               int count= (i-prevstart+(draw ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */
+                                               if(count)
+                                                       glDrawArrays(GL_TRIANGLES, first, count);
                                                prevstart = i + 1;
                                        }
                                }
@@@ -1573,8 -1554,6 +1592,8 @@@ static CDDerivedMesh *cdDM_create(cons
        dm->getFaceMap = cdDM_getFaceMap;
  
        dm->drawVerts = cdDM_drawVerts;
 +      // Jason
 +      dm->drawSelectedVerts = cdDM_drawSelectedVerts;
  
        dm->drawUVEdges = cdDM_drawUVEdges;
        dm->drawEdges = cdDM_drawEdges;
index cfe639578dc877bdf53f866cc34e5d56aec50136,eaaaa12eca17e9a540dbbb0ff67c05eaec6be896..960ab318dab9b32aca1dcd40a3c1efc50f3312e1
@@@ -1,6 -1,4 +1,4 @@@
  /*
-  * $Id$
-  *
   * ***** BEGIN GPL LICENSE BLOCK *****
   *
   * This program is free software; you can redistribute it and/or
@@@ -494,15 -492,32 +492,32 @@@ void ED_armature_apply_transform(Objec
        EditBone *ebone;
        bArmature *arm= ob->data;
        float scale = mat4_to_scale(mat);       /* store the scale of the matrix here to use on envelopes */
-       
+       float mat3[3][3];
+       copy_m3_m4(mat3, mat);
+       normalize_m3(mat3);
        /* Put the armature into editmode */
        ED_armature_to_edit(ob);
  
        /* Do the rotations */
-       for (ebone = arm->edbo->first; ebone; ebone=ebone->next){
+       for (ebone = arm->edbo->first; ebone; ebone=ebone->next) {
+               float   delta[3], tmat[3][3];
+               /* find the current bone's roll matrix */
+               sub_v3_v3v3(delta, ebone->tail, ebone->head);
+               vec_roll_to_mat3(delta, ebone->roll, tmat);
+               /* transform the roll matrix */
+               mul_m3_m3m3(tmat, mat3, tmat);
+               /* transform the bone */
                mul_m4_v3(mat, ebone->head);
                mul_m4_v3(mat, ebone->tail);
-               
+               /* apply the transfiormed roll back */
+               mat3_to_vec_roll(tmat, NULL, &ebone->roll);
                ebone->rad_head *= scale;
                ebone->rad_tail *= scale;
                ebone->dist             *= scale;
@@@ -2991,28 -3006,31 +3006,31 @@@ static void bones_merge(Object *obedit
        /* TODO, copy more things to the new bone */
        newbone->flag= start->flag & (BONE_HINGE|BONE_NO_DEFORM|BONE_NO_SCALE|BONE_NO_CYCLICOFFSET|BONE_NO_LOCAL_LOCATION|BONE_DONE);
        
-       /* step 2a: parent children of in-between bones to newbone */
-       for (chain= chains->first; chain; chain= chain->next) {
-               /* ick: we need to check if parent of each bone in chain is one of the bones in the */
-               short found= 0;
-               for (ebo= chain->data; ebo; ebo= ebo->parent) {
+       /* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge 
+        *      - potentially several tips for side chains leading to some tree exist...
+        */
+       for (chain = chains->first; chain; chain = chain->next) {
+               /* traverse down chain until we hit the bottom or if we run into the tip of the chain of bones we're 
+                * merging (need to stop in this case to avoid corrupting this chain too!) 
+                */
+               for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
+                       short found = 0;
                        
-                       /* try to find which bone from the list to be removed, is the parent */
-                       for (ebone= end; ebone; ebone= ebone->parent) {
-                               if (ebo->parent == ebone) {
-                                       found= 1;
+                       /* check if this bone is parented to one in the merging chain
+                        * ! WATCHIT: must only go check until end of checking chain
+                        */
+                       for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
+                               /* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
+                               if (ebone->parent == ebo) {
+                                       ebone->parent = newbone;
+                                       found = 1;
                                        break;
                                }
                        }
                        
-                       /* adjust this bone's parent to newbone then */
-                       if (found) {
-                               ebo->parent= newbone;
+                       /* carry on to the next tip now  */
+                       if (found) 
                                break;
-                       }
-               }
-               if (found) {
-                       break;
                }
        }
        
@@@ -3048,12 -3066,12 +3066,12 @@@ static int armature_merge_exec (bContex
                LinkData *chain, *nchain;
                EditBone *ebo;
                
+               armature_tag_select_mirrored(arm);
+               
                /* get chains (ends on chains) */
                chains_find_tips(arm->edbo, &chains);
                if (chains.first == NULL) return OPERATOR_CANCELLED;
-               armature_tag_select_mirrored(arm);
+               
                /* each 'chain' is the last bone in the chain (with no children) */
                for (chain= chains.first; chain; chain= nchain) {
                        EditBone *bstart= NULL, *bend= NULL;
                }               
                
                armature_tag_unselect(arm);
+               
                BLI_freelistN(&chains);
        }
        
@@@ -4258,69 -4276,28 +4276,69 @@@ static int bone_looper(Object *ob, Bon
        
        return count;
  }
 +// Jason
 +Bone* get_other_selected_bone(Object *ob) {
 +      Bone *bone;
 +      int i;
 +      bone = get_indexed_bone(ob, 0);
 +      for(i = 0; bone;){
 +              if(bone->flag & BONE_SELECTED) {
 +                      return bone;
 +              }
 +              i++;
 +              bone = get_indexed_bone(ob, i);
 +      }
  
 +      return NULL;
 +}
  /* called from editview.c, for mode-less pose selection */
  /* assumes scene obact and basact is still on old situation */
  int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short extend)
  {
        Object *ob= base->object;
        Bone *nearBone;
 -      
 +      // Jason
 +      Bone *new_act_bone;
 +
        if (!ob || !ob->pose) return 0;
  
        nearBone= get_bone_from_selectbuffer(scene, base, buffer, hits, 1);
 -      
 +
        /* if the bone cannot be affected, don't do anything */
        if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
                bArmature *arm= ob->data;
                
                /* since we do unified select, we don't shift+select a bone if the armature object was not active yet */
 -              if (!(extend) || (base != scene->basact)) {
 -                      ED_pose_deselectall(ob, 0);
 -                      nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
 -                      arm->act_bone= nearBone;
 -                      
 +              /* Jason was here, I'm doing a select for multibone painting */
 +              if ((base != scene->basact)) {//if (!(extend) || (base != scene->basact)) {
 +                      /* Jason was here */
 +                      /* only deselect all if they aren't using 'shift' */
 +                      if(!extend) {
 +                              ED_pose_deselectall(ob, 0);
 +                              nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
 +                              arm->act_bone= nearBone;
 +                              ED_vgroup_select_by_name(OBACT, nearBone->name);
 +                      }
 +                      else {
 +                              // Jason deselect this bone specifically if it is selected already
 +                              if (nearBone->flag & BONE_SELECTED) {
 +                                      nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
 +                                      if(nearBone == arm->act_bone) {
 +                                              // make a different bone the active one if it exists
 +                                              new_act_bone = get_other_selected_bone(ob);
 +                                              if(new_act_bone) {
 +                                                      new_act_bone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
 +                                                      arm->act_bone = new_act_bone;
 +                                                      ED_vgroup_select_by_name(OBACT, new_act_bone->name);
 +                                              }
 +                                      }
 +                              // or select the bone if they are using shift
 +                              } else {
 +                                      nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
 +                                      arm->act_bone= nearBone;
 +                              }
 +                      } 
 +                      DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
                                // XXX old cruft! use notifiers instead
                        //select_actionchannel_by_name(ob->action, nearBone->name, 1);
                }
@@@ -5084,10 -5061,6 +5102,10 @@@ void POSE_OT_select_inverse(wmOperatorT
  static int pose_de_select_all_exec(bContext *C, wmOperator *op)
  {
        int action = RNA_enum_get(op->ptr, "action");
 +      //Jason
 +      Object *ob = NULL;
 +      Scene *scene= CTX_data_scene(C);
 +      int multipaint = scene->toolsettings->multipaint;
  
        if (action == SEL_TOGGLE) {
                action= CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
        CTX_DATA_END;
  
        WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
 -      
 +      // Jason
 +      if(multipaint) {
 +              ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
 +              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      }
 +
        return OPERATOR_FINISHED;
  }
  
@@@ -5452,12 -5420,14 +5470,14 @@@ void ED_armature_bone_rename(bArmature 
                                ScrArea *sa;
                                /* add regions */
                                for(sa= screen->areabase.first; sa; sa= sa->next) {
-                                       SpaceLink *sl= sa->spacedata.first;
-                                       if(sl->spacetype == SPACE_VIEW3D) {
-                                               View3D *v3d= (View3D *)sl;
-                                               if(v3d->ob_centre && v3d->ob_centre->data == arm) {
-                                                       if (!strcmp(v3d->ob_centre_bone, oldname)) {
-                                                               BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
+                                       SpaceLink *sl;
+                                       for (sl= sa->spacedata.first; sl; sl= sl->next) {
+                                               if(sl->spacetype==SPACE_VIEW3D) {
+                                                       View3D *v3d= (View3D *)sl;
+                                                       if(v3d->ob_centre && v3d->ob_centre->data == arm) {
+                                                               if (!strcmp(v3d->ob_centre_bone, oldname)) {
+                                                                       BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
+                                                               }
                                                        }
                                                }
                                        }
index 62feeb151fa1b8e0064b3ec76c4395150e2b1faa,f8682d3935b273493fde1878d1fe70485a02e293..648d9cf4a8440a29e35bd41dfc5f7b90be54b14f
@@@ -215,9 -215,6 +215,9 @@@ void ED_view3d_project_float(struct ARe
  void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, struct rctf *viewborder_r, short do_shift);
  
  /* drawobject.c iterators */
 +/*Jason*/
 +void mesh_obmode_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct MVert *mv, int x, int y, int index), void *userData, int clipVerts);
 +
  void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts);
  void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts);
  void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct EditFace *efa, int x, int y, int index), void *userData);
@@@ -291,7 -288,7 +291,7 @@@ unsigned int ED_viewedit_datamask(struc
  int ED_view3d_camera_lock_check(struct View3D *v3d, struct RegionView3D *rv3d);
  /* copy the camera to the view before starting a view transformation */
  void ED_view3d_camera_lock_init(struct View3D *v3d, struct RegionView3D *rv3d);
- /* copy the view to the camera */
void ED_view3d_camera_lock_sync(struct View3D *v3d, struct RegionView3D *rv3d);
+ /* copy the view to the camera, return TRUE if */
int ED_view3d_camera_lock_sync(struct View3D *v3d, struct RegionView3D *rv3d);
  
  #endif /* ED_VIEW3D_H */
index e548e68d683d91f44518f21952a53b6a2d8da496,c308d36f838a6617b81b7c7d07971da54c66759a..0a4c6b638a3ac954474bce4b345d97dadd1b45e9
@@@ -116,6 -116,7 +116,7 @@@ void OBJECT_OT_armature_add(struct wmOp
  void OBJECT_OT_lamp_add(struct wmOperatorType *ot);
  void OBJECT_OT_effector_add(struct wmOperatorType *ot);
  void OBJECT_OT_camera_add(struct wmOperatorType *ot);
+ void OBJECT_OT_speaker_add(struct wmOperatorType *ot);
  void OBJECT_OT_group_instance_add(struct wmOperatorType *ot);
  
  void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot);
@@@ -199,12 -200,6 +200,12 @@@ void OBJECT_OT_vertex_group_copy(struc
  void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot);
  void OBJECT_OT_vertex_group_normalize_all(struct wmOperatorType *ot);
  void OBJECT_OT_vertex_group_levels(struct wmOperatorType *ot);
 +/* Jason was here */
 +void OBJECT_OT_vertex_group_lock_all(struct wmOperatorType *ot);
 +void OBJECT_OT_vertex_group_invert_locks(struct wmOperatorType *ot);
 +void OBJECT_OT_vertex_group_unlock_all(struct wmOperatorType *ot);
 +void OBJECT_OT_vertex_group_fix(struct wmOperatorType *ot);
 +
  void OBJECT_OT_vertex_group_invert(struct wmOperatorType *ot);
  void OBJECT_OT_vertex_group_blend(struct wmOperatorType *ot);
  void OBJECT_OT_vertex_group_clean(struct wmOperatorType *ot);
index ad08f08696c1cd2cbfab59d7ee40e91276f9796a,8f00f923b849d5de02e0eb821f94e8e3ac39a9f6..3e8c34b7395f9642a57a08bc98f40c5bd29830a9
@@@ -117,6 -117,7 +117,7 @@@ void ED_operatortypes_object(void
        WM_operatortype_append(OBJECT_OT_armature_add);
        WM_operatortype_append(OBJECT_OT_lamp_add);
        WM_operatortype_append(OBJECT_OT_camera_add);
+       WM_operatortype_append(OBJECT_OT_speaker_add);
        WM_operatortype_append(OBJECT_OT_add);
        WM_operatortype_append(OBJECT_OT_add_named);
        WM_operatortype_append(OBJECT_OT_effector_add);
        WM_operatortype_append(OBJECT_OT_vertex_group_copy);
        WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
        WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
 +      /* Jason was here */
 +      WM_operatortype_append(OBJECT_OT_vertex_group_invert_locks);
 +      WM_operatortype_append(OBJECT_OT_vertex_group_lock_all);
 +      WM_operatortype_append(OBJECT_OT_vertex_group_unlock_all);
 +      WM_operatortype_append(OBJECT_OT_vertex_group_fix);
 +
        WM_operatortype_append(OBJECT_OT_vertex_group_invert);
        WM_operatortype_append(OBJECT_OT_vertex_group_levels);
        WM_operatortype_append(OBJECT_OT_vertex_group_blend);
index 3c3d350377174dc784bb027bd28644e5c85e7b68,d69c1d9c4470f9c51e46ec31d19d30c65695edf8..226c71b05733ad70f16edbea0b1a23e40c7dedef
@@@ -512,7 -512,7 +512,7 @@@ static float VecZDepthOrtho(float pt[2]
        return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]);
  }
  
- static float VecZDepthPersp(float pt[2], float v1[3], float v2[3], float v3[3], float w[3])
+ static float VecZDepthPersp(float pt[2], float v1[4], float v2[4], float v3[4], float w[3])
  {
        float wtot_inv, wtot;
        float w_tmp[3];
@@@ -1193,7 -1193,7 +1193,7 @@@ static void screen_px_from_ortho
   * the perspective W coord for each vert */
  static void screen_px_from_persp(
                float uv[2],
-               float v1co[3], float v2co[3], float v3co[3], /* screenspace coords */
+               float v1co[4], float v2co[4], float v3co[4], /* screenspace coords */
                float uv1co[2], float uv2co[2], float uv3co[2],
                float pixelScreenCo[4],
                float w[3])
@@@ -5407,16 -5407,7 +5407,16 @@@ int facemask_paint_poll(bContext *C
  {
        return paint_facesel_test(CTX_data_active_object(C));
  }
 -
 +// Jason
 +int vert_paint_poll(bContext *C)
 +{
 +      return paint_vertsel_test(CTX_data_active_object(C));
 +}
 +// Jason
 +int mask_paint_poll(bContext *C)
 +{
 +      return paint_facesel_test(CTX_data_active_object(C)) || paint_vertsel_test(CTX_data_active_object(C));
 +}
  /* use project paint to re-apply an image */
  static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
  {
index 86826ffc7e189095eec8213b0a267f733dde4cd4,6e02ecbd5a866fed660736117a8949ce4e32fc75..b8d33de2e372877f49c8a5c6a0003c511dbd2b4c
@@@ -523,7 -523,7 +523,7 @@@ static void draw_mesh_text(Scene *scene
        if(ob->mode & OB_MODE_EDIT)
                return;
        else if(ob==OBACT)
 -              if(paint_facesel_test(ob))
 +              if(paint_facesel_test(ob) || paint_vertsel_test(ob))
                        return;
  
        ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
@@@ -607,7 -607,7 +607,7 @@@ void draw_mesh_textured(Scene *scene, V
        }
        else if(faceselect) {
                if(ob->mode & OB_MODE_WEIGHT_PAINT)
-                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1, GPU_enable_material);
+                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1, GPU_enable_material, NULL);
                else
                        dm->drawMappedFacesTex(dm, me->mface ? draw_tface_mapped__set_draw : NULL, me);
        }
index a2abe1c4a29eb06eb37e6c9b99669f7567c61cd7,d573198aa10e557c1b7865a3e63ac95403820097..459a07d03a47a2318ecaf14ebe5f727f3d91f3fd
@@@ -45,6 -45,7 +45,7 @@@
  #include "DNA_meta_types.h"
  #include "DNA_scene_types.h"
  #include "DNA_smoke_types.h"
+ #include "DNA_speaker_types.h"
  #include "DNA_world_types.h"
  #include "DNA_armature_types.h"
  
@@@ -1491,6 -1492,47 +1492,47 @@@ static void drawcamera(Scene *scene, Vi
        }
  }
  
+ /* flag similar to draw_object() */
+ static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), Object *UNUSED(ob), int UNUSED(flag))
+ {
+       //Speaker *spk = ob->data;
+       float vec[3];
+       int i, j;
+       glEnable(GL_BLEND);
+       for(j = 0; j < 3; j++) {
+               vec[2] = 0.25f * j -0.125f;
+               glBegin(GL_LINE_LOOP);
+               for(i = 0; i < 16; i++) {
+                       vec[0] = cosf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
+                       vec[1] = sinf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
+                       glVertex3fv(vec);
+               }
+               glEnd();
+       }
+       for(j = 0; j < 4; j++) {
+               vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
+               vec[1] = ((j % 2) * (j - 2)) * 0.5f;
+               glBegin(GL_LINE_STRIP);
+               for(i = 0; i < 3; i++) {
+                       if(i == 1) {
+                               vec[0] *= 0.5f;
+                               vec[1] *= 0.5f;
+                       }
+                       vec[2] = 0.25f * i -0.125f;
+                       glVertex3fv(vec);
+               }
+               glEnd();
+       }
+       glDisable(GL_BLEND);
+ }
  static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
  {
        BPoint *bp = lt->def;
@@@ -1670,45 -1712,7 +1712,45 @@@ void mesh_foreachScreenVert(ViewContex
  
        dm->release(dm);
  }
 +/*Jason */
 +static void mesh_obmode_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
 +{
 +      struct { void (*func)(void *userData, MVert *mv, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
 +      Mesh *me = data->vc.obact->data;
 +      MVert *mv = me->mvert+index;
 +      //MVert *dmv = CDDM_get_verts(data->vc.obact->derivedFinal)+index;
 +      //MVert *mv = CDDM_get_verts(data->vc.obact->derivedFinal)+index;
 +      if ((mv->flag & ME_HIDE)==0) {
 +              short s[2]= {IS_CLIPPED, 0};
 +
 +              if (data->clipVerts) {
 +                      view3d_project_short_clip(data->vc.ar, co, s, 1);
 +              } else {
 +                      view3d_project_short_noclip(data->vc.ar, co, s);
 +              }
  
 +              if (s[0]!=IS_CLIPPED)
 +                      data->func(data->userData, mv, s[0], s[1], index);
 +      }
 +}
 +/*Jason*/
 +void mesh_obmode_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, MVert *mv, int x, int y, int index), void *userData, int clipVerts)
 +{
 +      struct { void (*func)(void *userData, MVert *mv, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
 +      DerivedMesh *dm = mesh_get_derived_final(vc->scene, vc->obact, CD_MASK_BAREMESH);
 +
 +      data.vc= *vc;
 +      data.func = func;
 +      data.userData = userData;
 +      data.clipVerts = clipVerts;
 +      
 +      if(clipVerts)
 +              ED_view3d_local_clipping(vc->rv3d, vc->obact->obmat); /* for local clipping lookups */
 +
 +      dm->foreachMappedVert(dm, mesh_obmode_foreachScreenVert__mapFunc, &data);
 +
 +      dm->release(dm);
 +}
  static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
  {
        struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
@@@ -2068,6 -2072,28 +2110,28 @@@ static int draw_dm_faces_sel__setDrawOp
        return 0;
  }
  
+ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
+ {
+       struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
+       EditFace *efa = EM_get_face_for_index(index);
+       EditFace *next_efa = EM_get_face_for_index(next_index);
+       unsigned char *col, *next_col;
+       if(efa == next_efa)
+               return 1;
+       if(efa == data->efa_act || next_efa == data->efa_act)
+               return 0;
+       col = data->cols[(efa->f&SELECT)?1:0];
+       next_col = data->cols[(next_efa->f&SELECT)?1:0];
+       if(col[3]==0 || next_col[3]==0)
+               return 0;
+       return col == next_col;
+ }
  /* also draws the active face */
  static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
  {
        data.cols[2] = actCol;
        data.efa_act = efa_act;
  
-       dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
+       dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
  }
  
  static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
@@@ -2487,7 -2513,7 +2551,7 @@@ static void draw_em_fancy(Scene *scene
                        glEnable(GL_LIGHTING);
                        glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
  
-                       finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material);
+                       finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
  
                        glFrontFace(GL_CCW);
                        glDisable(GL_LIGHTING);
@@@ -2716,7 -2742,7 +2780,7 @@@ static void draw_mesh_fancy(Scene *scen
                        /* weight paint in solid mode, special case. focus on making the weights clear
                         * rather than the shading, this is also forced in wire view */
                        GPU_enable_material(0, NULL);
-                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
+                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
                
                        bglPolygonOffset(rv3d->dist, 1.0);
                        glDepthMask(0); // disable write in zbuffer, selected edge wires show better
                                glEnable(GL_LIGHTING);
                                glEnable(GL_COLOR_MATERIAL);
  
-                               dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
+                               dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
                                glDisable(GL_COLOR_MATERIAL);
                                glDisable(GL_LIGHTING);
  
                        }
                        else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
                                if(me->mcol)
-                                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
+                                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material, NULL);
                                else {
                                        glColor3f(1.0f, 1.0f, 1.0f);
-                                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
+                                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material, NULL);
                                }
                        }
                }
        }
+       
        /* set default draw color back for wire or for draw-extra later on */
        if (dt!=OB_WIRE) {
                if(base->flag & SELECT) {
                        bglPolygonOffset(rv3d->dist, 0.0);
                }
        }
 -
 +      // Jason
 +      if(paint_vertsel_test(ob) && dm->drawSelectedVerts) {
 +              glColor3f(0.0f, 0.0f, 0.0f);
 +              glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
 +              dm->drawSelectedVerts(dm);
 +              glPointSize(1.0f);
 +      }
        dm->release(dm);
  }
  
@@@ -2887,7 -2908,18 +2952,18 @@@ static int draw_mesh_object(Scene *scen
        Object *obedit= scene->obedit;
        Mesh *me= ob->data;
        EditMesh *em= me->edit_mesh;
-       int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
+       int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
+       /* If we are drawing shadows and any of the materials don't cast a shadow,
+        * then don't draw the object */
+       if (v3d->flag2 & V3D_RENDER_SHADOW) {
+               for(i=0; i<ob->totcol; ++i) {
+                       Material *ma= give_current_material(ob, i);
+                       if (ma && !(ma->mode & MA_SHADBUF)) {
+                               return 1;
+                       }
+               }
+       }
        
        if(obedit && ob!=obedit && ob->data==obedit->data) {
                if(ob_get_key(ob) || ob_get_key(obedit));
@@@ -5815,6 -5847,7 +5891,7 @@@ void draw_object(Scene *scene, ARegion 
                else {
  
                        if(ob->type==OB_LAMP) UI_ThemeColor(TH_LAMP);
+                       else if(ob->type==OB_SPEAKER) UI_ThemeColor(TH_SPEAKER);
                        else UI_ThemeColor(TH_WIRE);
  
                        if((scene->basact)==base) {
                        if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0 || (rv3d->persp==RV3D_CAMOB && v3d->camera==ob)) /* special exception for active camera */
                                drawcamera(scene, v3d, rv3d, ob, flag);
                        break;
+               case OB_SPEAKER:
+                       if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
+                               drawspeaker(scene, v3d, rv3d, ob, flag);
+                       break;
                case OB_LATTICE:
                        if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) {
                                drawlattice(scene, v3d, ob);
        }
  
        /* draw code for smoke */
-       if((md = modifiers_findByType(ob, eModifierType_Smoke)))
-       {
+       if((md = modifiers_findByType(ob, eModifierType_Smoke))) {
                SmokeModifierData *smd = (SmokeModifierData *)md;
  
                // draw collision objects
  }
  
  /* ***************** BACKBUF SEL (BBS) ********* */
 +/* Jason */
 +static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
 +{
 +      // TODO: support hidden vertices
 +      int offset = (intptr_t) userData;
 +      //EditVert *eve = EM_get_vert_for_index(index);
 +
 +      //if (eve->h==0) {
 +      WM_set_framebuffer_index_color(offset+index);
 +      bglVertex3fv(co);
 +      //}
 +}
 +/* Jason */
 +static void bbs_obmode_mesh_verts(Scene* scene, Object *ob, DerivedMesh *dm, int offset)
 +{
 +      Mesh *me = (Mesh*)ob->data;
 +
 +      glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
 +      bglBegin(GL_POINTS);
 +      dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, (void*)(intptr_t) offset);
 +      bglEnd();
 +      glPointSize(1.0);
 +}
  
  static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
  {
@@@ -6515,7 -6528,7 +6595,7 @@@ static void bbs_mesh_solid_EM(Scene *sc
        cpack(0);
  
        if (facecol) {
-               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0, GPU_enable_material);
+               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0, GPU_enable_material, NULL);
  
                if(check_ob_drawface_dot(scene, v3d, ob->dt)) {
                        glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
                }
  
        } else {
-               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0, GPU_enable_material);
+               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0, GPU_enable_material, NULL);
        }
  }
  
@@@ -6547,18 -6560,7 +6627,18 @@@ static int bbs_mesh_solid_hide__setDraw
                return 0;
        }
  }
 +/* Jason */
 +// must have called WM_set_framebuffer_index_color beforehand
 +static int bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
 +{
 +      Mesh *me = userData;
  
 +      if (!(me->mface[index].flag&ME_HIDE)) {
 +              return 1;
 +      } else {
 +              return 0;
 +      }
 +}
  static void bbs_mesh_solid(Scene *scene, Object *ob)
  {
        DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
        
        glColor3ub(0, 0, 0);
                
-       if((me->editflag & ME_EDIT_PAINT_MASK)) dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, me, 0, GPU_enable_material);
-       else                                                                    dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0, GPU_enable_material);
+       if((me->editflag & ME_EDIT_PAINT_MASK)) dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, me, 0, GPU_enable_material, NULL);
+       else                                                                    dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0, GPU_enable_material, NULL);
  
        dm->release(dm);
  }
@@@ -6583,7 -6585,6 +6663,6 @@@ void draw_object_backbufsel(Scene *scen
  
        switch( ob->type) {
        case OB_MESH:
-       {
                if(ob->mode & OB_MODE_EDIT) {
                        Mesh *me= ob->data;
                        EditMesh *em= me->edit_mesh;
                        EM_free_index_arrays();
                }
                else {
 -                      bbs_mesh_solid(scene, ob);
 +                      Mesh *me= ob->data;
 +                      if(me->editflag & ME_EDIT_VERT_SEL) {
 +                              DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
 +                              WM_set_framebuffer_index_color(me->totvert+2);
 +                              glColor3ub(0, 0, 0);
 +
-                               dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, me, 0, GPU_enable_material);
++                              dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, me, 0, GPU_enable_material, NULL);
 +
 +                              
 +                              bbs_obmode_mesh_verts(scene, ob, dm, 1);
 +                              em_vertoffs = me->totvert+1;
 +                              dm->release(dm);
 +                      }
-                       else bbs_mesh_solid(scene, ob);
++                      else {
++                              bbs_mesh_solid(scene, ob);
++                      }
                }
-               
-       }
                break;
        case OB_CURVE:
        case OB_SURF:
@@@ -6690,7 -6676,7 +6769,7 @@@ static void draw_object_mesh_instance(S
                        GPU_end_object_materials();
                }
                else if(edm)
-                       edm->drawMappedFaces(edm, NULL, NULL, 0, GPU_enable_material);
+                       edm->drawMappedFaces(edm, NULL, NULL, 0, GPU_enable_material, NULL);
                
                glDisable(GL_LIGHTING);
        }
index fb69df258b52dfd518a992e744a1a94ddc695e22,65914ead899de7a511965209277c422acab1d89c..926678ab12352d58e577d1cfafa73e86469283db
  #include "BLI_linklist.h"
  #include "BLI_utildefines.h"
  
 +// Jason--vertex box select
 +#include "IMB_imbuf_types.h"
 +#include "IMB_imbuf.h"
 +#include "BKE_global.h"
 +
  #include "BKE_context.h"
  #include "BKE_paint.h"
  #include "BKE_armature.h"
@@@ -202,22 -197,6 +202,22 @@@ static void EM_backbuf_checkAndSelectFa
                }
        }
  }
 +/* Jason */
 +static void EM_backbuf_checkAndSelectTVerts(Mesh *me, int select)
 +{
 +      MVert *mv = me->mvert;
 +      int a;
 +
 +      if (mv) {
 +              for(a=1; a<=me->totvert; a++, mv++) {
 +                      if(EM_check_backbuf(a)) {
 +                              if(!(mv->flag & ME_HIDE)) {
 +                                      mv->flag = select?(mv->flag|SELECT):(mv->flag&~SELECT);
 +                              }
 +                      }
 +              }
 +      }
 +}
  
  static void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
  {
@@@ -252,7 -231,7 +252,7 @@@ static int view3d_selectable_data(bCont
                        if (ob->mode & OB_MODE_SCULPT) {
                                return 0;
                        }
 -                      if (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT) && !paint_facesel_test(ob)) {
 +                      if (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT) && !paint_facesel_test(ob) && !paint_vertsel_test(ob)) {//Jason
                                return 0;
                        }
                }
@@@ -646,6 -625,7 +646,6 @@@ static void do_lasso_select_curve(ViewC
        ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
        nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data);
  }
 -
  static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x, int y)
  {
        struct { int (*mcords)[2]; short moves; short select; } *data = userData;
@@@ -746,89 -726,7 +746,89 @@@ static void do_lasso_select_meta(ViewCo
                }
        }
  }
 +/* Jason */
 +int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend)
 +{
 +      Mesh *me;
 +      MVert *mvert;
 +      struct ImBuf *ibuf;
 +      unsigned int *rt;
 +      int a, index;
 +      char *selar;
 +      int sx= rect->xmax-rect->xmin+1;
 +      int sy= rect->ymax-rect->ymin+1;
 +
 +      me= vc->obact->data;
 +
 +      if(me==NULL || me->totvert==0 || sx*sy <= 0)
 +              return OPERATOR_CANCELLED;
 +
 +      selar= MEM_callocN(me->totvert+1, "selar");
 +
 +      if (extend == 0 && select)
 +              paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
 +
 +      view3d_validate_backbuf(vc);
 +
 +      ibuf = IMB_allocImBuf(sx,sy,32,IB_rect);
 +      rt = ibuf->rect;
 +      glReadPixels(rect->xmin+vc->ar->winrct.xmin,  rect->ymin+vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
 +      if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
 +
 +      a= sx*sy;
 +      while(a--) {
 +              if(*rt) {
 +                      index= WM_framebuffer_to_index(*rt);
 +                      if(index<=me->totvert) selar[index]= 1;
 +              }
 +              rt++;
 +      }
 +
 +      mvert= me->mvert;
 +      for(a=1; a<=me->totvert; a++, mvert++) {
 +              if(selar[a]) {
 +                      if(mvert->flag & ME_HIDE);
 +                      else {
 +                              if(select) mvert->flag |= SELECT;
 +                              else mvert->flag &= ~SELECT;
 +                      }
 +              }
 +      }
 +
 +      IMB_freeImBuf(ibuf);
 +      MEM_freeN(selar);
 +
 +#ifdef __APPLE__      
 +      glReadBuffer(GL_BACK);
 +#endif
 +
 +      paintvert_flush_flags(vc->obact);
 +
 +      return OPERATOR_FINISHED;
 +}
 +/* Jason */
 +static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
 +{
 +      Object *ob= vc->obact;
 +      Mesh *me= ob?ob->data:NULL;
 +      rcti rect;
 +
 +      if(me==NULL || me->totvert==0)
 +              return;
 +
 +      if(extend==0 && select)
 +              paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
 +      em_vertoffs= me->totvert+1;     /* max index array */
 +
 +      lasso_select_boundbox(&rect, mcords, moves);
 +      EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
  
 +      EM_backbuf_checkAndSelectTVerts(me, select);
 +
 +      EM_free_backbuf();
 +
 +      paintvert_flush_flags(ob);
 +}
  static void do_lasso_select_paintface(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
  {
        Object *ob= vc->obact;
@@@ -891,8 -789,6 +891,8 @@@ static void view3d_lasso_select(bContex
        if(vc->obedit==NULL) { /* Object Mode */
                if(paint_facesel_test(ob))
                        do_lasso_select_paintface(vc, mcords, moves, extend, select);
 +              else if(paint_vertsel_test(ob))
 +                      do_lasso_select_paintvert(vc, mcords, moves, extend, select);
                else if(ob && ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))
                        ;
                else if(ob && ob->mode & OB_MODE_PARTICLE_EDIT)
@@@ -1335,8 -1231,8 +1335,8 @@@ static int mouse_select(bContext *C, co
        if(BASACT && BASACT->next) startbase= BASACT->next;
        
        /* This block uses the control key to make the object selected by its center point rather than its contents */
-       /* XXX later on, in editmode do not activate */
-       if(vc.obedit==NULL && obcenter) {
+       /* in editmode do not activate */
+       if(obcenter) {
                
                /* note; shift+alt goes to group-flush-selecting */
                if(enumerate) {
@@@ -1869,9 -1765,15 +1869,15 @@@ static int view3d_borderselect_exec(bCo
                case OB_CURVE:
                case OB_SURF:
                        ret= do_nurbs_box_select(&vc, &rect, select, extend);
+                       if(ret & OPERATOR_FINISHED) {
+                               WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
+                       }
                        break;
                case OB_MBALL:
                        ret= do_meta_box_select(&vc, &rect, select, extend);
+                       if(ret & OPERATOR_FINISHED) {
+                               WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
+                       }
                        break;
                case OB_ARMATURE:
                        ret= do_armature_box_select(&vc, &rect, select, extend);
                else if(vc.obact && paint_facesel_test(vc.obact)) {
                        ret= do_paintface_box_select(&vc, &rect, select, extend);
                }
 +              else if(vc.obact && paint_vertsel_test(vc.obact)) {
 +                      ret= do_paintvert_box_select(&vc, &rect, select, extend);
 +              }
                else if(vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
                        ret= PE_border_select(C, &rect, select, extend);
                }
@@@ -1934,57 -1833,6 +1940,57 @@@ void VIEW3D_OT_select_border(wmOperator
        /* rna */
        WM_operator_properties_gesture_border(ot, TRUE);
  }
 +/*Jason*/
 +/* much like facesel_face_pick()*/
 +/* returns 0 if not found, otherwise 1 */
 +static int vertsel_vert_pick(struct bContext *C, Mesh *me, const int mval[2], unsigned int *index, short rect)
 +{
 +      ViewContext vc;
 +      view3d_set_viewcontext(C, &vc);
 +
 +      if (!me || me->totvert==0)
 +              return 0;
 +
 +      if (rect) {
 +              /* sample rect to increase changes of selecting, so that when clicking
 +                 on an face in the backbuf, we can still select a vert */
 +
 +              int dist;
 +              *index = view3d_sample_backbuf_rect(&vc, mval, 3, 1, me->totvert+1, &dist,0,NULL, NULL);
 +      }
 +      else {
 +              /* sample only on the exact position */
 +              *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
 +      }
 +
 +      if ((*index)<=0 || (*index)>(unsigned int)me->totvert)
 +              return 0;
 +
 +      (*index)--;
 +      
 +      return 1;
 +}
 +/* Jason */
 +/* mouse selection in weight paint */
 +/* gets called via generic mouse select operator */
 +int mouse_wp_select(bContext *C, const int mval[2], short extend, Object *obact, Mesh* me)
 +{
 +      unsigned int index = 0;
 +      MVert *mv;
 +      if(vertsel_vert_pick(C, me, mval, &index, 1)) {
 +              mv = me->mvert+index;
 +              if(extend) {
 +                      mv->flag ^= 1;
 +              } else {
 +                      paintvert_deselect_all_visible(obact, SEL_DESELECT, FALSE);
 +                      mv->flag |= 1;
 +              }
 +              paintvert_flush_flags(obact);
 +              WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obact->data);
 +              return 1;
 +      }
 +      return 0;
 +}
  
  /* ****** Mouse Select ****** */
  
@@@ -1996,14 -1844,22 +2002,25 @@@ static int view3d_select_invoke(bContex
        short extend= RNA_boolean_get(op->ptr, "extend");
        short center= RNA_boolean_get(op->ptr, "center");
        short enumerate= RNA_boolean_get(op->ptr, "enumerate");
+       short object= RNA_boolean_get(op->ptr, "object");
        int     retval = 0;
 +      // Jason
 +      Mesh *me;
 +      Scene *scene = CTX_data_scene(C);
  
        view3d_operator_needs_opengl(C);
  
-       if(obedit && center==FALSE) {
+       if(object) {
+               obedit= NULL;
+               obact= NULL;
+               /* ack, this is incorrect but to do this correctly we would need an
+                * alternative editmode/objectmode keymap, this copies the functionality
+                * from 2.4x where Ctrl+Select in editmode does object select only */
+               center= FALSE;
+       }
+       if(obedit && object==FALSE) {
                if(obedit->type==OB_MESH)
                        retval = mouse_mesh(C, event->mval, extend);
                else if(obedit->type==OB_ARMATURE)
                return PE_mouse_particles(C, event->mval, extend);
        else if(obact && paint_facesel_test(obact))
                retval = paintface_mouse_select(C, obact, event->mval, extend);
 -      else
 +      /*Jason*/
 +      else if (paint_vertsel_test(obact) && (me = (Mesh*)(obact->data))) {
 +              retval = mouse_wp_select(C, event->mval, extend, obact, me);
 +      } else {
                retval = mouse_select(C, event->mval, extend, center, enumerate);
 +      }
  
        /* passthrough allows tweaks
         * FINISHED to signal one operator worked
@@@ -2056,6 -1908,7 +2073,7 @@@ void VIEW3D_OT_select(wmOperatorType *o
        RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first.");
        RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting, in editmode used to extend object selection.");
        RNA_def_boolean(ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only).");
+       RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (editmode only).");
  }
  
  
@@@ -2071,7 -1924,6 +2089,7 @@@ static void mesh_circle_doSelectVert(vo
                eve->f = data->select?(eve->f|1):(eve->f&~1);
        }
  }
 +
  static void mesh_circle_doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
  {
        struct {ViewContext *vc; short select; int mval[2]; float radius; } *data = userData;
@@@ -2151,24 -2003,6 +2169,24 @@@ static void paint_facesel_circle_select
        }
  }
  
 +/* Jason */
 +static void paint_vertsel_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
 +{
 +      Object *ob= vc->obact;
 +      Mesh *me = ob?ob->data:NULL;
 +      int bbsel;
 +      struct {ViewContext *vc; short select; int mval[2]; float radius; } data = {NULL};
 +      if (me) {
 +              em_vertoffs= me->totvert+1;     /* max index array */
 +
 +              bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
 +              EM_backbuf_checkAndSelectTVerts(me, select==LEFTMOUSE);
 +              EM_free_backbuf();
 +
 +              paintvert_flush_flags(ob);
 +      }
 +}
 +
  
  static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
  {
@@@ -2423,8 -2257,8 +2441,8 @@@ static int view3d_circle_select_exec(bC
        int select;
        
        select= (gesture_mode==GESTURE_MODAL_SELECT);
 -
 -      if( CTX_data_edit_object(C) || paint_facesel_test(obact) ||
 +                                                                                                                              // Jason
 +      if( CTX_data_edit_object(C) || paint_facesel_test(obact) || paint_vertsel_test(obact) ||
                (obact && (obact->mode & (OB_MODE_PARTICLE_EDIT|OB_MODE_POSE))) )
        {
                ViewContext vc;
                else if(paint_facesel_test(obact)) {
                        paint_facesel_circle_select(&vc, select, mval, (float)radius);
                        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obact->data);
 +              }/* Jason */
 +              else if(paint_vertsel_test(obact)) {
 +                      paint_vertsel_circle_select(&vc, select, mval, (float)radius);
 +                      WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obact->data);
                }
                else if(obact->mode & OB_MODE_POSE)
                        pose_circle_select(&vc, select, mval, (float)radius);
index b1b3e779824946261ec337273c5568eddbb36213,ffa82092ef10f5b1ee2366f526f5aef1e0da5dd7..820b244ca6cecf7448860cade7cb09ac89f58fe1
@@@ -62,8 -62,6 +62,8 @@@ struct bGPdata
  typedef struct bDeformGroup {
        struct bDeformGroup *next, *prev;
        char name[32];
 +      /* Jason was here: need this flag for locking weights */
 +      char flag, pad[7];
  } bDeformGroup;
  #define MAX_VGROUP_NAME 32
  
@@@ -308,6 -306,8 +308,8 @@@ typedef struct DupliObject 
  #define OB_LAMP                       10
  #define OB_CAMERA             11
  
+ #define OB_SPEAKER            12
  // #define OB_WAVE                    21
  #define OB_LATTICE            22
  
index dcf646532c49b822b89d601052499f3f0d870d8e,be2a78ac774a9b581e051606ead17536cfa0e985..bc50c710d76bcb19db927a7d4c19ee9df38641dd
@@@ -126,6 -126,8 +126,8 @@@ typedef struct FFMpegCodecData 
        int video_bitrate;
        int audio_bitrate;
        int audio_mixrate;
+       int audio_channels;
+       int audio_pad;
        float audio_volume;
        int gop_size;
        int flags;
@@@ -147,6 -149,8 +149,8 @@@ typedef struct AudioData 
        int distance_model;
        short flag;
        short pad;
+       float volume;
+       float pad2;
  } AudioData;
  
  typedef struct SceneRenderLayer {
@@@ -475,6 -479,7 +479,7 @@@ typedef struct GameData 
  #define WOPHY_BULLET  5
  
  /* GameData.flag */
+ #define GAME_RESTRICT_ANIM_UPDATES                    (1 << 0)
  #define GAME_ENABLE_ALL_FRAMES                                (1 << 1)
  #define GAME_SHOW_DEBUG_PROPS                         (1 << 2)
  #define GAME_SHOW_FRAMERATE                                   (1 << 3)
  #define GAME_ENABLE_ANIMATION_RECORD          (1 << 13)
  #define GAME_SHOW_MOUSE                                               (1 << 14)
  #define GAME_GLSL_NO_COLOR_MANAGEMENT         (1 << 15)
+ /* Note: GameData.flag is a short (max 16 flags). To add more flags, GameData.flag needs to be an int */
  
  /* GameData.matmode */
  #define GAME_MAT_TEXFACE      0
@@@ -726,13 -732,10 +732,13 @@@ typedef struct ToolSettings 
        short snap_flag, snap_target;
        short proportional, prop_mode;
        char proportional_objects; /* proportional edit, object mode */
 -      char pad[3];
 +      char pad[7];
  
        int auto_normalize; /*auto normalizing mode in wpaint*/
  
 +      //Jason
 +      int multipaint; /* paint multiple bones in wpaint */
 +
        short sculpt_paint_settings; /* user preferences for sculpt and paint */
        short pad1;
        int sculpt_paint_unified_size; /* unified radius of brush in pixels */
@@@ -805,6 -808,7 +811,7 @@@ typedef struct Scene 
        void *sound_scene;
        void *sound_scene_handle;
        void *sound_scrub_handle;
+       void *speaker_handles;
        
        void *fps_info;                                 /* (runtime) info/cache used for presenting playback framerate info to the user */
        
  #define F_DUPLI                       3
  
  /* audio->flag */
- #define AUDIO_MUTE            1
- #define AUDIO_SYNC            2
- #define AUDIO_SCRUB           4
+ #define AUDIO_MUTE                (1<<0)
+ #define AUDIO_SYNC                (1<<1)
+ #define AUDIO_SCRUB                     (1<<2)
+ #define AUDIO_VOLUME_ANIMATED     (1<<3)
  
  #define FFMPEG_MULTIPLEX_AUDIO  1 /* deprecated, you can choose none as audiocodec now */
  #define FFMPEG_AUTOSPLIT_OUTPUT 2
index 14262184988eb4d3aace824e0d58645aef848acf,9e98f166875969ed7f7c3154ebd830321fcfc990..cd395a4bbd8404e201c12d0cc47aa18649e410f3
@@@ -168,6 -168,7 +168,7 @@@ void RNA_def_sensor(struct BlenderRNA *
  void RNA_def_sequencer(struct BlenderRNA *brna);
  void RNA_def_smoke(struct BlenderRNA *brna);
  void RNA_def_space(struct BlenderRNA *brna);
+ void RNA_def_speaker(struct BlenderRNA *brna);
  void RNA_def_test(struct BlenderRNA *brna);
  void RNA_def_text(struct BlenderRNA *brna);
  void RNA_def_texture(struct BlenderRNA *brna);
@@@ -214,8 -215,6 +215,8 @@@ int rna_object_shapekey_index_set(struc
  void rna_Object_internal_update_data(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
  void rna_Mesh_update_draw(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
  void rna_TextureSlot_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
 +//Jason
 +void rna_update_active_object(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
  
  /* basic poll functions for object types */
  int rna_Armature_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
@@@ -262,6 -261,7 +263,7 @@@ void RNA_api_wm(struct StructRNA *srna)
  void RNA_api_sensor(struct StructRNA *srna);
  void RNA_api_controller(struct StructRNA *srna);
  void RNA_api_actuator(struct StructRNA *srna);
+ void RNA_api_environment_map(struct StructRNA *srna);
  
  /* main collection functions */
  void RNA_def_main_cameras(BlenderRNA *brna, PropertyRNA *cprop);
@@@ -284,6 -284,7 +286,7 @@@ void RNA_def_main_brushes(BlenderRNA *b
  void RNA_def_main_worlds(BlenderRNA *brna, PropertyRNA *cprop);
  void RNA_def_main_groups(BlenderRNA *brna, PropertyRNA *cprop);
  void RNA_def_main_texts(BlenderRNA *brna, PropertyRNA *cprop);
+ void RNA_def_main_speakers(BlenderRNA *brna, PropertyRNA *cprop);
  void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop);
  void RNA_def_main_armatures(BlenderRNA *brna, PropertyRNA *cprop);
  void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop);
index d7440ad9ddb5bb1ddfc73e87c628336c96c5a86e,ad323b0aba448cf17d12e55637c7697e1952b7af..f043249d36cbf3e64a3dbbfb692ad796b2b1ada2
@@@ -115,6 -115,7 +115,7 @@@ EnumPropertyItem object_type_items[] = 
        {0, "", 0, NULL, NULL},
        {OB_CAMERA, "CAMERA", 0, "Camera", ""},
        {OB_LAMP, "LAMP", 0, "Lamp", ""},
+       {OB_SPEAKER, "SPEAKER", 0, "Speaker", ""},
        {0, NULL, 0, NULL, NULL}};
  
  EnumPropertyItem object_type_curve_items[] = {
@@@ -218,16 -219,6 +219,16 @@@ void rna_Object_internal_update_data(Ma
        DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
        WM_main_add_notifier(NC_OBJECT|ND_DRAW, ptr->id.data);
  }
 +// Jason
 +void rna_update_active_object(Main *bmain, Scene *scene, PointerRNA *ptr)
 +{
 +      Object *ob;
 +      Base *basact = scene->basact;
 +      if(basact && (ob = basact->object)) {
 +              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              WM_main_add_notifier(NC_OBJECT|ND_DRAW, &ob->id);
 +      }
 +}
  
  void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
  {
@@@ -375,6 -366,7 +376,7 @@@ static StructRNA *rna_Object_data_typef
                case OB_CAMERA: return &RNA_Camera;
                case OB_LATTICE: return &RNA_Lattice;
                case OB_ARMATURE: return &RNA_Armature;
+               case OB_SPEAKER: return &RNA_Speaker;
                default: return &RNA_ID;
        }
  }
@@@ -1266,11 -1258,6 +1268,11 @@@ static void rna_def_vertex_group(Blende
        RNA_def_struct_name_property(srna, prop);
        RNA_def_property_string_funcs(prop, NULL, NULL, "rna_VertexGroup_name_set");
        RNA_def_property_update(prop, NC_GEOM|ND_DATA|NA_RENAME, "rna_Object_internal_update_data"); /* update data because modifiers may use [#24761] */
 +      /* Jason was here */
 +      prop= RNA_def_property(srna, "flag", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_ui_text(prop, "", "Maintain the relative weights for the group");
 +      RNA_def_property_boolean_sdna(prop, "bDeformGroup", "flag", 0);
 +      RNA_def_property_update(prop, NC_GEOM|ND_DATA|NA_RENAME, "rna_Object_internal_update_data"); /* update data because modifiers may use [#24761] */
  
        prop= RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
index 5d191b07059084263bcaaab14c59958ffde788c0,cc1e7d9390b3923c944eda069c494a9325dd2071..1c5fe02e1f1a5b468408fd2d3e1ea16fa2acc956
@@@ -46,7 -46,7 +46,7 @@@
  #ifdef WITH_QUICKTIME
  #include "quicktime_export.h"
  #  ifdef WITH_AUDASPACE
- #    include "AUD_C-API.h"
+ #    include "AUD_Space.h"
  #  endif
  #endif
  
@@@ -155,6 -155,12 +155,12 @@@ EnumPropertyItem image_type_items[] = 
  #endif
        {0, NULL, 0, NULL, NULL}};
  
+ EnumPropertyItem image_color_mode_items[] ={
+       {R_PLANESBW, "BW", 0, "BW", "Images get saved in 8 bits grayscale (only PNG, JPEG, TGA, TIF)"},
+       {R_PLANES24, "RGB", 0, "RGB", "Images are saved with RGB (color) data"},
+       {R_PLANES32, "RGBA", 0, "RGBA", "Images are saved with RGB and Alpha data (if supported)"},
+       {0, NULL, 0, NULL, NULL}};
  #ifdef RNA_RUNTIME
  
  #include "DNA_anim_types.h"
  #include "BKE_mesh.h"
  #include "BKE_sound.h"
  #include "BKE_screen.h"
+ #include "BKE_sequencer.h"
  #include "BKE_animsys.h"
  
  #include "WM_api.h"
@@@ -332,6 -339,26 +339,26 @@@ static void rna_Scene_layer_update(Mai
        DAG_on_visible_update(bmain, FALSE);
  }
  
+ static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+ {
+       sound_update_fps(scene);
+       seq_update_sound_bounds_all(scene);
+ }
+ static void rna_Scene_listener_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+ {
+       sound_update_scene_listener(scene);
+ }
+ static void rna_Scene_volume_set(PointerRNA *ptr, float value)
+ {
+       Scene *scene= (Scene*)(ptr->data);
+       scene->audio.volume = value;
+       if(scene->sound_scene)
+               sound_set_scene_volume(scene, value);
+ }
  static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
  {     
        scene->r.framelen= (float)scene->r.framapto/(float)scene->r.images;
@@@ -700,8 -727,8 +727,8 @@@ static void rna_RenderSettings_active_l
  {
        RenderData *rd= (RenderData*)ptr->data;
        SceneRenderLayer *srl= (SceneRenderLayer*)value.data;
-       
-       rd->actlay = BLI_findindex(&rd->layers, srl);
+       const int index= BLI_findindex(&rd->layers, srl);
+       if (index != -1) rd->actlay= index;
  }
  
  static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value)
@@@ -991,9 -1018,8 +1018,8 @@@ static TimeMarker *rna_TimeLine_add(Sce
  
  static void rna_TimeLine_remove(Scene *scene, ReportList *reports, TimeMarker *marker)
  {
-       /* try to remove the F-Curve from the action */
        if (!BLI_remlink_safe(&scene->markers, marker)) {
-               BKE_reportf(reports, RPT_ERROR, "TimelineMarker '%s' not found in action '%s'", marker->name, scene->id.name+2);
+               BKE_reportf(reports, RPT_ERROR, "TimelineMarker '%s' not found in scene '%s'", marker->name, scene->id.name+2);
                return;
        }
  
@@@ -1051,10 -1077,14 +1077,14 @@@ static void rna_def_tool_settings(Blend
                {UV_SELECT_FACE, "FACE", ICON_UV_FACESEL, "Face", "Face selection mode"},
                {UV_SELECT_ISLAND, "ISLAND", ICON_UV_ISLANDSEL, "Island", "Island selection mode"},
                {0, NULL, 0, NULL, NULL}};
+       
+       /* the construction of this enum is quite special - everything is stored as bitflags, 
+        * with 1st position only for for on/off (and exposed as boolean), while others are mutually 
+        * exclusive options but which will only have any effect when autokey is enabled
+        */
        static EnumPropertyItem auto_key_items[] = {
-               {AUTOKEY_MODE_NORMAL, "ADD_REPLACE_KEYS", 0, "Add & Replace", ""},
-               {AUTOKEY_MODE_EDITKEYS, "REPLACE_KEYS", 0, "Replace", ""},
+               {AUTOKEY_MODE_NORMAL & ~AUTOKEY_ON, "ADD_REPLACE_KEYS", 0, "Add & Replace", ""},
+               {AUTOKEY_MODE_EDITKEYS & ~AUTOKEY_ON, "REPLACE_KEYS", 0, "Replace", ""},
                {0, NULL, 0, NULL, NULL}};
  
        static EnumPropertyItem retarget_roll_items[] = {
        RNA_def_property_ui_text(prop, "WPaint Auto-Normalize", 
                "Ensure all bone-deforming vertex groups add up to 1.0 while "
                 "weight painting");
 +      RNA_def_property_update(prop, 0, "rna_update_active_object");
 +
 +      prop = RNA_def_property(srna, "use_multipaint", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "multipaint", 1);
 +      RNA_def_property_ui_text(prop, "WPaint Multi-Paint", 
 +              "Paint across all selected bones while "
 +               "weight painting");
 +      RNA_def_property_update(prop, 0, "rna_update_active_object");
  
        prop= RNA_def_property(srna, "vertex_paint", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "vpaint");
        RNA_def_property_ui_icon(prop, ICON_REC, 0);
        
        prop= RNA_def_property(srna, "auto_keying_mode", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_sdna(prop, NULL, "autokey_mode");
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "autokey_mode");
        RNA_def_property_enum_items(prop, auto_key_items);
        RNA_def_property_ui_text(prop, "Auto-Keying Mode", "Mode of automatic keyframe insertion for Objects and Bones");
        
        prop= RNA_def_property(srna, "use_keyframe_insert_keyingset", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_ONLYKEYINGSET);
        RNA_def_property_ui_text(prop, "Auto Keyframe Insert Keying Set", "Automatic keyframe insertion using active Keying Set only");
-       RNA_def_property_ui_icon(prop, ICON_KEY_HLT, 0); // XXX: we need a dedicated icon
+       RNA_def_property_ui_icon(prop, ICON_KEYINGSET, 0);
        
        /* UV */
        prop= RNA_def_property(srna, "uv_select_mode", PROP_ENUM, PROP_NONE);
@@@ -1903,6 -1925,10 +1933,10 @@@ static void rna_def_scene_game_data(Ble
        prop= RNA_def_property(srna, "use_auto_start", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_funcs(prop, "rna_GameSettings_auto_start_get", "rna_GameSettings_auto_start_set");
        RNA_def_property_ui_text(prop, "Auto Start", "Automatically start game at load time");
+       prop= RNA_def_property(srna, "restrict_animation_updates", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_RESTRICT_ANIM_UPDATES);
+       RNA_def_property_ui_text(prop, "Restrict Animation Updates", "Restrict the number of animation updates to the animation FPS. This is better for performance, but can cause issues with smooth playback.");
        
        /* materials */
        prop= RNA_def_property(srna, "material_mode", PROP_ENUM, PROP_NONE);
@@@ -1981,7 -2007,7 +2015,7 @@@ static void rna_def_render_layers(Blend
        prop= RNA_def_property(srna, "active", PROP_POINTER, PROP_UNSIGNED);
        RNA_def_property_struct_type(prop, "SceneRenderLayer");
        RNA_def_property_pointer_funcs(prop, "rna_RenderSettings_active_layer_get", "rna_RenderSettings_active_layer_set", NULL, NULL);
-       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_NULL);
        RNA_def_property_ui_text(prop, "Active Render Layer", "Active Render Layer");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
  
@@@ -2007,13 -2033,7 +2041,7 @@@ static void rna_def_scene_render_data(B
                {R_ALPHAPREMUL, "PREMUL", 0, "Premultiplied", "Transparent RGB pixels are multiplied by the alpha channel"},
                {R_ALPHAKEY, "STRAIGHT", 0, "Straight Alpha", "Transparent RGB and alpha pixels are unmodified"},
                {0, NULL, 0, NULL, NULL}};
-               
-       static EnumPropertyItem color_mode_items[] ={
-               {R_PLANESBW, "BW", 0, "BW", "Images get saved in 8 bits grayscale (only PNG, JPEG, TGA, TIF)"},
-               {R_PLANES24, "RGB", 0, "RGB", "Images are saved with RGB (color) data"},
-               {R_PLANES32, "RGBA", 0, "RGBA", "Images are saved with RGB and Alpha data (if supported)"},
-               {0, NULL, 0, NULL, NULL}};
-       
        static EnumPropertyItem display_mode_items[] ={
                {R_OUTPUT_SCREEN, "SCREEN", 0, "Full Screen", "Images are rendered in full Screen"},
                {R_OUTPUT_AREA, "AREA", 0, "Image Editor", "Images are rendered in Image Editor"},
                {0, NULL, 0, NULL, NULL}};
  #endif
  
+       static EnumPropertyItem audio_channel_items[] = {
+               {1, "MONO", 0, "Mono", "Set audio channels to mono"},
+               {2, "STEREO", 0, "Stereo", "Set audio channels to stereo"},
+               {4, "SURROUND4", 0, "4 Channels", "Set audio channels to 4 channels"},
+               {6, "SURROUND51", 0, "5.1 Surround", "Set audio channels to 5.1 surround sound"},
+               {8, "SURROUND71", 0, "7.1 Surround", "Set audio channels to 7.1 surround sound"},
+               {0, NULL, 0, NULL, NULL}};
        static EnumPropertyItem engine_items[] = {
                {0, "BLENDER_RENDER", 0, "Blender Render", "Use the Blender internal rendering engine for rendering"},
                {0, NULL, 0, NULL, NULL}};
        
        prop= RNA_def_property(srna, "color_mode", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_bitflag_sdna(prop, NULL, "planes");
-       RNA_def_property_enum_items(prop, color_mode_items);
+       RNA_def_property_enum_items(prop, image_color_mode_items);
        RNA_def_property_ui_text(prop, "Color Mode", "Choose BW for saving greyscale images, RGB for saving red, green and blue channels, AND RGBA for saving red, green, blue + alpha channels");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
  
        /* FFMPEG Audio*/
        prop= RNA_def_property(srna, "ffmpeg_audio_codec", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_bitflag_sdna(prop, NULL, "ffcodecdata.audio_codec");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_enum_items(prop, ffmpeg_audio_codec_items);
        RNA_def_property_ui_text(prop, "Audio Codec", "FFMpeg audio codec to use");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
        
        prop= RNA_def_property(srna, "ffmpeg_audio_bitrate", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "ffcodecdata.audio_bitrate");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 32, 384);
        RNA_def_property_ui_text(prop, "Bitrate", "Audio bitrate(kb/s)");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
        
-       prop= RNA_def_property(srna, "ffmpeg_audio_mixrate", PROP_INT, PROP_NONE);
-       RNA_def_property_int_sdna(prop, NULL, "ffcodecdata.audio_mixrate");
-       RNA_def_property_range(prop, 8000, 192000);
-       RNA_def_property_ui_text(prop, "Samplerate", "Audio samplerate(samples/s)");
-       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
        prop= RNA_def_property(srna, "ffmpeg_audio_volume", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "ffcodecdata.audio_volume");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 0.0f, 1.0f);
        RNA_def_property_ui_text(prop, "Volume", "Audio volume");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
  #endif
  
+       // the following two "ffmpeg" settings are general audio settings
+       prop= RNA_def_property(srna, "ffmpeg_audio_mixrate", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "ffcodecdata.audio_mixrate");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_range(prop, 8000, 192000);
+       RNA_def_property_ui_text(prop, "Samplerate", "Audio samplerate(samples/s)");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "ffmpeg_audio_channels", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "ffcodecdata.audio_channels");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_enum_items(prop, audio_channel_items);
+       RNA_def_property_ui_text(prop, "Audio Channels", "Sets the audio channel count");
        prop= RNA_def_property(srna, "fps", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "frs_sec");
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 1, 120);
        RNA_def_property_ui_text(prop, "FPS", "Framerate, expressed in frames per second");
-       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_Scene_fps_update");
        
        prop= RNA_def_property(srna, "fps_base", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "frs_sec_base");
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 0.1f, 120.0f);
        RNA_def_property_ui_text(prop, "FPS Base", "Framerate base");
-       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_Scene_fps_update");
        
        /* frame mapping */
        prop= RNA_def_property(srna, "frame_map_old", PROP_INT, PROP_NONE);
@@@ -3435,21 -3473,31 +3481,31 @@@ void RNA_def_scene(BlenderRNA *brna
  
        prop= RNA_def_property(srna, "audio_doppler_speed", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "audio.speed_of_sound");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 0.01f, FLT_MAX);
        RNA_def_property_ui_text(prop, "Speed of Sound", "Speed of sound for Doppler effect calculation");
-       RNA_def_property_update(prop, NC_SCENE, NULL);
+       RNA_def_property_update(prop, NC_SCENE, "rna_Scene_listener_update");
  
        prop= RNA_def_property(srna, "audio_doppler_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "audio.doppler_factor");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_range(prop, 0.0, FLT_MAX);
        RNA_def_property_ui_text(prop, "Doppler Factor", "Pitch factor for Doppler effect calculation");
-       RNA_def_property_update(prop, NC_SCENE, NULL);
+       RNA_def_property_update(prop, NC_SCENE, "rna_Scene_listener_update");
  
        prop= RNA_def_property(srna, "audio_distance_model", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_bitflag_sdna(prop, NULL, "audio.distance_model");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_enum_items(prop, audio_distance_model_items);
        RNA_def_property_ui_text(prop, "Distance Model", "Distance model for distance attenuation calculation");
+       RNA_def_property_update(prop, NC_SCENE, "rna_Scene_listener_update");
+       prop= RNA_def_property(srna, "audio_volume", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "audio.volume");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Volume", "Audio volume");
        RNA_def_property_update(prop, NC_SCENE, NULL);
+       RNA_def_property_float_funcs(prop, NULL, "rna_Scene_volume_set", NULL);
  
        /* Game Settings */
        prop= RNA_def_property(srna, "game_settings", PROP_POINTER, PROP_NONE);