svn merge -r40000:40179 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorCampbell Barton <ideasman42@gmail.com>
Tue, 13 Sep 2011 10:05:30 +0000 (10:05 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 13 Sep 2011 10:05:30 +0000 (10:05 +0000)
13 files changed:
1  2 
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/editors/armature/meshlaplacian.c
source/blender/editors/mesh/editmesh.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_ops.c
source/blender/editors/space_view3d/drawobject.c
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_scene.c

@@@ -646,8 -646,6 +646,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()
  
@@@ -770,9 -768,9 +770,9 @@@ class VIEW3D_PT_tools_brush_texture(Pai
              col = row.column()
  
              if brush.use_texture_overlay:
-                 col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='MUTE_IPO_OFF')
+                 col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
              else:
-                 col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='MUTE_IPO_ON')
+                 col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
  
              col.active = tex_slot.map_mode in {'FIXED', 'TILED'}
  
@@@ -1060,7 -1058,6 +1060,7 @@@ class VIEW3D_PT_tools_weightpaint(View3
          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):
@@@ -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"
  
  ///////////////////////////////////
  ///////////////////////////////////
@@@ -648,13 -643,22 +648,22 @@@ static void emDM_drawMappedFaces(Derive
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
        EditFace *efa;
        int i, draw;
-       
+       const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
+       /* GL_ZERO is used to detect if drawing has started or not */
+       GLenum poly_prev= GL_ZERO;
+       GLenum shade_prev= GL_ZERO;
        (void)setMaterial; /* unused */
  
        /* currently unused -- each original face is handled separately */
        (void)compareDrawOptions;
  
        if (emdm->vertexCos) {
+               /* add direct access */
+               float (*vertexCos)[3]= emdm->vertexCos;
+               float (*vertexNos)[3]= emdm->vertexNos;
+               float (*faceNos)[3]=   emdm->faceNos;
                EditVert *eve;
  
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
                        int drawSmooth = (efa->flag & ME_SMOOTH);
                        draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth);
                        if(draw) {
+                               const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES;
                                if (draw==2) { /* enabled with stipple */
-                                         glEnable(GL_POLYGON_STIPPLE);
-                                         glPolygonStipple(stipple_quarttone);
+                                       if(poly_prev != GL_ZERO) glEnd();
+                                       poly_prev= GL_ZERO; /* force glBegin */
+                                       glEnable(GL_POLYGON_STIPPLE);
+                                       glPolygonStipple(stipple_quarttone);
                                }
                                
-                               glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+                               if(skip_normals) {
+                                       if(poly_type != poly_prev) {
+                                               if(poly_prev != GL_ZERO) glEnd();
+                                               glBegin((poly_prev= poly_type));
+                                       }
+                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                                       if(poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                               }
+                               else {
+                                       const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
+                                       if (shade_type != shade_prev) {
+                                               glShadeModel((shade_prev= shade_type));
+                                       }
+                                       if(poly_type != poly_prev) {
+                                               if(poly_prev != GL_ZERO) glEnd();
+                                               glBegin((poly_prev= poly_type));
+                                       }
  
-                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
-                               if (!drawSmooth) {
-                                       glNormal3fv(emdm->faceNos[i]);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v1->tmp.l]);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v2->tmp.l]);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v3->tmp.l]);
-                                       if(efa->v4) glVertex3fv(emdm->vertexCos[(int) efa->v4->tmp.l]);
-                               } else {
-                                       glNormal3fv(emdm->vertexNos[(int) efa->v1->tmp.l]);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v1->tmp.l]);
-                                       glNormal3fv(emdm->vertexNos[(int) efa->v2->tmp.l]);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v2->tmp.l]);
-                                       glNormal3fv(emdm->vertexNos[(int) efa->v3->tmp.l]);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v3->tmp.l]);
-                                       if(efa->v4) {
-                                               glNormal3fv(emdm->vertexNos[(int) efa->v4->tmp.l]);
-                                               glVertex3fv(emdm->vertexCos[(int) efa->v4->tmp.l]);
+                                       if (!drawSmooth) {
+                                               glNormal3fv(faceNos[i]);
+                                               glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                                               glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                                               glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                                               if(poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                       } else {
+                                               glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
+                                               glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                                               glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
+                                               glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                                               glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
+                                               glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                                               if(poly_type == GL_QUADS) {
+                                                       glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
+                                                       glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                               }
                                        }
                                }
-                               glEnd();
                                
-                               if (draw==2)
+                               if (draw==2) {
+                                       glEnd();
+                                       poly_prev= GL_ZERO; /* force glBegin */
                                        glDisable(GL_POLYGON_STIPPLE);
+                               }
                        }
                }
-       } else {
+       }
+       else {
                for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
                        int drawSmooth = (efa->flag & ME_SMOOTH);
                        draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth);
                        if(draw) {
+                               const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES;
                                if (draw==2) { /* enabled with stipple */
+                                       if(poly_prev != GL_ZERO) glEnd();
+                                       poly_prev= GL_ZERO; /* force glBegin */
                                        glEnable(GL_POLYGON_STIPPLE);
                                        glPolygonStipple(stipple_quarttone);
                                }
-                               glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
  
-                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
-                               if (!drawSmooth) {
-                                       glNormal3fv(efa->n);
-                                       glVertex3fv(efa->v1->co);
-                                       glVertex3fv(efa->v2->co);
-                                       glVertex3fv(efa->v3->co);
-                                       if(efa->v4) glVertex3fv(efa->v4->co);
-                               } else {
-                                       glNormal3fv(efa->v1->no);
+                               if(skip_normals) {
+                                       if(poly_type != poly_prev) {
+                                               if(poly_prev != GL_ZERO) glEnd();
+                                               glBegin((poly_prev= poly_type));
+                                       }
                                        glVertex3fv(efa->v1->co);
-                                       glNormal3fv(efa->v2->no);
                                        glVertex3fv(efa->v2->co);
-                                       glNormal3fv(efa->v3->no);
                                        glVertex3fv(efa->v3->co);
-                                       if(efa->v4) {
-                                               glNormal3fv(efa->v4->no);
-                                               glVertex3fv(efa->v4->co);
+                                       if(poly_type == GL_QUADS) glVertex3fv(efa->v4->co);
+                               }
+                               else {
+                                       const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
+                                       if (shade_type != shade_prev) {
+                                               glShadeModel((shade_prev= shade_type));
+                                       }
+                                       if(poly_type != poly_prev) {
+                                               if(poly_prev != GL_ZERO) glEnd();
+                                               glBegin((poly_prev= poly_type));
+                                       }
+                                       if (!drawSmooth) {
+                                               glNormal3fv(efa->n);
+                                               glVertex3fv(efa->v1->co);
+                                               glVertex3fv(efa->v2->co);
+                                               glVertex3fv(efa->v3->co);
+                                               if(poly_type == GL_QUADS) glVertex3fv(efa->v4->co);
+                                       } else {
+                                               glNormal3fv(efa->v1->no);
+                                               glVertex3fv(efa->v1->co);
+                                               glNormal3fv(efa->v2->no);
+                                               glVertex3fv(efa->v2->co);
+                                               glNormal3fv(efa->v3->no);
+                                               glVertex3fv(efa->v3->co);
+                                               if(poly_type == GL_QUADS) {
+                                                       glNormal3fv(efa->v4->no);
+                                                       glVertex3fv(efa->v4->co);
+                                               }
                                        }
                                }
-                               glEnd();
                                
-                               if (draw==2)
+                               if (draw==2) {
+                                       glEnd();
+                                       poly_prev= GL_ZERO;
                                        glDisable(GL_POLYGON_STIPPLE);
+                               }
                        }
                }
        }
+       /* if non zero we know a face was rendered */
+       if(poly_prev != GL_ZERO) glEnd();
  }
  
  static void emDM_drawFacesTex_common(DerivedMesh *dm,
@@@ -1612,50 -1675,19 +1680,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);
@@@ -1674,69 -1706,26 +1742,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);
  }
  
@@@ -1943,7 -1932,7 +2011,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 */
@@@ -2340,7 -2329,7 +2408,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)));
  
@@@ -2528,13 -2517,13 +2596,13 @@@ static void make_vertexcosnos__mapFunc(
        /* check if we've been here before (normal should not be 0) */
        if(vec[3] || vec[4] || vec[5]) return;
  
-       VECCOPY(vec, co);
+       copy_v3_v3(vec, co);
        vec+= 3;
        if(no_f) {
-               VECCOPY(vec, no_f);
+               copy_v3_v3(vec, no_f);
        }
        else {
-               VECCOPY(vec, no_s);
+               normal_short_to_float_v3(vec, no_s);
        }
  }
  
@@@ -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)
  {
@@@ -1592,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;
@@@ -1893,7 -1853,7 +1893,7 @@@ void CDDM_apply_vert_normals(DerivedMes
        cddm->mvert = vert;
  
        for(i = 0; i < dm->numVertData; ++i, ++vert)
-               VECCOPY(vert->no, vertNormals[i]);
+               copy_v3_v3_short(vert->no, vertNormals[i]);
  }
  
  void CDDM_calc_normals(DerivedMesh *dm)
@@@ -518,7 -518,7 +518,7 @@@ static float heat_source_distance(Lapla
        dist= normalize_v3(d);
  
        /* if the vertex normal does not point along the bone, increase distance */
-       cosine= INPR(d, sys->heat.vnors[vertex]);
+       cosine= dot_v3v3(d, sys->heat.vnors[vertex]);
  
        return dist/(0.5f*(cosine + 1.001f));
  }
@@@ -657,26 -657,22 +657,26 @@@ void heat_bone_weighting(Object *ob, Me
        int *vertsflipped = NULL, *mask= NULL;
        int a, totface, j, bbone, firstsegment, lastsegment;
  
 +      // Jason
 +      MVert *mv = me->mvert;
 +      int selectedVerts;
 +
        *err_str= NULL;
  
        /* count triangles and create mask */
 -      if(me->editflag & ME_EDIT_PAINT_MASK)
 +      if((me->editflag & ME_EDIT_PAINT_MASK) || (selectedVerts=(me->editflag & ME_EDIT_VERT_SEL)))
                mask= MEM_callocN(sizeof(int)*me->totvert, "heat_bone_weighting mask");
  
        for(totface=0, a=0, mface=me->mface; a<me->totface; a++, mface++) {
                totface++;
                if(mface->v4) totface++;
 -
 -              if(mask && (mface->flag & ME_FACE_SEL)) {
 -                      mask[mface->v1]= 1;
 -                      mask[mface->v2]= 1;
 -                      mask[mface->v3]= 1;
 +              // Jason (added selectedVerts content for vertex mask, they used to just equal 1)
 +              if(mask && ((mface->flag & ME_FACE_SEL) || selectedVerts)) {
 +                      mask[mface->v1]= selectedVerts ? ((mv+mface->v1)->flag & 1): 1;
 +                      mask[mface->v2]= selectedVerts ? ((mv+mface->v2)->flag & 1): 1;
 +                      mask[mface->v3]= selectedVerts ? ((mv+mface->v3)->flag & 1): 1;
                        if(mface->v4)
 -                              mask[mface->v4]= 1;
 +                              mask[mface->v4]= selectedVerts ? ((mv+mface->v4)->flag & 1): 1;
                }
        }
  
@@@ -1124,7 -1120,7 +1124,7 @@@ static int meshdeform_tri_intersect(flo
        cross_v3_v3v3(pvec, dir, edge2);
  
        /* if determinant is near zero, ray lies in plane of triangle */
-       det = INPR(edge1, pvec);
+       det = dot_v3v3(edge1, pvec);
  
        if (det == 0.0f)
                return 0;
        sub_v3_v3v3(tvec, orig, vert0);
  
        /* calculate U parameter and test bounds */
-       u = INPR(tvec, pvec) * inv_det;
+       u = dot_v3v3(tvec, pvec) * inv_det;
        if (u < -EPSILON || u > 1.0f+EPSILON)
                return 0;
  
        cross_v3_v3v3(qvec, tvec, edge1);
  
        /* calculate V parameter and test bounds */
-       v = INPR(dir, qvec) * inv_det;
+       v = dot_v3v3(dir, qvec) * inv_det;
        if (v < -EPSILON || u + v > 1.0f+EPSILON)
                return 0;
  
        /* check if it is within the length of the line segment */
        sub_v3_v3v3(isectdir, isectco, orig);
  
-       if(INPR(dir, isectdir) < -EPSILON)
+       if(dot_v3v3(dir, isectdir) < -EPSILON)
                return 0;
        
-       if(INPR(dir, dir) + EPSILON < INPR(isectdir, isectdir))
+       if(dot_v3v3(dir, dir) + EPSILON < dot_v3v3(isectdir, isectdir))
                return 0;
  
        return 1;
@@@ -1206,7 -1202,7 +1206,7 @@@ static int meshdeform_intersect(MeshDef
                        if(len < isec->labda) {
                                isec->labda= len;
                                isec->face = mface;
-                               isec->isect= (INPR(isec->vec, nor) <= 0.0f);
+                               isec->isect= (dot_v3v3(isec->vec, nor) <= 0.0f);
                                is= 1;
                        }
                }
@@@ -1659,8 -1659,8 +1659,8 @@@ static void *editMesh_to_undoMesh(void 
        /* now copy vertices */
        a = 0;
        for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
-               VECCOPY(evec->co, eve->co);
-               VECCOPY(evec->no, eve->no);
+               copy_v3_v3(evec->co, eve->co);
+               copy_v3_v3(evec->no, eve->no);
  
                evec->f= eve->f;
                evec->h= eve->h;
@@@ -1761,7 -1761,7 +1761,7 @@@ static void undoMesh_to_editMesh(void *
                eve= addvertlist(em, evec->co, NULL);
                evar[a]= eve;
  
-               VECCOPY(eve->no, evec->no);
+               copy_v3_v3(eve->no, evec->no);
                eve->f= evec->f;
                eve->h= evec->h;
                eve->keyindex= evec->keyindex;
@@@ -1958,96 -1958,3 +1958,96 @@@ void em_setup_viewcontext(bContext *C, 
                vc->em= me->edit_mesh;
        }
  }
 +
 +
 +/* Jason (similar to void paintface_flush_flags(Object *ob))
 + * copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
 + * use in object mode when selecting vertices (while painting) */
 +void paintvert_flush_flags(Object *ob)
 +{
 +      Mesh *me= get_mesh(ob);
 +      DerivedMesh *dm= ob->derivedFinal;
 +      MVert *verts, *mv, *mv_orig;
 +      int *index_array = NULL;
 +      int totvert;
 +      int i;
 +      
 +      if(me==NULL || dm==NULL)
 +              return;
 +
 +      index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
 +      
 +      verts = dm->getVertArray(dm);
 +      totvert = dm->getNumVerts(dm);
 +      
 +      mv= verts;
 +      
 +      for (i= 0; i<totvert; i++, mv++) { /* loop over derived mesh faces */
 +              if(index_array) {
 +                      mv_orig= me->mvert + index_array[i];
 +                      mv->flag= mv_orig->flag;
 +              } else {
 +                      mv_orig= me->mvert + i;
 +                      mv->flag= mv_orig->flag;
 +              }
 +      }
 +}
 +/* Jason note: caller needs to run paintvert_flush_flags(ob) after this */
 +void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
 +{
 +      Mesh *me;
 +      MVert *mvert;
 +      int a;
 +
 +      me= get_mesh(ob);
 +      if(me==NULL) return;
 +      
 +      if(action == SEL_INVERT) {
 +              mvert= me->mvert;
 +              a= me->totvert;
 +              while(a--) {
 +                      if((mvert->flag & ME_HIDE) == 0) {
 +                              mvert->flag ^= SELECT;
 +                      }
 +                      mvert++;
 +              }
 +      }
 +      else {
 +              if (action == SEL_TOGGLE) {
 +                      action = SEL_SELECT;
 +
 +                      mvert= me->mvert;
 +                      a= me->totvert;
 +                      while(a--) {
 +                              if((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
 +                                      action = SEL_DESELECT;
 +                                      break;
 +                              }
 +                              mvert++;
 +                      }
 +              }
 +
 +              mvert= me->mvert;
 +              a= me->totvert;
 +              while(a--) {
 +                      if((mvert->flag & ME_HIDE) == 0) {
 +                              switch (action) {
 +                              case SEL_SELECT:
 +                                      mvert->flag |= SELECT;
 +                                      break;
 +                              case SEL_DESELECT:
 +                                      mvert->flag &= ~SELECT;
 +                                      break;
 +                              case SEL_INVERT:
 +                                      mvert->flag ^= SELECT;
 +                                      break;
 +                              }
 +                      }
 +                      mvert++;
 +              }
 +      }
 +
 +      if(flush_flags) {
 +              paintvert_flush_flags(ob);
 +      }
 +}
@@@ -266,7 -266,6 +266,7 @@@ int EM_mask_init_backbuf_border(ViewCon
        /* method in use for face selecting too */
        if(vc->obedit==NULL) {
                if(paint_facesel_test(vc->obact));
 +              else if(paint_vertsel_test(vc->obact));//Jason
                else return 0;
        }
        else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
@@@ -329,7 -328,6 +329,7 @@@ int EM_init_backbuf_circle(ViewContext 
        /* method in use for face selecting too */
        if(vc->obedit==NULL) {
                if(paint_facesel_test(vc->obact));
 +              else if (paint_vertsel_test(vc->obact));//Jason
                else return 0;
        }
        else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
@@@ -829,7 -827,7 +829,7 @@@ static int similar_face_select__interna
                                float angle;
                                for(efa= em->faces.first; efa; efa= efa->next) {
                                        if (!(efa->f & SELECT) && !efa->h) {
-                                               angle= RAD2DEGF(angle_v2v2(base_efa->n, efa->n));
+                                               angle= RAD2DEGF(angle_v3v3(base_efa->n, efa->n));
                                                if (angle/180.0f<=thresh) {
                                                        EM_select_face(efa, 1);
                                                        selcount++;
                                base_dot= dot_v3v3(base_efa->cent, base_efa->n);
                                for(efa= em->faces.first; efa; efa= efa->next) {
                                        if (!(efa->f & SELECT) && !efa->h) {
-                                               angle= RAD2DEGF(angle_v2v2(base_efa->n, efa->n));
+                                               angle= RAD2DEGF(angle_v3v3(base_efa->n, efa->n));
                                                if (angle/180.0f<=thresh) {
                                                        dot=dot_v3v3(efa->cent, base_efa->n);
                                                        if (fabsf(base_dot-dot) <= thresh) {
@@@ -961,7 -959,7 +961,7 @@@ static int similar_edge_select__interna
                                        else if (eed->f2==0) /* first access, assign the face */
                                                eed->tmp.f= efa;
                                        else if (eed->f2==1) /* second, we assign the angle*/
-                                               eed->tmp.fp= RAD2DEGF(angle_v2v2(eed->tmp.f->n, efa->n))/180;
+                                               eed->tmp.fp= RAD2DEGF(angle_v3v3(eed->tmp.f->n, efa->n))/180;
                                        eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/
                                }
                                j++;
                                for(eed= em->edges.first; eed; eed= eed->next) {
                                        if (!(eed->f & SELECT) && !eed->h) {
                                                sub_v3_v3v3(dir, eed->v1->co, eed->v2->co);
-                                               angle= RAD2DEGF(angle_v2v2(base_dir, dir));
+                                               angle= RAD2DEGF(angle_v3v3(base_dir, dir));
                                                
                                                if (angle>90.0f) /* use the smallest angle between the edges */
                                                        angle= fabsf(angle-180.0f);
@@@ -1088,7 -1086,7 +1088,7 @@@ static int similar_edge_select_exec(bCo
        Mesh *me= obedit->data;
        EditMesh *em= BKE_mesh_get_editmesh(me); 
  
-       int selcount = similar_edge_select__internal(em, RNA_int_get(op->ptr, "type"), RNA_float_get(op->ptr, "threshold"));
+       int selcount = similar_edge_select__internal(em, RNA_enum_get(op->ptr, "type"), RNA_float_get(op->ptr, "threshold"));
        
        if (selcount) {
                /* here was an edge-mode only select flush case, has to be generalized */
@@@ -1161,7 -1159,7 +1161,7 @@@ static int similar_vert_select_exec(bCo
                                float angle;
                                for(eve= em->verts.first; eve; eve= eve->next) {
                                        if (!(eve->f & SELECT) && !eve->h) {
-                                               angle= RAD2DEGF(angle_v2v2(base_eve->no, eve->no));
+                                               angle= RAD2DEGF(angle_v3v3(base_eve->no, eve->no));
                                                if (angle/180.0f<=thresh) {
                                                        eve->f |= SELECT;
                                                        selcount++;
@@@ -4150,7 -4148,7 +4150,7 @@@ static int smooth_vertex(bContext *C, w
         * are within tolerance of the plane(s) of reflection 
         */
        for(md=obedit->modifiers.first; md; md=md->next) {
-               if(md->type==eModifierType_Mirror) {
+               if((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
                        MirrorModifierData *mmd = (MirrorModifierData*) md;     
                
                        if(mmd->flag & MOD_MIR_CLIPPING) {
@@@ -200,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);
@@@ -229,5 -223,10 +229,10 @@@ void OBJECT_OT_group_remove(struct wmOp
  /* object_bake.c */
  void OBJECT_OT_bake_image(wmOperatorType *ot);
  
+ /* object_navmesh.cpp */
+ void OBJECT_OT_create_navmesh(struct wmOperatorType *ot);
+ void OBJECT_OT_assign_navpolygon(struct wmOperatorType *ot);
+ void OBJECT_OT_assign_new_navpolygon(struct wmOperatorType *ot);
  #endif /* ED_OBJECT_INTERN_H */
  
@@@ -174,12 -174,6 +174,12 @@@ void ED_operatortypes_object(void
        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);
  
        WM_operatortype_append(OBJECT_OT_bake_image);
        WM_operatortype_append(OBJECT_OT_drop_named_material);
+ #ifdef WITH_GAMEENGINE
+       WM_operatortype_append(OBJECT_OT_create_navmesh);
+       WM_operatortype_append(OBJECT_OT_assign_navpolygon);
+       WM_operatortype_append(OBJECT_OT_assign_new_navpolygon);
+ #endif
  }
  
  void ED_operatormacros_object(void)
  {
        wmOperatorType *ot;
@@@ -139,7 -139,7 +139,7 @@@ static int check_ob_drawface_dot(Scene 
  /* ************* only use while object drawing **************
   * or after running ED_view3d_init_mats_rv3d
   * */
- static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
+ static void view3d_project_short_clip(ARegion *ar, const float vec[3], short *adr, int local)
  {
        RegionView3D *rv3d= ar->regiondata;
        float fx, fy, vec4[4];
  }
  
  /* only use while object drawing */
- static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
+ static void view3d_project_short_noclip(ARegion *ar, const float vec[3], short *adr)
  {
        RegionView3D *rv3d= ar->regiondata;
        float fx, fy, vec4[4];
@@@ -837,7 -837,7 +837,7 @@@ static void drawcube_size(float size
  
  /* this is an unused (old) cube-drawing function based on a given size */
  #if 0
- static void drawcube_size(float *size)
+ static void drawcube_size(const float size[3])
  {
  
        glPushMatrix();
@@@ -891,7 -891,7 +891,7 @@@ static void drawshadbuflimits(Lamp *la
  
  
  
- static void spotvolume(float *lvec, float *vvec, float inp)
+ static void spotvolume(float lvec[3], float vvec[3], const float inp)
  {
        /* camera is at 0,0,0 */
        float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
        normalize_v3(&q[1]);
  
        angle = saacos(plane[2])/2.0f;
-       co = cos(angle);
-       si = sqrt(1-co*co);
+       co = cosf(angle);
+       si = sqrtf(1-co*co);
  
        q[0] =  co;
        q[1] *= si;
  
        unit_m3(mat2);
        co = inp;
-       si = sqrt(1-inp*inp);
+       si = sqrtf(1.0f-inp*inp);
  
        mat2[0][0] =  co;
        mat2[1][0] = -si;
@@@ -1712,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;
@@@ -2935,13 -2897,7 +2935,13 @@@ static void draw_mesh_fancy(Scene *scen
                        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);
  }
  
@@@ -5079,7 -5035,7 +5079,7 @@@ static void draw_textcurs(float textcur
        set_inverted_drawing(0);
  }
  
- static void drawspiral(float *cent, float rad, float tmat[][4], int start)
+ static void drawspiral(const float cent[3], float rad, float tmat[][4], int start)
  {
        float vec[3], vx[3], vy[3];
        int a, tot=32;
@@@ -5150,7 -5106,7 +5150,7 @@@ static void drawcircle_size(float size
  }
  
  /* needs fixing if non-identity matrice used */
- static void drawtube(float *vec, float radius, float height, float tmat[][4])
+ static void drawtube(const float vec[3], float radius, float height, float tmat[][4])
  {
        float cur[3];
        drawcircball(GL_LINE_LOOP, vec, radius, tmat);
        glEnd();
  }
  /* needs fixing if non-identity matrice used */
- static void drawcone(float *vec, float radius, float height, float tmat[][4])
+ static void drawcone(const float vec[3], float radius, float height, float tmat[][4])
  {
        float cur[3];
  
@@@ -5448,7 -5404,7 +5448,7 @@@ static void draw_box(float vec[8][3]
  
  /* uses boundbox, function used by Ketsji */
  #if 0
- static void get_local_bounds(Object *ob, float *center, float *size)
+ static void get_local_bounds(Object *ob, float center[3], float size[3])
  {
        BoundBox *bb= object_get_boundbox(ob);
        
@@@ -5885,46 -5841,68 +5885,68 @@@ void draw_object(Scene *scene, ARegion 
  
        /* which wire color */
        if((flag & DRAW_CONSTCOLOR) == 0) {
+               /* confusing logic here, there are 2 methods of setting the color
+                * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
+                *
+                * note: no theme yet for 'colindex' */
+               int theme_id= TH_WIRE;
+               int theme_shade= 0;
                project_short(ar, ob->obmat[3], &base->sx);
  
-               if( (!scene->obedit) && (G.moving & G_TRANSFORM_OBJ) && (base->flag & (SELECT+BA_WAS_SEL))) UI_ThemeColor(TH_TRANSFORM);
+               if(             (scene->obedit == NULL) &&
+                       (G.moving & G_TRANSFORM_OBJ) &&
+                       (base->flag & (SELECT+BA_WAS_SEL)))
+               {
+                       theme_id= TH_TRANSFORM;
+               }
                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(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
-                       }
-                       else {
-                               if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
-                       }
-                       // no theme yet
+                       /* Sets the 'colindex' */
                        if(ob->id.lib) {
-                               if(base->flag & (SELECT+BA_WAS_SEL)) colindex = 4;
-                               else colindex = 3;
+                               colindex= (base->flag & (SELECT+BA_WAS_SEL)) ? 4 : 3;
                        }
                        else if(warning_recursive==1) {
                                if(base->flag & (SELECT+BA_WAS_SEL)) {
-                                       if(scene->basact==base) colindex = 8;
-                                       else colindex= 7;
+                                       colindex= (scene->basact==base) ? 8 : 7;
                                }
-                               else colindex = 6;
-                       }
-                       else if(ob->flag & OB_FROMGROUP) {
-                               if(base->flag & (SELECT+BA_WAS_SEL)) {
-                                       if(scene->basact==base) UI_ThemeColor(TH_GROUP_ACTIVE);
-                                       else UI_ThemeColorShade(TH_GROUP_ACTIVE, -16); 
+                               else {
+                                       colindex = 6;
                                }
-                               else UI_ThemeColor(TH_GROUP);
-                               colindex= 0;
                        }
+                       /* Sets the 'theme_id' or fallback to wire */
+                       else {
+                               if(ob->flag & OB_FROMGROUP) {
+                                       if(base->flag & (SELECT+BA_WAS_SEL)) {
+                                               /* uses darker active color for non-active + selected*/
+                                               theme_id= TH_GROUP_ACTIVE;
  
-               }       
+                                               if(scene->basact != base) {
+                                                       theme_shade= -16;
+                                               }
+                                       }
+                                       else {
+                                               theme_id= TH_GROUP;
+                                       }
+                               }
+                               else {
+                                       if(base->flag & (SELECT+BA_WAS_SEL)) {
+                                               theme_id= scene->basact == base ? TH_ACTIVE : TH_SELECT;
+                                       }
+                                       else {
+                                               if(ob->type==OB_LAMP) theme_id= TH_LAMP;
+                                               else if(ob->type==OB_SPEAKER) theme_id= TH_SPEAKER;
+                                               /* fallback to TH_WIRE */
+                                       }
+                               }
+                       }
+               }
  
-               if(colindex) {
+               /* finally set the color */
+               if(colindex == 0) {
+                       if(theme_shade == 0) UI_ThemeColor(theme_id);
+                       else                 UI_ThemeColorShade(theme_id, theme_shade);
+               }
+               else {
                        col= colortab[colindex];
                        cpack(col);
                }
                                }
  
                                if (cu->linewidth != 0.0f) {
-                                       cpack(0xff44ff);
                                        UI_ThemeColor(TH_WIRE);
                                        copy_v3_v3(vec1, ob->orig);
                                        copy_v3_v3(vec2, ob->orig);
                                setlinestyle(3);
                                for (i=0; i<cu->totbox; i++) {
                                        if (cu->tb[i].w != 0.0f) {
-                                               if (i == (cu->actbox-1))
-                                                       UI_ThemeColor(TH_ACTIVE);
-                                               else
-                                                       UI_ThemeColor(TH_WIRE);
+                                               UI_ThemeColor(i == (cu->actbox-1) ? TH_ACTIVE : TH_WIRE);
                                                vec1[0] = (cu->xof * cu->fsize) + cu->tb[i].x;
                                                vec1[1] = (cu->yof * cu->fsize) + cu->tb[i].y + cu->fsize;
                                                vec1[2] = 0.001;
  }
  
  /* ***************** 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))
  {
@@@ -6627,18 -6578,7 +6645,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);
@@@ -6697,22 -6637,7 +6715,22 @@@ void draw_object_backbufsel(Scene *scen
                        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, NULL);
 +
 +                              
 +                              bbs_obmode_mesh_verts(scene, ob, dm, 1);
 +                              em_vertoffs = me->totvert+1;
 +                              dm->release(dm);
 +                      }
 +                      else {
 +                              bbs_mesh_solid(scene, ob);
 +                      }
                }
                break;
        case OB_CURVE:
@@@ -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
  
@@@ -191,6 -189,8 +191,8 @@@ typedef struct Object 
        float max_vel; /* clamp the maximum velocity 0.0 is disabled */
        float min_vel; /* clamp the maximum velocity 0.0 is disabled */
        float m_contactProcessingThreshold;
+       float obstacleRad;
+       char pad0[4];
        
        short rotmode;          /* rotation mode - uses defines set out in DNA_action_types.h for PoseChannel rotations... */
        
@@@ -475,6 -475,8 +477,8 @@@ typedef struct DupliObject 
  #define OB_SOFT_BODY  0x20000
  #define OB_OCCLUDER           0x40000
  #define OB_SENSOR             0x80000
+ #define OB_NAVMESH            0x100000
+ #define OB_HASOBSTACLE        0x200000
  
  /* ob->gameflag2 */
  #define OB_NEVER_DO_ACTIVITY_CULLING  1
  #define OB_BODY_TYPE_SOFT                     4
  #define OB_BODY_TYPE_OCCLUDER         5
  #define OB_BODY_TYPE_SENSOR                   6
+ #define OB_BODY_TYPE_NAVMESH          7
  
  /* ob->scavisflag */
  #define OB_VIS_SENS           1
@@@ -426,8 -426,38 +426,38 @@@ typedef struct GameFraming 
  #define SCE_GAMEFRAMING_EXTEND 1
  #define SCE_GAMEFRAMING_SCALE  2
  
+ typedef struct RecastData
+ {
+       float cellsize;
+       float cellheight;
+       float agentmaxslope;
+       float agentmaxclimb;
+       float agentheight;
+       float agentradius;
+       float edgemaxlen;
+       float edgemaxerror;
+       float regionminsize;
+       float regionmergesize;
+       int vertsperpoly;
+       float detailsampledist;
+       float detailsamplemaxerror;
+ } RecastData;
  typedef struct GameData {
  
+       /*  standalone player */
+       struct GameFraming framing;
+       short fullscreen, xplay, yplay, freqplay;
+       short depth, attrib, rt1, rt2;
+       /* stereo/dome mode */
+       struct GameDome dome;
+       short stereoflag, stereomode;
+       short pad2, pad3;
+       float eyeseparation, pad1;
+       RecastData recastData;
        /* physics (it was in world)*/
        float gravity; /*Gravitation constant for the game world*/
  
         * bit 3: (gameengine): Activity culling is enabled.
         * bit 5: (gameengine) : enable Bullet DBVT tree for view frustrum culling
        */
-       short mode, flag, matmode, pad[3];
+       short mode, flag, matmode, pad[2];
        short occlusionRes;             /* resolution of occlusion Z buffer in pixel */
        short physicsEngine;
        short ticrate, maxlogicstep, physubstep, maxphystep;
-       /*  standalone player */
-       struct GameFraming framing;
-       short fullscreen, xplay, yplay, freqplay;
-       short depth, attrib, rt1, rt2;
-       /* stereo/dome mode */
-       struct GameDome dome;
-       short stereoflag, stereomode;
-       short pad2, pad3;
-       float eyeseparation, pad1;
+       short obstacleSimulation;
+       float levelHeight;
  } GameData;
  
  #define STEREO_NOSTEREO               1
  #define WOPHY_ODE             4
  #define WOPHY_BULLET  5
  
+ /* obstacleSimulation */
+ #define OBSTSIMULATION_NONE           0
+ #define OBSTSIMULATION_TOI_rays               1
+ #define OBSTSIMULATION_TOI_cells      2
  /* GameData.flag */
  #define GAME_RESTRICT_ANIM_UPDATES                    (1 << 0)
  #define GAME_ENABLE_ALL_FRAMES                                (1 << 1)
  #define GAME_IGNORE_DEPRECATION_WARNINGS      (1 << 12)
  #define GAME_ENABLE_ANIMATION_RECORD          (1 << 13)
  #define GAME_SHOW_MOUSE                                               (1 << 14)
+ #define GAME_SHOW_OBSTACLE_SIMULATION         (1 << 15)
  #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 */
  
@@@ -732,13 -759,10 +759,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 */
@@@ -220,16 -220,6 +220,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)
  {
@@@ -868,6 -858,8 +868,8 @@@ static int rna_GameObjectSettings_physi
        if (!(ob->gameflag & OB_COLLISION)) {
                if (ob->gameflag & OB_OCCLUDER) {
                        ob->body_type = OB_BODY_TYPE_OCCLUDER;
+               } else if (ob->gameflag & OB_NAVMESH){
+                       ob->body_type = OB_BODY_TYPE_NAVMESH;
                } else {
                        ob->body_type = OB_BODY_TYPE_NO_COLLISION;
                }
@@@ -897,31 -889,35 +899,35 @@@ static void rna_GameObjectSettings_phys
        switch (ob->body_type) {
        case OB_BODY_TYPE_SENSOR:
                ob->gameflag |= OB_SENSOR|OB_COLLISION|OB_GHOST;
-               ob->gameflag &= ~(OB_OCCLUDER|OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY|OB_ACTOR|OB_ANISOTROPIC_FRICTION|OB_DO_FH|OB_ROT_FH|OB_COLLISION_RESPONSE);
+               ob->gameflag &= ~(OB_OCCLUDER|OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY|OB_ACTOR|OB_ANISOTROPIC_FRICTION|OB_DO_FH|OB_ROT_FH|OB_COLLISION_RESPONSE|OB_NAVMESH);
                break;
        case OB_BODY_TYPE_OCCLUDER:
                ob->gameflag |= OB_OCCLUDER;
-               ob->gameflag &= ~(OB_SENSOR|OB_COLLISION|OB_DYNAMIC);
+               ob->gameflag &= ~(OB_SENSOR|OB_COLLISION|OB_DYNAMIC|OB_NAVMESH);
+               break;
+       case OB_BODY_TYPE_NAVMESH:
+               ob->gameflag |= OB_NAVMESH;
+               ob->gameflag &= ~(OB_SENSOR|OB_COLLISION|OB_DYNAMIC|OB_OCCLUDER);
                break;
        case OB_BODY_TYPE_NO_COLLISION:
-               ob->gameflag &= ~(OB_SENSOR|OB_COLLISION|OB_OCCLUDER|OB_DYNAMIC);
+               ob->gameflag &= ~(OB_SENSOR|OB_COLLISION|OB_OCCLUDER|OB_DYNAMIC|OB_NAVMESH);
                break;
        case OB_BODY_TYPE_STATIC:
                ob->gameflag |= OB_COLLISION;
-               ob->gameflag &= ~(OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY|OB_OCCLUDER|OB_SENSOR);
+               ob->gameflag &= ~(OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY|OB_OCCLUDER|OB_SENSOR|OB_NAVMESH);
                break;
        case OB_BODY_TYPE_DYNAMIC:
                ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_ACTOR;
-               ob->gameflag &= ~(OB_RIGID_BODY|OB_SOFT_BODY|OB_OCCLUDER|OB_SENSOR);
+               ob->gameflag &= ~(OB_RIGID_BODY|OB_SOFT_BODY|OB_OCCLUDER|OB_SENSOR|OB_NAVMESH);
                break;
        case OB_BODY_TYPE_RIGID:
                ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_RIGID_BODY|OB_ACTOR;
-               ob->gameflag &= ~(OB_SOFT_BODY|OB_OCCLUDER|OB_SENSOR);
+               ob->gameflag &= ~(OB_SOFT_BODY|OB_OCCLUDER|OB_SENSOR|OB_NAVMESH);
                break;
        default:
        case OB_BODY_TYPE_SOFT:
                ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_SOFT_BODY|OB_ACTOR;
-               ob->gameflag &= ~(OB_RIGID_BODY|OB_OCCLUDER|OB_SENSOR);
+               ob->gameflag &= ~(OB_RIGID_BODY|OB_OCCLUDER|OB_SENSOR|OB_NAVMESH);
  
                /* assume triangle mesh, if no bounds chosen for soft body */
                if ((ob->gameflag & OB_BOUNDS) && (ob->boundtype<OB_BOUND_POLYH))
@@@ -1269,11 -1265,6 +1275,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);
@@@ -1358,6 -1349,7 +1364,7 @@@ static void rna_def_object_game_setting
                {OB_BODY_TYPE_SOFT, "SOFT_BODY", 0, "Soft Body", "Soft body"},
                {OB_BODY_TYPE_OCCLUDER, "OCCLUDE", 0, "Occlude", "Occluder for optimizing scene rendering"},
                {OB_BODY_TYPE_SENSOR, "SENSOR", 0, "Sensor", "Collision Sensor, detects static and dynamic objects but not the other collision sensor objects"},
+               {OB_BODY_TYPE_NAVMESH, "NAVMESH", 0, "Navigation Mesh", "Navigation mesh"},
                {0, NULL, 0, NULL, NULL}};
  
        srna= RNA_def_struct(brna, "GameObjectSettings", NULL);
        RNA_def_property_pointer_sdna(prop, NULL, "bsoft");
        RNA_def_property_ui_text(prop, "Soft Body Settings", "Settings for Bullet soft body simulation");
  
+       prop= RNA_def_property(srna, "create_obstacle", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "gameflag", OB_HASOBSTACLE);
+       RNA_def_property_ui_text(prop, "Create obstacle", "Create representation for obstacle simulation");
+       prop= RNA_def_property(srna, "obstacle_radius", PROP_FLOAT, PROP_NONE|PROP_UNIT_LENGTH);
+       RNA_def_property_float_sdna(prop, NULL, "obstacleRad");
+       RNA_def_property_range(prop, 0.0, 1000.0);
+       RNA_def_property_ui_text(prop, "Obstacle Radius", "Radius of object representation in obstacle simulation");
+       
        /* state */
  
        prop= RNA_def_property(srna, "states_visible", PROP_BOOLEAN, PROP_LAYER_MEMBER);
@@@ -39,6 -39,7 +39,7 @@@
  #include "DNA_particle_types.h"
  #include "DNA_scene_types.h"
  #include "DNA_userdef_types.h"
+ #include "BLI_math.h"
  
  /* Include for Bake Options */
  #include "RE_pipeline.h"
@@@ -1119,14 -1120,6 +1120,14 @@@ static void rna_def_tool_settings(Blend
        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");
@@@ -1677,6 -1670,96 +1678,96 @@@ void rna_def_render_layer_common(Struct
        else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
  }
  
+ static void rna_def_scene_game_recast_data(BlenderRNA *brna)
+ {
+       StructRNA *srna;
+       PropertyRNA *prop;
+       srna= RNA_def_struct(brna, "SceneGameRecastData", NULL);
+       RNA_def_struct_sdna(srna, "RecastData");
+       RNA_def_struct_nested(brna, srna, "Scene");
+       RNA_def_struct_ui_text(srna, "Recast Data", "Recast data for a Game datablock");
+       prop= RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "cellsize");
+       RNA_def_property_ui_range(prop, 0.1, 1, 1, 2);
+       RNA_def_property_ui_text(prop, "Cell Size", "Rasterized cell size");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "cell_height", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "cellheight");
+       RNA_def_property_ui_range(prop, 0.1, 1, 1, 2);
+       RNA_def_property_ui_text(prop, "Cell Height", "Rasterized cell height");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "agent_height", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "agentheight");
+       RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+       RNA_def_property_ui_text(prop, "Agent Height", "Minimum height where the agent can still walk");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "agent_radius", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "agentradius");
+       RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+       RNA_def_property_ui_text(prop, "Agent Radius", "Radius of the agent");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "max_climb", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "agentmaxclimb");
+       RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+       RNA_def_property_ui_text(prop, "Max Climb", "Maximum height between grid cells the agent can climb");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "max_slope", PROP_FLOAT, PROP_ANGLE);
+       RNA_def_property_float_sdna(prop, NULL, "agentmaxslope");
+       RNA_def_property_range(prop, 0, M_PI/2);
+       RNA_def_property_ui_text(prop, "Max Slope", "Maximum walkable slope angle in degrees");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "region_min_size", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "regionminsize");
+       RNA_def_property_ui_range(prop, 0, 150, 1, 2);
+       RNA_def_property_ui_text(prop, "Min Region Size", "Minimum regions size. Smaller regions will be deleted");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "region_merge_size", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "regionmergesize");
+       RNA_def_property_ui_range(prop, 0, 150, 1, 2);
+       RNA_def_property_ui_text(prop, "Merged Region Size", "Minimum regions size. Smaller regions will be merged");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "edge_max_len", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "edgemaxlen");
+       RNA_def_property_ui_range(prop, 0, 50, 1, 2);
+       RNA_def_property_ui_text(prop, "Max Edge Length", "Maximum contour edge length");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "edge_max_error", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "edgemaxerror");
+       RNA_def_property_ui_range(prop, 0.1, 3.0, 1, 2);
+       RNA_def_property_ui_text(prop, "Max Edge Error", "Maximum distance error from contour to cells");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "verts_per_poly", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "vertsperpoly");
+       RNA_def_property_ui_range(prop, 3, 12, 1, 0);
+       RNA_def_property_ui_text(prop, "Verts Per Poly", "Max number of vertices per polygon");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "sample_dist", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "detailsampledist");
+       RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2);
+       RNA_def_property_ui_text(prop, "Sample Distance", "Detail mesh sample spacing");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "sample_max_error", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "detailsamplemaxerror");
+       RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2);
+       RNA_def_property_ui_text(prop, "Max Sample Error", "Detail mesh simplification max sample error");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+ }
  static void rna_def_scene_game_data(BlenderRNA *brna)
  {
        StructRNA *srna;
                {GAME_MAT_GLSL, "GLSL", 0, "GLSL", "OpenGL shading language shaders"},
                {0, NULL, 0, NULL, NULL}};
  
+       static EnumPropertyItem obstacle_simulation_items[] = {
+               {OBSTSIMULATION_NONE, "NONE", 0, "None", ""},
+               {OBSTSIMULATION_TOI_rays, "RVO (rays)", 0, "RVO (rays)", ""},
+               {OBSTSIMULATION_TOI_cells, "RVO (cells)", 0, "RVO (cells)", ""},
+               {0, NULL, 0, NULL, NULL}};
        srna= RNA_def_struct(brna, "SceneGameData", NULL);
        RNA_def_struct_sdna(srna, "GameData");
        RNA_def_struct_nested(brna, srna, "Scene");
        RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_GLSL_NO_EXTRA_TEX);
        RNA_def_property_ui_text(prop, "GLSL Extra Textures", "Use extra textures like normal or specular maps for GLSL rendering");
        RNA_def_property_update(prop, NC_SCENE|NA_EDITED, "rna_Scene_glsl_update");
+       /* obstacle simulation */
+       prop= RNA_def_property(srna, "obstacle_simulation", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "obstacleSimulation");
+       RNA_def_property_enum_items(prop, obstacle_simulation_items);
+       RNA_def_property_ui_text(prop, "Obstacle simulation", "Simulation used for obstacle avoidance in the game engine");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "level_height", PROP_FLOAT, PROP_ACCELERATION);
+       RNA_def_property_float_sdna(prop, NULL, "levelHeight");
+       RNA_def_property_range(prop, 0.0f, 200.0f);
+       RNA_def_property_ui_text(prop, "Level height", "Max difference in heights of obstacles to enable their interaction");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       prop= RNA_def_property(srna, "show_obstacle_simulation", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_SHOW_OBSTACLE_SIMULATION);
+       RNA_def_property_ui_text(prop, "Visualization", "Enable debug visualization for obstacle simulation");
+       /* Recast Settings */
+       prop= RNA_def_property(srna, "recast_data", PROP_POINTER, PROP_NONE);
+       RNA_def_property_flag(prop, PROP_NEVER_NULL);
+       RNA_def_property_pointer_sdna(prop, NULL, "recastData");
+       RNA_def_property_struct_type(prop, "SceneGameRecastData");
+       RNA_def_property_ui_text(prop, "Recast Data", "");
+       /* Nestled Data  */
+       rna_def_scene_game_recast_data(brna);
  }
  
  static void rna_def_scene_render_layer(BlenderRNA *brna)