External cache
authorJanne Karhu <jhkarh@gmail.com>
Thu, 23 Jul 2009 00:19:01 +0000 (00:19 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Thu, 23 Jul 2009 00:19:01 +0000 (00:19 +0000)
Particle point cache can now be loaded from external files.
- Activated by "external" checkbox in cache panel and giving proper folder path and file name identifier.
- External cache panel has controls for particle emission start, end, lifetime and random lifetime. These should be set according to the external data for correct playback.
- External files should be named "identifier_frame_index.bphys" or "identifier_frame.bphys" where:
* "identifier" is a freely choseable name.
* "frame" is the cached frame number.
** Six digits padded with zeros!, for example "000024".
* "index" can be used to tell caches with the same identifier apart.
** Two digits starting from zero.
** The index and the underscore before are optional. If no index is present the index number in ui should be set to -1.
- Cache file format is pure floating point numbers (in binary, not text!) with each particle's data one after the other with the following data members:
* 3 floats: particle's location vector
* 3 floats: particle's velocity vector (per second)
* 4 floats: particle's rotation quaternion
* 3 floats: particle's angular velocity vector (per second)
* 1 float: frame of the actual data (this can be non-integer for particles that are born or die between two integer frames, but otherwise should be the same as the "frame" in the file name)
- Cache files don't have to exist for each frame.
* Frames without actual data are interpolated from surrounding frames that have data (extrapolation is not supported).
- Cache file formats with extended (or reduced even) data members are in future plans for easier usage.
- Current code only does particles, don't yet know if it's applicable to cloth or sb.
- Known issue: endianness can't yet be handled in any way.

Other changes:

New hard limits for many particle parameters. Some examples:
- Maximum amount of particles: 10M particles :) And before you all go and crash your Blender trying this out remember that this limit is only for those freaks who really have the machine power to handle it. 10M particles alone take around 2.2 Gb of memory / disk space in saved file and each cached frame takes around 0.5 Gb of memory / disk space depending on cache mode.
* Known issue: To actually use this many particles they most likely need to be allocated in parts as taking hold of a 2.2Gb chunk of memory at once is probably not ok with any operating system.
- Maximum amount of children: 100k children/particle (1T childparticles here we come :D)
- Kink frequency: -100k to 100k half-rotations (really strange the previous limit was only from zero upwards)
- Path draw steps: 10 (power of 2 remember)
- Path render steps: 20 (power of 2 also!! If over 1M segments doesn't get you smooth paths then I think nothing will!)

release/ui/buttons_particle.py
source/blender/blenkernel/BKE_pointcache.h
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_particle.c

index 47d325a59403bc96726b91059f7b65d3be21fced..f74dfa06427628daf7821ab17ada6e90035dbe7e 100644 (file)
@@ -86,6 +86,12 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
        __idname__= "PARTICLE_PT_emission"
        __label__ = "Emission"
        
+       def poll(self, context):
+               if particle_panel_poll(context):
+                       return not context.particle_system.point_cache.external
+               else:
+                       return False
+       
        def draw(self, context):
                layout = self.layout
 
@@ -150,37 +156,60 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
                cache = psys.point_cache
                
                row = layout.row()
-               row.itemR(cache, "name")
+               row.itemL(text="File Name:")
+               row.itemR(cache, "external")
                
-               row = layout.row()
-               
-               if cache.baked == True:
-                       row.itemO("ptcache.free_bake_particle_system", text="Free Bake")
+               if cache.external:
+                       split = layout.split(percentage=0.80)
+                       split.itemR(cache, "name", text="")
+                       split.itemR(cache, "index", text="")
+                       
+                       layout.itemL(text="File Path:")
+                       layout.itemR(cache, "filepath", text="")
+                       
+                       layout.itemL(text=cache.info)
+                       
+                       split = layout.split()
+                       
+                       col = split.column(align=True)
+                       col.itemR(part, "start")
+                       col.itemR(part, "end")
+
+                       col = split.column(align=True)
+                       col.itemR(part, "lifetime")
+                       col.itemR(part, "random_lifetime", slider=True)
                else:
-                       row.item_booleanO("ptcache.cache_particle_system", "bake", True, text="Bake")
-               
-               subrow = row.row()
-               subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
-               subrow.itemO("ptcache.cache_particle_system", text="Calculate to Current Frame")
+                       layout.itemR(cache, "name", text="")
+                       
+                       row = layout.row()
                
-               row = layout.row()
-               row.enabled = particle_panel_enabled(psys)
-               row.itemO("ptcache.bake_from_particles_cache", text="Current Cache to Bake")
-               row.itemR(cache, "step");
-       
-               row = layout.row()
-               row.enabled = particle_panel_enabled(psys)
-               row.itemR(cache, "quick_cache")
-               row.itemR(cache, "disk_cache")
+                       if cache.baked == True:
+                               row.itemO("ptcache.free_bake_particle_system", text="Free Bake")
+                       else:
+                               row.item_booleanO("ptcache.cache_particle_system", "bake", True, text="Bake")
                
-               layout.itemL(text=cache.info)
+                       subrow = row.row()
+                       subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
+                       subrow.itemO("ptcache.cache_particle_system", text="Calculate to Current Frame")
+                       
+                       row = layout.row()
+                       row.enabled = particle_panel_enabled(psys)
+                       row.itemO("ptcache.bake_from_particles_cache", text="Current Cache to Bake")
+                       row.itemR(cache, "step");
                
-               layout.itemS()
+                       row = layout.row()
+                       row.enabled = particle_panel_enabled(psys)
+                       row.itemR(cache, "quick_cache")
+                       row.itemR(cache, "disk_cache")
                
-               row = layout.row()
-               row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
-               row.itemO("ptcache.free_bake_all", text="Free All Bakes")
-               layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame")
+                       layout.itemL(text=cache.info)
+                       
+                       layout.itemS()
+                       
+                       row = layout.row()
+                       row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
+                       row.itemO("ptcache.free_bake_all", text="Free All Bakes")
+                       layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame")
                
                # for particles these are figured out automatically
                #row.itemR(cache, "start_frame")
@@ -193,7 +222,7 @@ class PARTICLE_PT_initial(ParticleButtonsPanel):
        def poll(self, context):
                if particle_panel_poll(context):
                        psys = context.particle_system
-                       return psys.settings.physics_type != 'BOIDS'
+                       return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.external
                else:
                        return False
 
@@ -256,6 +285,12 @@ class PARTICLE_PT_initial(ParticleButtonsPanel):
 class PARTICLE_PT_physics(ParticleButtonsPanel):
        __idname__= "PARTICLE_PT_physics"
        __label__ = "Physics"
+       
+       def poll(self, context):
+               if particle_panel_poll(context):
+                       return not context.particle_system.point_cache.external
+               else:
+                       return False
 
        def draw(self, context):
                layout = self.layout
@@ -399,12 +434,15 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel):
                psys = context.particle_system
                if psys==None:  return False
                if psys.settings==None:  return False
+               if psys.point_cache.external: return False
                return psys.settings.physics_type=='BOIDS'
        
        def draw(self, context):
                boids = context.particle_system.settings.boids
                layout = self.layout
                
+               layout.enabled = particle_panel_enabled(psys)
+               
                # Currently boids can only use the first state so these are commented out for now.
                #row = layout.row()
                #row.template_list(boids, "states", boids, "active_boid_state_index", compact="True")
@@ -764,12 +802,6 @@ class PARTICLE_PT_effectors(ParticleButtonsPanel):
        __label__ = "Effectors"
        __default_closed__ = True
        
-       def poll(self, context):
-               psys = context.particle_system
-               if psys==None: return False
-               if psys.settings==None: return False
-               return True;
-       
        def draw(self, context):
                layout = self.layout
 
index c5d423c13baf1488e5406a566121433ce288d150..8062f807055e0329563a161e3d4cc52ec1748306 100644 (file)
@@ -166,4 +166,6 @@ void BKE_ptcache_quick_cache_all(struct Scene *scene);
 void BKE_ptcache_make_cache(struct PTCacheBaker* baker);
 void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
 
+void BKE_ptcache_load_external(struct PTCacheID *pid);
+
 #endif
index b792564f50cd370f31ff6fffc72a6073e029486d..43174343302fb407fe2bc5c70e0dcce438219940 100644 (file)
@@ -3982,7 +3982,8 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
                /* update alive status and push events */
                if(pa->time >= cfra) {
                        pa->alive = pa->time==cfra ? PARS_ALIVE : PARS_UNBORN;
-                       reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra, NULL, NULL, NULL);
+                       if((psys->pointcache->flag & PTCACHE_EXTERNAL) == 0)
+                               reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra, NULL, NULL, NULL);
                }
                else if(dietime <= cfra){
                        if(dietime > psys->cfra){
@@ -4303,7 +4304,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
        oldtotpart = psys->totpart;
        oldtotchild = psys->totchild;
 
-       if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT)
+       if(psys->pointcache->flag & PTCACHE_EXTERNAL)
+               totpart = pid.cache->totpoint;
+       else if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT)
                totpart = part->grid_res*part->grid_res*part->grid_res;
        else
                totpart = psys->part->totpart;
index cde0587772e5b1ddf62b833f2bae2ac18526af56..4bb571aa8ca49c7ce23985d19483f1980d65330d 100644 (file)
@@ -181,7 +181,11 @@ static int ptcache_path(PTCacheID *pid, char *filename)
 
        lib= (pid)? pid->ob->id.lib: NULL;
 
-       if (G.relbase_valid || lib) {
+       if(pid->cache->flag & PTCACHE_EXTERNAL) {
+               strcpy(filename, pid->cache->path);
+               return BLI_add_slash(filename); /* new strlen() */
+       }
+       else if (G.relbase_valid || lib) {
                char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */
                char *blendfilename;
 
@@ -214,14 +218,14 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho
        filename[0] = '\0';
        newname = filename;
        
-       if (!G.relbase_valid) return 0; /* save blend file before using disk pointcache */
+       if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
        
        /* start with temp dir */
        if (do_path) {
                len = ptcache_path(pid, filename);
                newname += len;
        }
-       if(strcmp(pid->cache->name, "")==0) {
+       if(strcmp(pid->cache->name, "")==0 && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
                idname = (pid->ob->id.name+2);
                /* convert chars to hex so they are always a valid filename */
                while('\0' != *idname) {
@@ -238,7 +242,15 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho
        }
 
        if (do_ext) {
-               snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+               if(pid->cache->flag & PTCACHE_EXTERNAL) {
+                       if(pid->cache->index >= 0)
+                               snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+                       else
+                               snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
+               }
+               else {
+                       snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+               }
                len += 16;
        }
        
@@ -256,7 +268,7 @@ PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra)
        if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
                return NULL;
 
-       if (!G.relbase_valid) return NULL; /* save blend file before using disk pointcache */
+       if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
        
        BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
 
@@ -328,6 +340,21 @@ void BKE_ptcache_update_info(PTCacheID *pid)
        int totframes = 0;
        char mem_info[64];
 
+       if(cache->flag & PTCACHE_EXTERNAL) {
+               int cfra = cache->startframe;
+
+               for(; cfra<=cache->endframe; cfra++) {
+                       if(BKE_ptcache_id_exist(pid, cfra))
+                               totframes++;
+               }
+
+               if(totframes)
+                       sprintf(cache->info, "%i points read for %i frames", cache->totpoint, totframes);
+               else
+                       sprintf(cache->info, "No valid data to read!");
+               return;
+       }
+
        if(cache->flag & PTCACHE_DISK_CACHE) {
                int cfra = cache->startframe;
 
@@ -743,7 +770,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
        char path_full[MAX_PTCACHE_FILE];
        char ext[MAX_PTCACHE_PATH];
 
-       if(!pid->cache)
+       if(!pid->cache || pid->cache->flag & PTCACHE_BAKED)
                return;
 
        /* don't allow clearing for linked objects */
@@ -1408,3 +1435,77 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
 
        BKE_ptcache_update_info(pid);
 }
+
+void BKE_ptcache_load_external(PTCacheID *pid)
+{
+       PointCache *cache = pid->cache;
+       int len; /* store the length of the string */
+
+       /* mode is same as fopen's modes */
+       DIR *dir; 
+       struct dirent *de;
+       char path[MAX_PTCACHE_PATH];
+       char filename[MAX_PTCACHE_FILE];
+       char path_full[MAX_PTCACHE_FILE];
+       char ext[MAX_PTCACHE_PATH];
+
+       if(!cache)
+               return;
+
+       cache->startframe = MAXFRAME;
+       cache->endframe = -1;
+       cache->totpoint = 0;
+
+       ptcache_path(pid, path);
+       
+       len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */
+       
+       dir = opendir(path);
+       if (dir==NULL)
+               return;
+
+       if(cache->index >= 0)
+               snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index);
+       else
+               strcpy(ext, PTCACHE_EXT);
+       
+       while ((de = readdir(dir)) != NULL) {
+               if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
+                       if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+                               /* read the number of the file */
+                               int frame, len2 = strlen(de->d_name);
+                               char num[7];
+
+                               if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
+                                       BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
+                                       frame = atoi(num);
+
+                                       cache->startframe = MIN2(cache->startframe, frame);
+                                       cache->endframe = MAX2(cache->endframe, frame);
+                               }
+                       }
+               }
+       }
+       closedir(dir);
+
+       if(cache->startframe != MAXFRAME) {
+               PTCacheFile *pf;
+               int elemsize = ptcache_pid_elemsize(pid);
+               int     incr = elemsize / sizeof(float);
+               float *data = NULL;
+               pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
+
+               if(pf) {
+                       data = MEM_callocN(elemsize, "pointcache read data");
+                       while(BKE_ptcache_file_read_floats(pf, data, incr))
+                               cache->totpoint++;
+                       
+                       BKE_ptcache_file_close(pf);
+                       MEM_freeN(data);
+               }
+       }
+
+       cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
+
+       BKE_ptcache_update_info(pid);
+}
index 6cf20cc25a2c22f3d5e4b3b1392cb15b8b778df3..d640e37f48d4061177a1a3d007824fecb28e87b9 100644 (file)
@@ -89,10 +89,15 @@ typedef struct PointCache {
        int endframe;   /* simulation end frame */
        int editframe;  /* frame being edited (runtime only) */
        int last_exact; /* last exact frame that's cached */
-       int xdata_type; /* type of extra data */
+
+       /* for external cache files */
+       int totpoint;   /* number of cached points */
+       int index, rt;  /* modifier stack index */
+       
        char name[64];
        char prev_name[64];
        char info[64];
+       char path[240]; /* file path */
        struct ListBase mem_cache;
 } PointCache;
 
@@ -267,6 +272,7 @@ typedef struct SoftBody {
 #define PTCACHE_DISK_CACHE                     64
 #define PTCACHE_QUICK_CACHE                    128
 #define PTCACHE_FRAMES_SKIPPED         256
+#define PTCACHE_EXTERNAL                       512
 
 /* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
 #define PTCACHE_REDO_NEEDED                    258
index 2d8a186d3f4de4264725dc852adc3bfd6e6c8441..3d1dfff61cdb79243e26eba85f1c16ef0e0ad27a 100644 (file)
@@ -233,13 +233,6 @@ typedef struct ParticleSystem{                             /* note, make sure all (runtime) are NULL's in
        struct KDTree *tree;                                    /* used for interactions with self and other systems */
 }ParticleSystem;
 
-/* general particle maximums */
-/* no special why's, just seem reasonable */
-/* changing these (atleast upwards) should not cause any major problems */
-#define MAX_PARTS                      100000  /* real particles/system */
-#define MAX_PART_CHILDREN      10000   /* child particles/real particles */
-#define MAX_BOIDNEIGHBOURS     10              /* neigbours considered/boid */
-
 /* part->type */
 /* hair is allways baked static in object/geometry space */
 /* other types (normal particles) are in global space and not static baked */
index 2ec8d9ea41e53c0f93ede8e87165b669d433f694..965b70714dcb9bd4e8e0f64627f90e8f13c82f10 100644 (file)
@@ -105,6 +105,7 @@ static void rna_Cache_toggle_disk_cache(bContext *C, PointerRNA *ptr)
 
 static void rna_Cache_idname_change(bContext *C, PointerRNA *ptr)
 {
+       Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
        PointCache *cache = (PointCache*)ptr->data;
        PTCacheID *pid = NULL, *pid2= NULL;
@@ -119,33 +120,50 @@ static void rna_Cache_idname_change(bContext *C, PointerRNA *ptr)
 
        BKE_ptcache_ids_from_object(&pidlist, ob);
 
-       for(pid=pidlist.first; pid; pid=pid->next) {
-               if(pid->cache==cache)
-                       pid2 = pid;
-               else if(strcmp(cache->name, "") && strcmp(cache->name,pid->cache->name)==0) {
-                       /*TODO: report "name exists" to user */
-                       strcpy(cache->name, cache->prev_name);
-                       new_name = 0;
+       if(cache->flag & PTCACHE_EXTERNAL) {
+               for(pid=pidlist.first; pid; pid=pid->next) {
+                       if(pid->cache==cache)
+                               break;
                }
+
+               if(!pid)
+                       return;
+
+               cache->flag |= (PTCACHE_BAKED|PTCACHE_DISK_CACHE|PTCACHE_SIMULATION_VALID);
+               cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
+
+               BKE_ptcache_load_external(pid);
+               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
        }
+       else {
+               for(pid=pidlist.first; pid; pid=pid->next) {
+                       if(pid->cache==cache)
+                               pid2 = pid;
+                       else if(strcmp(cache->name, "") && strcmp(cache->name,pid->cache->name)==0) {
+                               /*TODO: report "name exists" to user */
+                               strcpy(cache->name, cache->prev_name);
+                               new_name = 0;
+                       }
+               }
 
-       if(new_name) {
-               if(pid2 && cache->flag & PTCACHE_DISK_CACHE) {
-                       strcpy(name, cache->name);
-                       strcpy(cache->name, cache->prev_name);
+               if(new_name) {
+                       if(pid2 && cache->flag & PTCACHE_DISK_CACHE) {
+                               strcpy(name, cache->name);
+                               strcpy(cache->name, cache->prev_name);
 
-                       cache->flag &= ~PTCACHE_DISK_CACHE;
+                               cache->flag &= ~PTCACHE_DISK_CACHE;
 
-                       BKE_ptcache_toggle_disk_cache(pid2);
+                               BKE_ptcache_toggle_disk_cache(pid2);
 
-                       strcpy(cache->name, name);
+                               strcpy(cache->name, name);
 
-                       cache->flag |= PTCACHE_DISK_CACHE;
+                               cache->flag |= PTCACHE_DISK_CACHE;
 
-                       BKE_ptcache_toggle_disk_cache(pid2);
-               }
+                               BKE_ptcache_toggle_disk_cache(pid2);
+                       }
 
-               strcpy(cache->prev_name, cache->name);
+                       strcpy(cache->prev_name, cache->name);
+               }
        }
 
        BLI_freelistN(&pidlist);
@@ -365,11 +383,16 @@ static void rna_def_pointcache(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops.");
 
        prop= RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
-       RNA_def_property_int_sdna(prop, NULL, "step");
        RNA_def_property_range(prop, 1, 20);
        RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames.");
        RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
 
+       prop= RNA_def_property(srna, "index", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "index");
+       RNA_def_property_range(prop, -1, 100);
+       RNA_def_property_ui_text(prop, "Cache Index", "Index number of cache files.");
+       RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
+
        /* flags */
        prop= RNA_def_property(srna, "baked", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKED);
@@ -398,6 +421,11 @@ static void rna_def_pointcache(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Name", "Cache name");
        RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
 
+       prop= RNA_def_property(srna, "filepath", PROP_STRING, PROP_DIRPATH);
+       RNA_def_property_string_sdna(prop, NULL, "path");
+       RNA_def_property_ui_text(prop, "File Path", "Cache file path.");
+       RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
+
        prop= RNA_def_property(srna, "quick_cache", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE);
        RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps");
@@ -407,6 +435,11 @@ static void rna_def_pointcache(BlenderRNA *brna)
        RNA_def_property_string_sdna(prop, NULL, "info");
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status.");
+
+       prop= RNA_def_property(srna, "external", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_EXTERNAL);
+       RNA_def_property_ui_text(prop, "External", "Read cache from an external location");
+       RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
 }
 
 static void rna_def_collision(BlenderRNA *brna)
index f07351f0a3080e66be8e33f71b2b3618a20f1a8d..4caf915e7ea9bf9aea527ae71b57389cd037335c 100644 (file)
@@ -616,33 +616,65 @@ static void rna_def_particle(BlenderRNA *brna)
        RNA_def_property_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Stick Object", "Object that particle sticks to when dead");
 
-//     ParticleKey state;              /* normally current global coordinates or       */
-//                                                     /* in sticky object space if dead & sticky      */
-//
-//     ParticleKey prev_state; /* previous state */
+       /* Particle State & Previous State */
+       prop= RNA_def_property(srna, "location", PROP_FLOAT, PROP_VECTOR);
+       RNA_def_property_float_sdna(prop, NULL, "state.co");
+       RNA_def_property_ui_text(prop, "Particle Location", "");
+
+       prop= RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VECTOR);
+       RNA_def_property_float_sdna(prop, NULL, "state.vel");
+       RNA_def_property_ui_text(prop, "Particle Velocity", "");
+
+       prop= RNA_def_property(srna, "angular_velocity", PROP_FLOAT, PROP_VECTOR);
+       RNA_def_property_float_sdna(prop, NULL, "state.ave");
+       RNA_def_property_ui_text(prop, "Angular Velocity", "");
+
+       prop= RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ROTATION);
+       RNA_def_property_float_sdna(prop, NULL, "state.rot");
+       RNA_def_property_ui_text(prop, "Rotation", "");
 
-//     prop= RNA_def_property(srna, "hair", PROP_COLLECTION, PROP_NONE);
-//     RNA_def_property_collection_sdna(prop, NULL, "hair", "???totalHair???"); //don't know what the hair array size is
-//     RNA_def_property_struct_type(prop, "HairKey");
-//     RNA_def_property_ui_text(prop, "Hair", "");
+       prop= RNA_def_property(srna, "prev_location", PROP_FLOAT, PROP_VECTOR);
+       RNA_def_property_float_sdna(prop, NULL, "prev_state.co");
+       RNA_def_property_ui_text(prop, "Previous Particle Location", "");
+
+       prop= RNA_def_property(srna, "prev_velocity", PROP_FLOAT, PROP_VECTOR);
+       RNA_def_property_float_sdna(prop, NULL, "prev_state.vel");
+       RNA_def_property_ui_text(prop, "Previous Particle Velocity", "");
+
+       prop= RNA_def_property(srna, "prev_angular_velocity", PROP_FLOAT, PROP_VECTOR);
+       RNA_def_property_float_sdna(prop, NULL, "prev_state.ave");
+       RNA_def_property_ui_text(prop, "Previous Angular Velocity", "");
+
+       prop= RNA_def_property(srna, "prev_rotation", PROP_FLOAT, PROP_ROTATION);
+       RNA_def_property_float_sdna(prop, NULL, "prev_state.rot");
+       RNA_def_property_ui_text(prop, "Previous Rotation", "");
+
+       /* Hair & Keyed Keys */
+
+       prop= RNA_def_property(srna, "hair", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_sdna(prop, NULL, "hair", "totkey");
+       RNA_def_property_struct_type(prop, "ParticleHairKey");
+       RNA_def_property_ui_text(prop, "Hair", "");
 
        prop= RNA_def_property(srna, "keys", PROP_COLLECTION, PROP_NONE);
        RNA_def_property_collection_sdna(prop, NULL, "keys", "totkey");
        RNA_def_property_struct_type(prop, "ParticleKey");
        RNA_def_property_ui_text(prop, "Keyed States", "");
 
-       prop= RNA_def_property(srna, "random_rotation", PROP_FLOAT, PROP_NONE);
+       /* Random variables */
+
+       prop= RNA_def_property(srna, "random_rotation", PROP_FLOAT, PROP_ROTATION);
        RNA_def_property_float_sdna(prop, NULL, "r_rot");
 //     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
        RNA_def_property_ui_text(prop, "Random Rotation", "");
 
-       prop= RNA_def_property(srna, "random_a_velocity", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "random_a_velocity", PROP_FLOAT, PROP_VECTOR);
        RNA_def_property_float_sdna(prop, NULL, "r_ave");
 //     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
-       RNA_def_property_ui_text(prop, "Random erm.. Velocity", "");//TODO: fix name
+       RNA_def_property_ui_text(prop, "Random Angular Velocity", "");
 
-       prop= RNA_def_property(srna, "random_velocity", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_sdna(prop, NULL, "r_ve");//optional if prop names are the same
+       prop= RNA_def_property(srna, "random_velocity", PROP_FLOAT, PROP_VECTOR);
+       RNA_def_property_float_sdna(prop, NULL, "r_ve");
 //     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
        RNA_def_property_ui_text(prop, "Random Velocity", "");
 
@@ -650,9 +682,10 @@ static void rna_def_particle(BlenderRNA *brna)
 //     float fuv[4], foffset;  /* coordinates on face/edge number "num" and depth along*/
 //                                                     /* face normal for volume emission                                              */
 
-       prop= RNA_def_property(srna, "time", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "birthtime", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "time");
 //     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
-       RNA_def_property_ui_text(prop, "Time", "");
+       RNA_def_property_ui_text(prop, "Birth Time", "");
 
        prop= RNA_def_property(srna, "lifetime", PROP_FLOAT, PROP_NONE);
 //     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
@@ -663,11 +696,6 @@ static void rna_def_particle(BlenderRNA *brna)
 //     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
        RNA_def_property_ui_text(prop, "Die Time", "");
 
-//     prop= RNA_def_property(srna, "banking_angle", PROP_FLOAT, PROP_NONE);
-//     RNA_def_property_float_sdna(prop, NULL, "bank");
-////   RNA_def_property_range(prop, lowerLimitf, upperLimitf);
-//     RNA_def_property_ui_text(prop, "Banking Angle", "");
-
        prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
 //     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
        RNA_def_property_ui_text(prop, "Size", "");
@@ -1133,12 +1161,14 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "draw_step", PROP_INT, PROP_NONE);
        RNA_def_property_range(prop, 0, 7);
+       RNA_def_property_ui_range(prop, 0, 10, 1, 0);
        RNA_def_property_ui_text(prop, "Steps", "How many steps paths are drawn with (power of 2)");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
 
        prop= RNA_def_property(srna, "render_step", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "ren_step");
        RNA_def_property_range(prop, 0, 9);
+       RNA_def_property_ui_range(prop, 0, 20, 1, 0);
        RNA_def_property_ui_text(prop, "Render", "How many steps paths are rendered with (power of 2)");
 
        prop= RNA_def_property(srna, "hair_step", PROP_INT, PROP_NONE);
@@ -1206,7 +1236,8 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "billboard_uv_split", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "bb_uv_split");
-       RNA_def_property_range(prop, 1, 10);
+       RNA_def_property_range(prop, 1, 100);
+       RNA_def_property_ui_range(prop, 1, 10, 1, 0);
        RNA_def_property_ui_text(prop, "UV Split", "Amount of rows/columns to split uv coordinates for billboards");
 
        prop= RNA_def_property(srna, "billboard_animation", PROP_ENUM, PROP_NONE);
@@ -1234,7 +1265,8 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        prop= RNA_def_property(srna, "billboard_offset", PROP_FLOAT, PROP_VECTOR);
        RNA_def_property_float_sdna(prop, NULL, "bb_offset");
        RNA_def_property_array(prop, 2);
-       RNA_def_property_range(prop, -1.0f, 1.0f);
+       RNA_def_property_range(prop, -100.0f, 100.0f);
+       RNA_def_property_ui_range(prop, -1.0, 1.0, 0.1, 3);
        RNA_def_property_ui_text(prop, "Billboard Offset", "");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
 
@@ -1314,7 +1346,11 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        prop= RNA_def_property(srna, "amount", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_int_sdna(prop, NULL, "totpart");
        RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
-       RNA_def_property_range(prop, 0, 100000);
+       /* This limit is for those freaks who have the machine power to handle it. */
+       /* 10M particles take around 2.2 Gb of memory / disk space in saved file and */
+       /* each cached frame takes around 0.5 Gb of memory / disk space depending on cache mode. */
+       RNA_def_property_range(prop, 0, 10000000);
+       RNA_def_property_ui_range(prop, 0, 100000, 1, 0);
        RNA_def_property_ui_text(prop, "Amount", "Total number of particles.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
@@ -1328,7 +1364,8 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        prop= RNA_def_property(srna, "grid_resolution", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_int_sdna(prop, NULL, "grid_res");
        RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
-       RNA_def_property_range(prop, 1, 100);
+       RNA_def_property_range(prop, 1, 46); /* ~100k particles in a cube */
+       RNA_def_property_ui_range(prop, 1, 215, 1, 0); /* ~10M particles in a cube */
        RNA_def_property_ui_text(prop, "Resolution", "The resolution of the particle grid.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
@@ -1341,7 +1378,8 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "object_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "obfac");
-       RNA_def_property_range(prop, -1.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Object", "Let the object give the particle a starting speed");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
@@ -1353,7 +1391,8 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "particle_factor", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "partfac");
-       RNA_def_property_range(prop, -10.0f, 10.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Particle", "Let the target particle give the particle a starting speed.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
@@ -1401,13 +1440,15 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        /* physical properties */
        prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_range(prop, 0.01f, 100.0f);
+       RNA_def_property_range(prop, 0.001f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.01f, 100.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Mass", "Specify the mass of the particles");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "particle_size", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "size");
-       RNA_def_property_range(prop, 0.01f, 100.0f);
+       RNA_def_property_range(prop, 0.001f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.01f, 100.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Size", "The size of the particles");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
@@ -1466,13 +1507,15 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        /* children */
        prop= RNA_def_property(srna, "child_nbr", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "child_nbr");//optional if prop names are the same
-       RNA_def_property_range(prop, 0, MAX_PART_CHILDREN);
+       RNA_def_property_range(prop, 0, 100000);
+       RNA_def_property_ui_range(prop, 0, 1000, 1, 0);
        RNA_def_property_ui_text(prop, "Children Per Parent", "Amount of children/parent");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
        prop= RNA_def_property(srna, "rendered_child_nbr", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "ren_child_nbr");
-       RNA_def_property_range(prop, 0, MAX_PART_CHILDREN);
+       RNA_def_property_range(prop, 0, 100000);
+       RNA_def_property_ui_range(prop, 0, 10000, 1, 0);
        RNA_def_property_ui_text(prop, "Rendered Children", "Amount of children/parent for rendering.");
 
        prop= RNA_def_property(srna, "virtual_parents", PROP_FLOAT, PROP_NONE);
@@ -1483,7 +1526,8 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "child_size", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "childsize");
-       RNA_def_property_range(prop, 0.01f, 100.0f);
+       RNA_def_property_range(prop, 0.001f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.01f, 100.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Child Size", "A multiplier for the child particle size.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
@@ -1522,13 +1566,15 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        /* kink */
        prop= RNA_def_property(srna, "kink_amplitude", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "kink_amp");
-       RNA_def_property_range(prop, 0.0f, 10.0f);
+       RNA_def_property_range(prop, -100000.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Amplitude", "The amplitude of the offset.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
        prop= RNA_def_property(srna, "kink_frequency", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "kink_freq");
-       RNA_def_property_range(prop, 0.0f, 10.0f);
+       RNA_def_property_range(prop, -100000.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Frequency", "The frequency of the offset (1/total length)");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
@@ -1540,24 +1586,28 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        /* rough */
        prop= RNA_def_property(srna, "rough1", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_range(prop, 0.0f, 10.0f);
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Rough1", "Amount of location dependent rough.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
        prop= RNA_def_property(srna, "rough1_size", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_range(prop, 0.01f, 10.0f);
+       RNA_def_property_range(prop, 0.01f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Size1", "Size of location dependent rough.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
        prop= RNA_def_property(srna, "rough2", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "rough2");
-       RNA_def_property_range(prop, 0.0f, 10.0f);
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Rough2", "Amount of random rough.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
        prop= RNA_def_property(srna, "rough2_size", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "rough2_size");
-       RNA_def_property_range(prop, 0.01f, 10.0f);
+       RNA_def_property_range(prop, 0.01f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Size2", "Size of random rough.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
@@ -1569,7 +1619,8 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "rough_endpoint", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "rough_end");
-       RNA_def_property_range(prop, 0.0f, 10.0f);
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Rough Endpoint", "Amount of end point rough.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
 
@@ -1600,13 +1651,15 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        /* drawing stuff */
        prop= RNA_def_property(srna, "line_length_tail", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_funcs(prop, "rna_PartSetting_linelentail_get", "rna_PartSetting_linelentail_set", NULL);
-       RNA_def_property_range(prop, 0.0f, 10.0f);
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Back", "Length of the line's tail");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
 
        prop= RNA_def_property(srna, "line_length_head", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_funcs(prop, "rna_PartSetting_linelenhead_get", "rna_PartSetting_linelenhead_set", NULL);
-       RNA_def_property_range(prop, 0.0f, 10.0f);
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Head", "Length of the line's head");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
 
@@ -1624,14 +1677,16 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "trail_count", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "trail_count");
-       RNA_def_property_range(prop, 1.0f, 100.0f);
+       RNA_def_property_range(prop, 1, 100000);
+       RNA_def_property_ui_range(prop, 1, 100, 1, 0);
        RNA_def_property_ui_text(prop, "Trail Count", "Number of trail particles.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
 
        /* keyed particles */
        prop= RNA_def_property(srna, "keyed_loops", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "keyed_loops");
-       RNA_def_property_range(prop, 1.0f, 100.0f);
+       RNA_def_property_range(prop, 1.0f, 10000.0f);
+       RNA_def_property_ui_range(prop, 1.0f, 100.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Loop count", "Number of times the keys are looped.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
 
@@ -1674,61 +1729,71 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 
        prop= RNA_def_property(srna, "eweight_all", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[0]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "All", "All effector's weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_spherical", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[1]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Spherical", "Spherical effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_vortex", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[2]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Vortex", "Vortex effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_magnetic", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[3]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Magnetic", "Magnetic effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_wind", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[4]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Wind", "Wind effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_curveguide", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[5]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Curve Guide", "Curve guide effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_texture", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[6]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Magnetic", "Texture effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_harmonic", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[7]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Harmonic", "Harmonic effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_charge", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[8]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Charge", "Charge effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
        prop= RNA_def_property(srna, "eweight_lennardjones", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "effector_weight[9]");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_ui_text(prop, "Lennard-Jones", "Lennard-Jones effector weight.");
        RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");