svn merge -r 15649:15800 https://svn.blender.org/svnroot/bf-blender/trunk/blender...
authorDaniel Genrich <daniel.genrich@gmx.net>
Sun, 27 Jul 2008 10:46:46 +0000 (10:46 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Sun, 27 Jul 2008 10:46:46 +0000 (10:46 +0000)
1  2 
source/blender/blenkernel/intern/fluidsim.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/src/buttons_editing.c

index 2b7d3d1964225138d7485bd01aef9efc14db283d,0000000000000000000000000000000000000000..3b369e52c439a75b93e6417138fead9e1fd02ba2
mode 100644,000000..100644
--- /dev/null
@@@ -1,710 -1,0 +1,713 @@@
 +/**
 + * fluidsim.c
 + * 
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) Blender Foundation
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): none yet.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "DNA_mesh_types.h"
 +#include "DNA_meshdata_types.h"
 +#include "DNA_object_force.h" // for pointcache 
 +#include "DNA_particle_types.h"
 +#include "DNA_scene_types.h" // N_T
 +
 +#include "BLI_arithb.h"
 +#include "BLI_blenlib.h"
 +
 +#include "BKE_cdderivedmesh.h"
 +#include "BKE_customdata.h"
 +#include "BKE_DerivedMesh.h"
 +#include "BKE_fluidsim.h"
 +#include "BKE_global.h"
 +#include "BKE_modifier.h"
 +#include "BKE_mesh.h"
 +#include "BKE_pointcache.h"
 +#include "BKE_utildefines.h"
 +
 +// headers for fluidsim bobj meshes
 +#include <stdlib.h>
 +#include "LBM_fluidsim.h"
 +#include "elbeem.h"
 +#include <zlib.h>
 +#include <string.h>
 +#include <stdio.h>
 +
 +/* ************************* fluidsim bobj file handling **************************** */
 +
 +#ifndef DISABLE_ELBEEM
 +
 +// -----------------------------------------
 +// forward decleration
 +// -----------------------------------------
 +
 +// -----------------------------------------
 +
 +void fluidsim_init(FluidsimModifierData *fluidmd)
 +{
 +      if(fluidmd)
 +      {
 +              FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");
 +              
 +              fluidmd->fss = fss;
 +              
 +              if(!fss)
 +                      return;
 +              
 +              fss->type = 0;
 +              fss->show_advancedoptions = 0;
 +
 +              fss->resolutionxyz = 50;
 +              fss->previewresxyz = 25;
 +              fss->realsize = 0.03;
 +              fss->guiDisplayMode = 2; // preview
 +              fss->renderDisplayMode = 3; // render
 +
 +              fss->viscosityMode = 2; // default to water
 +              fss->viscosityValue = 1.0;
 +              fss->viscosityExponent = 6;
 +              
 +              // dg TODO: change this to []
 +              fss->gravx = 0.0;
 +              fss->gravy = 0.0;
 +              fss->gravz = -9.81;
 +              fss->animStart = 0.0; 
 +              fss->animEnd = 0.30;
 +              fss->gstar = 0.005; // used as normgstar
 +              fss->maxRefine = -1;
 +              // maxRefine is set according to resolutionxyz during bake
 +
 +              // fluid/inflow settings
 +              // fss->iniVel --> automatically set to 0
 +
 +              /*  elubie: changed this to default to the same dir as the render output
 +              to prevent saving to C:\ on Windows */
 +              BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX);
 +
 +              // first init of bounding box
 +              // no bounding box needed
 +              
 +              // todo - reuse default init from elbeem!
 +              fss->typeFlags = 0;
 +              fss->domainNovecgen = 0;
 +              fss->volumeInitType = 1; // volume
 +              fss->partSlipValue = 0.0;
 +
 +              fss->generateTracers = 0;
 +              fss->generateParticles = 0.0;
 +              fss->surfaceSmoothing = 1.0;
 +              fss->surfaceSubdivs = 1.0;
 +              fss->particleInfSize = 0.0;
 +              fss->particleInfAlpha = 0.0;
 +      
 +              // init fluid control settings
 +              fss->attractforceStrength = 0.2;
 +              fss->attractforceRadius = 0.75;
 +              fss->velocityforceStrength = 0.2;
 +              fss->velocityforceRadius = 0.75;
 +              fss->cpsTimeStart = fss->animStart;
 +              fss->cpsTimeEnd = fss->animEnd;
 +              fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
 +              
 +              /*
 +              BAD TODO: this is done in buttons_object.c in the moment 
 +              Mesh *mesh = ob->data;
 +              // calculate bounding box
 +              fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize); 
 +              */
 +              
 +              fss->lastgoodframe = -1;
 +
 +      }
 +      
 +      return;
 +}
 +
 +void fluidsim_free(FluidsimModifierData *fluidmd)
 +{
 +      if(fluidmd)
 +      {
 +              MEM_freeN(fluidmd->fss);
 +      }
 +      
 +      return;
 +}
 +
 +DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
 +{
 +      DerivedMesh *result = NULL;
 +      int framenr;
 +      FluidsimSettings *fss = NULL;
 +
 +      framenr= (int)G.scene->r.cfra;
 +      
 +      // only handle fluidsim domains
 +      if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN))
 +              return dm;
 +      
 +      // sanity check
 +      if(!fluidmd || (fluidmd && !fluidmd->fss))
 +              return dm;
 +      
 +      fss = fluidmd->fss;
 +      
 +      // timescale not supported yet
 +      // clmd->sim_parms->timescale= timescale;
 +      
 +      /* try to read from cache */
 +      if((result = fluidsim_read_cache(ob, fluidmd, framenr, useRenderParams))) 
 +      {
 +              fss->lastgoodframe = framenr;
 +              return result;
 +      }
 +      else
 +      {       
 +              // display last known good frame
 +              if(fss->lastgoodframe >= 0)
 +              {
 +                      if((result = fluidsim_read_cache(ob, fluidmd, fss->lastgoodframe, useRenderParams))) 
 +                      {
 +                              return result;
 +                      }
++                      
++                      // it was supposed to be a valid frame but it isn't!
++                      fss->lastgoodframe = -1;
 +              }
 +              
 +              result = CDDM_copy(dm);
 +
 +              if(result) 
 +              {
 +                      return result;
 +              }
 +      }
 +      
 +      return dm;
 +}
 +
 +/* read .bobj.gz file into a fluidsimDerivedMesh struct */
 +static DerivedMesh *fluidsim_read_obj(char *filename)
 +{
 +      int wri,i,j;
 +      float wrf;
 +      int gotBytes;
 +      gzFile gzf;
 +      int numverts = 0, numfaces = 0, numedges = 0;
 +      DerivedMesh *dm = NULL;
 +      MFace *mface;
 +      MVert *mvert;
 +      short *normals;
 +              
 +      // ------------------------------------------------
 +      // get numverts + numfaces first
 +      // ------------------------------------------------
 +      gzf = gzopen(filename, "rb");
 +      if (!gzf) 
 +      {
 +              return NULL;
 +      }
 +
 +      // read numverts
 +      gotBytes = gzread(gzf, &wri, sizeof(wri));
 +      numverts = wri;
 +      
 +      // skip verts
 +      for(i=0; i<numverts*3; i++) 
 +      {       
 +              gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
 +      }
 +      
 +      // read number of normals
 +      gotBytes = gzread(gzf, &wri, sizeof(wri));
 +      
 +      // skip normals
 +      for(i=0; i<numverts*3; i++) 
 +      {       
 +              gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
 +      }
 +      
 +      /* get no. of triangles */
 +      gotBytes = gzread(gzf, &wri, sizeof(wri));
 +      numfaces = wri;
 +      
 +      gzclose( gzf );
 +      // ------------------------------------------------
 +      
 +      if(!numfaces || !numverts)
 +              return NULL;
 +      
 +      gzf = gzopen(filename, "rb");
 +      if (!gzf) 
 +      {
 +              return NULL;
 +      }
 +      
 +      dm = CDDM_new(numverts, 0, numfaces);
 +      
 +      if(!dm)
 +      {
 +              gzclose( gzf );
 +              return NULL;
 +      }
 +      
 +      // read numverts
 +      gotBytes = gzread(gzf, &wri, sizeof(wri));
 +
 +      // read vertex position from file
 +      mvert = CDDM_get_verts(dm);
 +      for(i=0; i<numverts; i++) 
 +      {
 +              MVert *mv = &mvert[i];
 +              
 +              for(j=0; j<3; j++) 
 +              {
 +                      gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
 +                      mv->co[j] = wrf;
 +              }
 +      }
 +
 +      // should be the same as numverts
 +      gotBytes = gzread(gzf, &wri, sizeof(wri));
 +      if(wri != numverts) 
 +      {
 +              if(dm)
 +                      dm->release(dm);
 +              gzclose( gzf );
 +              return NULL;
 +      }
 +      
 +      normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" );      
 +      if(!normals)
 +      {
 +              if(dm)
 +                      dm->release(dm);
 +              gzclose( gzf );
 +              return NULL;
 +      }       
 +      
 +      // read normals from file (but don't save them yet)
 +      for(i=0; i<numverts*3; i++) 
 +      { 
 +              gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
 +              normals[i] = (short)(wrf*32767.0f);
 +      }
 +      
 +      /* read no. of triangles */
 +      gotBytes = gzread(gzf, &wri, sizeof(wri));
 +      
 +      if(wri!=numfaces)
 +              printf("Fluidsim: error in reading data from file.\n");
 +      
 +      // read triangles from file
 +      mface = CDDM_get_faces(dm);
 +      for(i=0; i<numfaces; i++) 
 +      {
 +              int face[4];
 +              MFace *mf = &mface[i];
 +
 +              gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); 
 +              gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); 
 +              gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); 
 +              face[3] = 0;
 +
 +              // check if 3rd vertex has index 0 (not allowed in blender)
 +              if(face[2])
 +              {
 +                      mf->v1 = face[0];
 +                      mf->v2 = face[1];
 +                      mf->v3 = face[2];
 +              }
 +              else
 +              {
 +                      mf->v1 = face[1];
 +                      mf->v2 = face[2];
 +                      mf->v3 = face[0];
 +              }
 +              mf->v4 = face[3];
 +              
 +              test_index_face(mf, NULL, 0, 3);
 +      }
 +      
 +      gzclose( gzf );
 +      
 +      CDDM_calc_edges(dm);
 +      
 +      CDDM_apply_vert_normals(dm, (short (*)[3])normals);
 +      MEM_freeN(normals);
 +      
 +      // CDDM_calc_normals(result);
 +
 +      return dm;
 +}
 +
 +DerivedMesh *fluidsim_read_cache(Object *ob, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
 +{
 +      int displaymode = 0;
 +      int curFrame = framenr - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
 +      char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
 +      FluidsimSettings *fss = fluidmd->fss;
 +      DerivedMesh *dm = NULL;
 +      
 +      if(!useRenderParams) {
 +              displaymode = fss->guiDisplayMode;
 +      } else {
 +              displaymode = fss->renderDisplayMode;
 +      }
 +
 +      strncpy(targetDir, fss->surfdataPath, FILE_MAXDIR);
 +      
 +      // use preview or final mesh?
 +      if(displaymode==1) 
 +      {
 +              // just display original object
 +              return NULL;
 +      } 
 +      else if(displaymode==2) 
 +      {
 +              strcat(targetDir,"fluidsurface_preview_####");
 +      } 
 +      else 
 +      { // 3
 +              strcat(targetDir,"fluidsurface_final_####");
 +      }
 +      
 +      BLI_convertstringcode(targetDir, G.sce);
 +      BLI_convertstringframe(targetDir, curFrame); // fixed #frame-no 
 +      
 +      strcpy(targetFile,targetDir);
 +      strcat(targetFile, ".bobj.gz");
 +
 +      dm = fluidsim_read_obj(targetFile);
 +      
 +      if(!dm) 
 +      {       
 +              // switch, abort background rendering when fluidsim mesh is missing
 +              const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
 +              
 +              if(G.background==1) {
 +                      if(getenv(strEnvName2)) {
 +                              int elevel = atoi(getenv(strEnvName2));
 +                              if(elevel>0) {
 +                                      printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
 +                                      exit(1);
 +                              }
 +                      }
 +              }
 +              
 +              // display org. object upon failure which is in dm
 +              return NULL;
 +      }
 +
 +      // load vertex velocities, if they exist...
 +      // TODO? use generate flag as loading flag as well?
 +      // warning, needs original .bobj.gz mesh loading filename
 +      /*
 +      if(displaymode==3) 
 +      {
 +              readVelgz(targetFile, srcob);
 +      } 
 +      else 
 +      {
 +              // no data for preview, only clear...
 +              int i,j;
 +              for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }} 
 +      }*/
 +      
 +      return dm;
 +}
 +
 +void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
 +               /*RET*/ float start[3], /*RET*/ float size[3] )
 +{
 +      float bbsx=0.0, bbsy=0.0, bbsz=0.0;
 +      float bbex=1.0, bbey=1.0, bbez=1.0;
 +      int i;
 +      float vec[3];
 +
 +      VECCOPY(vec, mvert[0].co); 
 +      Mat4MulVecfl(obmat, vec);
 +      bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
 +      bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
 +
 +      for(i = 1; i < totvert; i++) {
 +              VECCOPY(vec, mvert[i].co);
 +              Mat4MulVecfl(obmat, vec);
 +
 +              if(vec[0] < bbsx){ bbsx= vec[0]; }
 +              if(vec[1] < bbsy){ bbsy= vec[1]; }
 +              if(vec[2] < bbsz){ bbsz= vec[2]; }
 +              if(vec[0] > bbex){ bbex= vec[0]; }
 +              if(vec[1] > bbey){ bbey= vec[1]; }
 +              if(vec[2] > bbez){ bbez= vec[2]; }
 +      }
 +
 +      // return values...
 +      if(start) {
 +              start[0] = bbsx;
 +              start[1] = bbsy;
 +              start[2] = bbsz;
 +      } 
 +      if(size) {
 +              size[0] = bbex-bbsx;
 +              size[1] = bbey-bbsy;
 +              size[2] = bbez-bbsz;
 +      }
 +}
 +
 +//-------------------------------------------------------------------------------
 +// old interface
 +//-------------------------------------------------------------------------------
 +
 +
 +
 +//-------------------------------------------------------------------------------
 +// file handling
 +//-------------------------------------------------------------------------------
 +
 +
 +/* write .bobj.gz file for a mesh object */
 +void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time) 
 +{
 +      int wri,i,j,totvert,totface;
 +      float wrf;
 +      gzFile gzf;
 +      DerivedMesh *dm;
 +      float vec[3];
 +      float rotmat[3][3];
 +      MVert *mvert;
 +      MFace *mface;
 +      //if(append)return; // DEBUG
 +
 +      if(!ob->data || (ob->type!=OB_MESH)) 
 +      {
 +              return;
 +      }
 +      if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) 
 +      {
 +              return;
 +      }
 +
 +      if(append) gzf = gzopen(filename, "a+b9");
 +      else       gzf = gzopen(filename, "wb9");
 +      
 +      if (!gzf) 
 +              return;
 +
 +      dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
 +      //dm = mesh_create_derived_no_deform(ob,NULL);
 +
 +      mvert = dm->getVertArray(dm);
 +      mface = dm->getFaceArray(dm);
 +      totvert = dm->getNumVerts(dm);
 +      totface = dm->getNumFaces(dm);
 +
 +      // write time value for appended anim mesh
 +      if(append) 
 +      {
 +              gzwrite(gzf, &time, sizeof(time));
 +      }
 +
 +      // continue with verts/norms
 +      if(sizeof(wri)!=4) { return; } // paranoia check
 +      wri = dm->getNumVerts(dm);
 +      mvert = dm->getVertArray(dm);
 +      gzwrite(gzf, &wri, sizeof(wri));
 +      for(i=0; i<wri;i++) 
 +      {
 +              VECCOPY(vec, mvert[i].co);
 +              if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, vec); }
 +              for(j=0; j<3; j++) {
 +                      wrf = vec[j]; 
 +                      gzwrite(gzf, &wrf, sizeof( wrf )); 
 +              }
 +      }
 +
 +      // should be the same as Vertices.size
 +      wri = totvert;
 +      gzwrite(gzf, &wri, sizeof(wri));
 +      EulToMat3(ob->rot, rotmat);
 +      for(i=0; i<wri;i++) 
 +      {
 +              VECCOPY(vec, mvert[i].no);
 +              Normalize(vec);
 +              if(useGlobalCoords) { Mat3MulVecfl(rotmat, vec); }
 +              for(j=0; j<3; j++) {
 +                      wrf = vec[j];
 +                      gzwrite(gzf, &wrf, sizeof( wrf )); 
 +              }
 +      }
 +
 +      // append only writes verts&norms 
 +      if(!append) {
 +              // compute no. of triangles 
 +              wri = 0;
 +              for(i=0; i<totface; i++) 
 +              {
 +                      wri++;
 +                      if(mface[i].v4) { wri++; }
 +              }
 +              gzwrite(gzf, &wri, sizeof(wri));
 +              for(i=0; i<totface; i++) 
 +              {
 +
 +                      int face[4];
 +                      face[0] = mface[i].v1;
 +                      face[1] = mface[i].v2;
 +                      face[2] = mface[i].v3;
 +                      face[3] = mface[i].v4;
 +
 +                      gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
 +                      gzwrite(gzf, &(face[1]), sizeof( face[1] )); 
 +                      gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
 +                      if(face[3]) 
 +                      { 
 +                              gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
 +                              gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
 +                              gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
 +                      } // quad
 +              }
 +      }
 +      
 +      gzclose( gzf );
 +      dm->release(dm);
 +}
 +
 +void initElbeemMesh(struct Object *ob, 
 +                  int *numVertices, float **vertices, 
 +      int *numTriangles, int **triangles,
 +      int useGlobalCoords) 
 +{
 +      DerivedMesh *dm = NULL;
 +      MVert *mvert;
 +      MFace *mface;
 +      int countTris=0, i, totvert, totface;
 +      float *verts;
 +      int *tris;
 +
 +      dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
 +      //dm = mesh_create_derived_no_deform(ob,NULL);
 +
 +      mvert = dm->getVertArray(dm);
 +      mface = dm->getFaceArray(dm);
 +      totvert = dm->getNumVerts(dm);
 +      totface = dm->getNumFaces(dm);
 +
 +      *numVertices = totvert;
 +      verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
 +      for(i=0; i<totvert; i++) {
 +              VECCOPY( &verts[i*3], mvert[i].co);
 +              if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
 +      }
 +      *vertices = verts;
 +
 +      for(i=0; i<totface; i++) {
 +              countTris++;
 +              if(mface[i].v4) { countTris++; }
 +      }
 +      *numTriangles = countTris;
 +      tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
 +      countTris = 0;
 +      for(i=0; i<totface; i++) {
 +              int face[4];
 +              face[0] = mface[i].v1;
 +              face[1] = mface[i].v2;
 +              face[2] = mface[i].v3;
 +              face[3] = mface[i].v4;
 +
 +              tris[countTris*3+0] = face[0]; 
 +              tris[countTris*3+1] = face[1]; 
 +              tris[countTris*3+2] = face[2]; 
 +              countTris++;
 +              if(face[3]) { 
 +                      tris[countTris*3+0] = face[0]; 
 +                      tris[countTris*3+1] = face[2]; 
 +                      tris[countTris*3+2] = face[3]; 
 +                      countTris++;
 +              }
 +      }
 +      *triangles = tris;
 +
 +      dm->release(dm);
 +}
 +
 +/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
 +void readVelgz(char *filename, Object *srcob)
 +{
 +      int wri, i, j;
 +      float wrf;
 +      gzFile gzf;
 +      MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
 +      int len = strlen(filename);
 +      Mesh *mesh = srcob->data;
 +      // mesh and vverts have to be valid from loading...
 +
 +      // clean up in any case
 +      for(i=0; i<mesh->totvert;i++) 
 +      { 
 +              for(j=0; j<3; j++) 
 +              {
 +                      vverts[i].co[j] = 0.; 
 +              } 
 +      } 
 +      if(srcob->fluidsimSettings->domainNovecgen>0) return;
 +
 +      if(len<7) 
 +      { 
 +              return; 
 +      }
 +
 +      // .bobj.gz , correct filename
 +      // 87654321
 +      filename[len-6] = 'v';
 +      filename[len-5] = 'e';
 +      filename[len-4] = 'l';
 +
 +      gzf = gzopen(filename, "rb");
 +      if (!gzf)
 +              return;
 +
 +      gzread(gzf, &wri, sizeof( wri ));
 +      if(wri != mesh->totvert) 
 +      {
 +              return; 
 +      }
 +
 +      for(i=0; i<mesh->totvert;i++) 
 +      {
 +              for(j=0; j<3; j++) 
 +              {
 +                      gzread(gzf, &wrf, sizeof( wrf )); 
 +                      vverts[i].co[j] = wrf;
 +              }
 +      }
 +
 +      gzclose(gzf);
 +}
 +
 +
 +#endif // DISABLE_ELBEEM
 +
index 6973ad51e4345331adef321c41c0a89a877f1c2e,7dca87d5c135ad53b2de60acda7a7af89b365e44..2149e541263fb1e3650b7dd3ea19cb95b20f7237
@@@ -2797,7 -2797,10 +2797,10 @@@ void do_effectors(int pa_no, ParticleDa
                                epart= epsys->part;
                                pd= epart->pd;
                                totepart= epsys->totpart;
+                               
+                               if(totepart <= 0)
+                                       continue;
+                               
                                if(pd->forcefield==PFIELD_HARMONIC){
                                        /* every particle is mapped to only one harmonic effector particle */
                                        p= pa_no%epsys->totpart;
@@@ -4540,7 -4543,7 +4543,7 @@@ void psys_changed_type(ParticleSystem *
  }
  
  static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
 -{
 +{     
        if(psys->particles){
                MEM_freeN(psys->particles);
                psys->particles = 0;
  
        /* fluid sim particle import handling, actual loading of particles from file */
        #ifndef DISABLE_ELBEEM
 -      if( (1) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&  // broken, disabled for now!
 -              (ob->fluidsimSettings)) { 
 -              ParticleSettings *part = psys->part;
 -              ParticleData *pa=0;
 -              char *suffix  = "fluidsurface_particles_####";
 -              char *suffix2 = ".gz";
 -              char filename[256];
 -              char debugStrBuffer[256];
 -              int  curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
 -              int  p, j, numFileParts, totpart;
 -              int readMask, activeParts = 0, fileParts = 0;
 -              gzFile gzf;
 -
 -              if(ob==G.obedit) // off...
 -                      return;
 -
 -              // ok, start loading
 -              strcpy(filename, ob->fluidsimSettings->surfdataPath);
 -              strcat(filename, suffix);
 -              BLI_convertstringcode(filename, G.sce);
 -              BLI_convertstringframe(filename, curFrame); // fixed #frame-no 
 -              strcat(filename, suffix2);
 -
 -              gzf = gzopen(filename, "rb");
 -              if (!gzf) {
 -                      snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); 
 -                      //elbeemDebugOut(debugStrBuffer);
 -                      return;
 -              }
 -
 -              gzread(gzf, &totpart, sizeof(totpart));
 -              numFileParts = totpart;
 -              totpart = (G.rendering)?totpart:(part->disp*totpart)/100;
 +      {
 +              FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
                
 -              part->totpart= totpart;
 -              part->sta=part->end = 1.0f;
 -              part->lifetime = G.scene->r.efra + 1;
 -
 -              /* initialize particles */
 -              realloc_particles(ob, psys, part->totpart);
 -              initialize_all_particles(ob, psys, 0);
 -
 -              // set up reading mask
 -              readMask = ob->fluidsimSettings->typeFlags;
 -              
 -              for(p=0, pa=psys->particles; p<totpart; p++, pa++) {
 -                      int ptype=0;
 -
 -                      gzread(gzf, &ptype, sizeof( ptype )); 
 -                      if(ptype&readMask) {
 -                              activeParts++;
 -
 -                              gzread(gzf, &(pa->size), sizeof( float )); 
 -
 -                              pa->size /= 10.0f;
 -
 -                              for(j=0; j<3; j++) {
 -                                      float wrf;
 -                                      gzread(gzf, &wrf, sizeof( wrf )); 
 -                                      pa->state.co[j] = wrf;
 -                                      //fprintf(stderr,"Rj%d ",j);
 -                              }
 -                              for(j=0; j<3; j++) {
 -                                      float wrf;
 -                                      gzread(gzf, &wrf, sizeof( wrf )); 
 -                                      pa->state.vel[j] = wrf;
 -                              }
 -
 -                              pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
 -                              pa->state.rot[0] = 1.0;
 -                              pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0;
 -
 -                              pa->alive = PARS_ALIVE;
 -                              //if(a<25) fprintf(stderr,"FSPARTICLE debug set %s , a%d = %f,%f,%f , life=%f \n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime );
 -                      } else {
 -                              // skip...
 -                              for(j=0; j<2*3+1; j++) {
 -                                      float wrf; gzread(gzf, &wrf, sizeof( wrf )); 
 +              if( fluidmd && fluidmd->fss) { 
 +                      FluidsimSettings *fss= fluidmd->fss;
 +                      ParticleSettings *part = psys->part;
 +                      ParticleData *pa=0;
 +                      char *suffix  = "fluidsurface_particles_####";
 +                      char *suffix2 = ".gz";
 +                      char filename[256];
 +                      char debugStrBuffer[256];
 +                      int  curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
 +                      int  p, j, numFileParts, totpart;
 +                      int readMask, activeParts = 0, fileParts = 0;
 +                      gzFile gzf;
 +      
 +                      if(ob==G.obedit) // off...
 +                              return;
 +      
 +                      // ok, start loading
 +                      strcpy(filename, fss->surfdataPath);
 +                      strcat(filename, suffix);
 +                      BLI_convertstringcode(filename, G.sce);
 +                      BLI_convertstringframe(filename, curFrame); // fixed #frame-no 
 +                      strcat(filename, suffix2);
 +      
 +                      gzf = gzopen(filename, "rb");
 +                      if (!gzf) {
 +                              snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); 
 +                              //elbeemDebugOut(debugStrBuffer);
 +                              return;
 +                      }
 +      
 +                      gzread(gzf, &totpart, sizeof(totpart));
 +                      numFileParts = totpart;
 +                      totpart = (G.rendering)?totpart:(part->disp*totpart)/100;
 +                      
 +                      part->totpart= totpart;
 +                      part->sta=part->end = 1.0f;
 +                      part->lifetime = G.scene->r.efra + 1;
 +      
 +                      /* initialize particles */
 +                      realloc_particles(ob, psys, part->totpart);
 +                      initialize_all_particles(ob, psys, 0);
 +      
 +                      // set up reading mask
 +                      readMask = fss->typeFlags;
 +                      
 +                      for(p=0, pa=psys->particles; p<totpart; p++, pa++) {
 +                              int ptype=0;
 +      
 +                              gzread(gzf, &ptype, sizeof( ptype )); 
 +                              if(ptype&readMask) {
 +                                      activeParts++;
 +      
 +                                      gzread(gzf, &(pa->size), sizeof( float )); 
 +      
 +                                      pa->size /= 10.0f;
 +      
 +                                      for(j=0; j<3; j++) {
 +                                              float wrf;
 +                                              gzread(gzf, &wrf, sizeof( wrf )); 
 +                                              pa->state.co[j] = wrf;
 +                                              //fprintf(stderr,"Rj%d ",j);
 +                                      }
 +                                      for(j=0; j<3; j++) {
 +                                              float wrf;
 +                                              gzread(gzf, &wrf, sizeof( wrf )); 
 +                                              pa->state.vel[j] = wrf;
 +                                      }
 +      
 +                                      pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
 +                                      pa->state.rot[0] = 1.0;
 +                                      pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0;
 +      
 +                                      pa->alive = PARS_ALIVE;
 +                                      //if(a<25) fprintf(stderr,"FSPARTICLE debug set %s , a%d = %f,%f,%f , life=%f \n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime );
 +                              } else {
 +                                      // skip...
 +                                      for(j=0; j<2*3+1; j++) {
 +                                              float wrf; gzread(gzf, &wrf, sizeof( wrf )); 
 +                                      }
                                }
 +                              fileParts++;
                        }
 -                      fileParts++;
 -              }
 -              gzclose( gzf );
 -
 -              totpart = psys->totpart = activeParts;
 -              snprintf(debugStrBuffer,256,"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d  \n", psys->totpart,activeParts,fileParts,readMask);
 -              elbeemDebugOut(debugStrBuffer);
 -      } // fluid sim particles done
 +                      gzclose( gzf );
 +      
 +                      totpart = psys->totpart = activeParts;
 +                      snprintf(debugStrBuffer,256,"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d  \n", psys->totpart,activeParts,fileParts,readMask);
 +                      elbeemDebugOut(debugStrBuffer);
 +              } // fluid sim particles done
 +      }
        #endif // DISABLE_ELBEEM
  }
  
index c7927f7d4ebe97b9d82489d0fd7b7283758ff2d6,ad004dd5c8216509e59c967dec8cadf947351978..65c5aad43a71410be9e3ef8a9c486ce3a3fb788c
@@@ -69,6 -69,7 +69,7 @@@
  #include "DNA_effect_types.h"
  #include "DNA_fileglobal_types.h"
  #include "DNA_group_types.h"
+ #include "DNA_gpencil_types.h"
  #include "DNA_ipo_types.h"
  #include "DNA_image_types.h"
  #include "DNA_key_types.h"
@@@ -1346,8 -1347,14 +1347,14 @@@ void IDP_DirectLinkArray(IDProperty *pr
        prop->data.pointer = newdataadr(fd, prop->data.pointer);
  
        if (switch_endian) {
-               for (i=0; i<prop->len; i++) {
-                       SWITCH_INT(((int*)prop->data.pointer)[i]);
+               if (prop->subtype != IDP_DOUBLE) {
+                       for (i=0; i<prop->len; i++) {
+                               SWITCH_INT(((int*)prop->data.pointer)[i]);
+                       }
+               } else {
+                       for (i=0; i<prop->len; i++) {
+                               SWITCH_LONGINT(((double*)prop->data.pointer)[i]);
+                       }
                }
        }
  }
@@@ -1383,6 -1390,24 +1390,24 @@@ void IDP_DirectLinkProperty(IDProperty 
                        break;
                case IDP_ARRAY:
                        IDP_DirectLinkArray(prop, switch_endian, fd);
+                       break;
+               case IDP_DOUBLE:
+                       /*erg, stupid doubles.  since I'm storing them
+                        in the same field as int val; val2 in the
+                        IDPropertyData struct, they have to deal with
+                        endianness specifically
+                        
+                        in theory, val and val2 would've already been swapped
+                        if switch_endian is true, so we have to first unswap
+                        them then reswap them as a single 64-bit entity.
+                        */
+                       
+                       if (switch_endian) {
+                               SWITCH_INT(prop->data.val);
+                               SWITCH_INT(prop->data.val2);
+                               SWITCH_LONGINT(prop->data.val);
+                       }
+                       
                        break;
        }
  }
@@@ -3016,6 -3041,10 +3041,6 @@@ static void lib_link_object(FileData *f
                                }
                                act= act->next;
                        }
 -
 -                      if(ob->fluidsimSettings) {
 -                              ob->fluidsimSettings->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo);
 -                      }
                        
                        /* texture field */
                        if(ob->pd)
@@@ -3089,12 -3118,6 +3114,12 @@@ static void direct_link_modifiers(FileD
                        }
                        
                }
 +              else if (md->type==eModifierType_Fluidsim) {
 +                      FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
 +                      
 +                      fluidmd->fss= newdataadr(fd, fluidmd->fss);
 +                      fluidmd->fss->ipo = newlibadr_us(fd, lb, fluidmd->fss->ipo);
 +              }
                else if (md->type==eModifierType_Collision) {
                        
                        CollisionModifierData *collmd = (CollisionModifierData*) md;
@@@ -3281,6 -3304,13 +3306,6 @@@ static void direct_link_object(FileDat
                        direct_link_pointcache(fd, sb->pointcache);
        }
        ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
 -      if(ob->fluidsimSettings) {
 -              // reinit mesh pointers
 -              ob->fluidsimSettings->orgMesh = NULL; //ob->data;
 -              ob->fluidsimSettings->meshSurface = NULL;
 -              ob->fluidsimSettings->meshBB = NULL;
 -              ob->fluidsimSettings->meshSurfNormals = NULL;
 -      }
  
        link_list(fd, &ob->particlesystem);
        direct_link_particlesystems(fd,&ob->particlesystem);
@@@ -3693,6 -3723,32 +3718,32 @@@ static void lib_link_screen_sequence_ip
  
  /* ************ READ SCREEN ***************** */
  
+ /* relinks grease-pencil data for 3d-view(s) - used for direct_link */
+ static void link_gpencil(FileData *fd, bGPdata *gpd)
+ {
+       bGPDlayer *gpl;
+       bGPDframe *gpf;
+       bGPDstroke *gps;
+       
+       /* relink layers */
+       link_list(fd, &gpd->layers);
+       
+       for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+               /* relink frames */
+               link_list(fd, &gpl->frames);
+               gpl->actframe= newdataadr(fd, gpl->actframe);
+               
+               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+                       /* relink strokes (and their points) */
+                       link_list(fd, &gpf->strokes);
+                       
+                       for (gps= gpf->strokes.first; gps; gps= gps->next) {
+                               gps->points= newdataadr(fd, gps->points);
+                       }
+               }
+       }
+ }
  /* note: file read without screens option G_FILE_NO_UI; 
     check lib pointers in call below */
  static void lib_link_screen(FileData *fd, Main *main)
                if(sc->id.flag & LIB_NEEDLINK) {
                        sc->id.us= 1;
                        sc->scene= newlibadr(fd, sc->id.lib, sc->scene);
+                       
                        sa= sc->areabase.first;
                        while(sa) {
                                SpaceLink *sl;
+                               
                                sa->full= newlibadr(fd, sc->id.lib, sa->full);
+                               
                                /* space handler scriptlinks */
                                lib_link_scriptlink(fd, &sc->id, &sa->scriptlink);
+                               
                                for (sl= sa->spacedata.first; sl; sl= sl->next) {
                                        if(sl->spacetype==SPACE_VIEW3D) {
                                                View3D *v3d= (View3D*) sl;
+                                               
                                                v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
                                                v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
+                                               
                                                if(v3d->bgpic) {
                                                        v3d->bgpic->ima= newlibadr_us(fd, sc->id.lib, v3d->bgpic->ima);
                                                }
@@@ -4076,6 -4132,10 +4127,10 @@@ static void direct_link_screen(FileDat
                                v3d->bgpic= newdataadr(fd, v3d->bgpic);
                                if(v3d->bgpic)
                                        v3d->bgpic->iuser.ok= 1;
+                               if(v3d->gpd) {
+                                       v3d->gpd= newdataadr(fd, v3d->gpd);
+                                       link_gpencil(fd, v3d->gpd);
+                               }
                                v3d->localvd= newdataadr(fd, v3d->localvd);
                                v3d->afterdraw.first= v3d->afterdraw.last= NULL;
                                v3d->clipbb= newdataadr(fd, v3d->clipbb);
                        }
                        else if(sl->spacetype==SPACE_NODE) {
                                SpaceNode *snode= (SpaceNode *)sl;
+                               
+                               if(snode->gpd) {
+                                       snode->gpd= newdataadr(fd, snode->gpd);
+                                       link_gpencil(fd, snode->gpd);
+                               }
                                snode->nodetree= snode->edittree= NULL;
                                snode->flag |= SNODE_DO_PREVIEW;
                        }
+                       else if(sl->spacetype==SPACE_SEQ) {
+                               SpaceSeq *sseq= (SpaceSeq *)sl;
+                               if(sseq->gpd) {
+                                       sseq->gpd= newdataadr(fd, sseq->gpd);
+                                       link_gpencil(fd, sseq->gpd);
+                               }
+                       }
                }
  
                sa->v1= newdataadr(fd, sa->v1);
@@@ -7488,12 -7560,8 +7555,12 @@@ static void do_versions(FileData *fd, L
                                        }
                                }
  
 -                              if(ob->fluidsimSettings && ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)
 -                                      part->type = PART_FLUID;
 +                              
 +                              {
 +                                      FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
 +                                      if(fluidmd && fluidmd->fss && fluidmd->fss->type == OB_FLUIDSIM_PARTICLE)
 +                                              part->type = PART_FLUID;
 +                              }
  
                                free_effects(&ob->effect);
  
                        la->sun_intensity = 1.0;
                }
        }
 +      
 +      // convert fluids to modifier
 +      if(main->versionfile <= 246 && main->subversionfile < 1)
 +      {
 +              Object *ob;
 +              
 +              for(ob = main->object.first; ob; ob= ob->id.next) {
 +                      if(ob->fluidsimSettings)
 +                      {
 +                              FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifier_new(eModifierType_Fluidsim);
 +                              BLI_addhead(&ob->modifiers, (ModifierData *)fluidmd);
 +                              
 +                              MEM_freeN(fluidmd->fss);
 +                              fluidmd->fss = MEM_dupallocN(ob->fluidsimSettings);
 +                              fluidmd->fss->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo);
 +                              MEM_freeN(ob->fluidsimSettings);
 +                      }
 +              }
 +      }
 +      
  
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
index b47642b6a6fff355612924b9c24c867fda05b5ee,73abf362d12d9d0875c8660ac76f01f488fab08b..081aed2ef39668f39efade10381a9dac6fb38e20
@@@ -112,6 -112,7 +112,7 @@@ Important to know is that 'streaming' h
  #include "DNA_customdata_types.h"
  #include "DNA_effect_types.h"
  #include "DNA_group_types.h"
+ #include "DNA_gpencil_types.h"
  #include "DNA_image_types.h"
  #include "DNA_ipo_types.h"
  #include "DNA_fileglobal_types.h"
@@@ -532,6 -533,7 +533,7 @@@ static void write_particlesettings(Writ
                if(part->id.us>0 || wd->current) {
                        /* write LibData */
                        writestruct(wd, ID_PA, "ParticleSettings", 1, part);
+                       if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
                        writestruct(wd, DATA, "PartDeflect", 1, part->pd);
                }
                part= part->id.next;
@@@ -846,11 -848,6 +848,11 @@@ static void write_modifiers(WriteData *
                        writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
                        writestruct(wd, DATA, "PointCache", 1, clmd->point_cache);
                } 
 +              else if(md->type==eModifierType_Fluidsim) {
 +                      FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
 +                      
 +                      writestruct(wd, DATA, "FluidsimSettings", 1, fluidmd->fss);
 +              } 
                else if (md->type==eModifierType_Collision) {
                        
                        /*
@@@ -916,6 -913,7 +918,6 @@@ static void write_objects(WriteData *wd
                        writestruct(wd, DATA, "PartDeflect", 1, ob->pd);
                        writestruct(wd, DATA, "SoftBody", 1, ob->soft);
                        if(ob->soft) writestruct(wd, DATA, "PointCache", 1, ob->soft->pointcache);
 -                      writestruct(wd, DATA, "FluidsimSettings", 1, ob->fluidsimSettings); // NT
                        
                        write_particlesystems(wd, &ob->particlesystem);
                        write_modifiers(wd, &ob->modifiers);
@@@ -1569,6 -1567,32 +1571,32 @@@ static void write_scenes(WriteData *wd
        mywrite(wd, MYWRITE_FLUSH, 0);
  }
  
+ static void write_gpencil(WriteData *wd, bGPdata *gpd)
+ {
+       bGPDlayer *gpl;
+       bGPDframe *gpf;
+       bGPDstroke *gps;
+       
+       /* write gpd data block to file */
+       writestruct(wd, DATA, "bGPdata", 1, gpd);
+       
+       /* write grease-pencil layers to file */
+       for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+               writestruct(wd, DATA, "bGPDlayer", 1, gpl);
+               
+               /* write this layer's frames to file */
+               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+                       writestruct(wd, DATA, "bGPDframe", 1, gpf);
+                       
+                       /* write strokes */
+                       for (gps= gpf->strokes.first; gps; gps= gps->next) {
+                               writestruct(wd, DATA, "bGPDstroke", 1, gps);
+                               writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points);                               
+                       }
+               }
+       }
+ }
  static void write_screens(WriteData *wd, ListBase *scrbase)
  {
        bScreen *sc;
                        sl= sa->spacedata.first;
                        while(sl) {
                                if(sl->spacetype==SPACE_VIEW3D) {
-                                       View3D *v3d= (View3D*) sl;
+                                       View3D *v3d= (View3D *) sl;
                                        writestruct(wd, DATA, "View3D", 1, v3d);
                                        if(v3d->bgpic) writestruct(wd, DATA, "BGpic", 1, v3d->bgpic);
                                        if(v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
                                        if(v3d->clipbb) writestruct(wd, DATA, "BoundBox", 1, v3d->clipbb);
+                                       if(v3d->gpd) write_gpencil(wd, v3d->gpd);
                                }
                                else if(sl->spacetype==SPACE_IPO) {
                                        writestruct(wd, DATA, "SpaceIpo", 1, sl);
                                        writestruct(wd, DATA, "SpaceFile", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_SEQ) {
+                                       SpaceSeq *sseq= (SpaceSeq *)sl;
                                        writestruct(wd, DATA, "SpaceSeq", 1, sl);
+                                       if(sseq->gpd) write_gpencil(wd, sseq->gpd);
                                }
                                else if(sl->spacetype==SPACE_OOPS) {
                                        SpaceOops *so= (SpaceOops *)sl;
                                        writestruct(wd, DATA, "SpaceTime", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_NODE){
+                                       SpaceNode *snode= (SpaceNode *)sl;
                                        writestruct(wd, DATA, "SpaceNode", 1, sl);
+                                       if(snode->gpd) write_gpencil(wd, snode->gpd);
                                }
                                sl= sl->next;
                        }
index f058db9e835760f5a0e67a7e629de3ea9523881a,180fdc852aea68c160bcb28ddf676ad3043f0b0b..66adc1b603ce64be71e1cc1a9fe5b38c3c3a6005
@@@ -985,7 -985,7 +985,7 @@@ static uiBlock *modifiers_add_menu(voi
                /* Only allow adding through appropriate other interfaces */
                if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
                
 -              if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
 +              if(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim)) continue;
  
                if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
                   (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@@@ -1742,7 -1742,7 +1742,7 @@@ static void draw_modifier(uiBlock *bloc
                
                // deletion over the deflection panel
                // fluid particle modifier can't be deleted here
 -              if(md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
 +              if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
                {
                        but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
                        uiButSetFunc(but, modifiers_del, ob, md);
                        height = 94;
                } else if (md->type==eModifierType_Explode) {
                        height = 94;
 +              } else if (md->type==eModifierType_Fluidsim) {
 +                      height = 31;
                }
                                                        /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
                uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
                                uiButSetFunc(but, modifiers_applyModifier, ob, md);
                        }
                        
 -                      if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
 +                      if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
                                but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy",   lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
                                uiButSetFunc(but, modifiers_copyModifier, ob, md);
                        }
                        uiBlockBeginAlign(block);
                        uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
                                          lx, (cy -= 19), buttonWidth, 19, &bmd->value,
-                                         0.0, 0.5, 5, 2,
+                                         0.0, 0.5, 5, 4,
                                          "Bevel value/amount");
                        /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
                                          lx, (cy -= 19), buttonWidth, 19, &bmd->res,
@@@ -4373,11 -4371,12 +4373,12 @@@ static void editing_panel_armature_bone
                        uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", 225, by-19,105, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
                        
                        /* bone types */
-                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",         -10,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
-                       uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",          70,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
-                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   90, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
-                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 170,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
-                       uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide",   250,by-38,80,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",         -10,by-38,60,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
+                       uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",          50,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
+                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   70, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
+                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 150,by-38,60,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
+                       uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide",   210,by-38,60,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+                       uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, REDRAWVIEW3D, "Lock",    270,by-38,60,18, &curBone->flag, 0, 0, 0, 0, "Prevents this bone from being transformed in Edit Mode");
                        
                        /* layers */
                        uiBlockBeginAlign(block);