diff options
author | Andre Susano Pinto <andresusanopinto@gmail.com> | 2009-08-17 21:43:49 +0400 |
---|---|---|
committer | Andre Susano Pinto <andresusanopinto@gmail.com> | 2009-08-17 21:43:49 +0400 |
commit | 950b770c1ea0c05a907abc93ad7174a02432843f (patch) | |
tree | 12936d6440bc7a0710a2fc776d1e122e000ea71e /source/blender/blenkernel | |
parent | 0e3acbaa386384f1b1d27a2b4e0f0dcd07c0e0e2 (diff) | |
parent | 931ffbedaa3e76a6ebec3df2af22176e504158db (diff) |
svn merge -r 22371:22571 https://svn.blender.org/svnroot/bf-blender/branches/blender2.5/blender
Diffstat (limited to 'source/blender/blenkernel')
38 files changed, 2687 insertions, 896 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 2447d1823af..cabbaa7aa0f 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -66,6 +66,9 @@ void BKE_keyingset_add_destination(struct KeyingSet *ks, struct ID *id, const ch struct KS_Path *BKE_keyingset_find_destination(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode); +/* Copy all KeyingSets in the given list */ +void BKE_keyingsets_copy(struct ListBase *newlist, struct ListBase *list); + /* Free data for KeyingSet but not set itself */ void BKE_keyingset_free(struct KeyingSet *ks); diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 19b9c315939..4fe1eec55c0 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ struct bContext; struct ReportList; #define BLENDER_VERSION 250 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 9eb0b15aed4..6ec988e111e 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -38,16 +38,15 @@ struct Scene; struct wmOperator; /* datablock functions */ -struct Brush *add_brush(char *name); +struct Brush *add_brush(const char *name); struct Brush *copy_brush(struct Brush *brush); void make_local_brush(struct Brush *brush); void free_brush(struct Brush *brush); /* brush library operations used by different paint panels */ -struct Brush **current_brush_source(struct Scene *sce); -int brush_set_nr(struct Brush **current_brush, int nr); +int brush_set_nr(struct Brush **current_brush, int nr, const char *name); int brush_delete(struct Brush **current_brush); -void brush_check_exists(struct Brush **brush); +void brush_check_exists(struct Brush **brush, const char *name); void brush_toggled_fake_user(struct Brush *brush); int brush_texture_set_nr(struct Brush *brush, int nr); int brush_texture_delete(struct Brush *brush); diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index f3165c959bf..bc4585106e6 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -244,10 +244,6 @@ void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int tot void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving ); void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving ); -// needed for editmesh.c -void cloth_write_cache( Object *ob, ClothModifierData *clmd, int framenr ); -int cloth_read_cache( Scene *scene, Object *ob, ClothModifierData *clmd, float framenr, int *old_framenr ); - // needed for button_object.c void cloth_clear_cache ( Object *ob, ClothModifierData *clmd, float framenr ); diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index e47ad969b91..035b7e2e5b9 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -86,6 +86,25 @@ typedef struct bContextStore { int used; } bContextStore; +/* for the conrtext's rna mode enum + * keep aligned with data_mode_strings in context.c */ +enum { + CTX_MODE_EDIT_MESH = 0, + CTX_MODE_EDIT_CURVE, + CTX_MODE_EDIT_SURFACE, + CTX_MODE_EDIT_TEXT, + CTX_MODE_EDIT_ARMATURE, + CTX_MODE_EDIT_METABALL, + CTX_MODE_EDIT_LATTICE, + CTX_MODE_POSE, + CTX_MODE_SCULPT, + CTX_MODE_PAINT_WEIGHT, + CTX_MODE_PAINT_VERTEX, + CTX_MODE_PAINT_TEXTURE, + CTX_MODE_PARTICLE, + CTX_MODE_OBJECT +}; + /* Context */ bContext *CTX_create(void); @@ -191,6 +210,9 @@ struct Main *CTX_data_main(const bContext *C); struct Scene *CTX_data_scene(const bContext *C); struct ToolSettings *CTX_data_tool_settings(const bContext *C); +char *CTX_data_mode_string(const bContext *C); +int CTX_data_mode_enum(const bContext *C); + void CTX_data_main_set(bContext *C, struct Main *bmain); void CTX_data_scene_set(bContext *C, struct Scene *bmain); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 315fe2a39cb..7ce616c37c9 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -112,27 +112,15 @@ typedef struct Global { #define G_FACESELECT (1 << 8) -#define G_VERTEXPAINT (1 << 10) - #define G_DEBUG (1 << 12) #define G_DOSCRIPTLINKS (1 << 13) -#define G_WEIGHTPAINT (1 << 15) -#define G_TEXTUREPAINT (1 << 16) /* #define G_NOFROZEN (1 << 17) also removed */ #define G_GREASEPENCIL (1 << 17) -#define G_SCULPTMODE (1 << 29) -#define G_PARTICLEEDIT (1 << 30) - /* #define G_AUTOMATKEYS (1 << 30) also removed */ #define G_HIDDENHANDLES (1 << 31) /* used for curves only */ -/* macro for testing face select mode - * Texture paint could be removed since selected faces are not used - * however hiding faces is useful */ -#define FACESEL_PAINT_TEST ((G.f&G_FACESELECT) && (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT))) - /* G.fileflags */ #define G_AUTOPACK (1 << 0) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 87ee8f9cab3..183cdaff0e6 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -47,6 +47,7 @@ struct rctf; struct ListBase; struct RenderData; struct Scene; +struct Main; struct Tex; struct GPUMaterial; struct GPUNode; @@ -432,4 +433,8 @@ char* ntreeTexOutputMenu(struct bNodeTree *ntree); void init_nodesystem(void); void free_nodesystem(void); +/**/ + +void clear_scene_in_nodes(struct Main *bmain, struct Scene *sce); + #endif diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h new file mode 100644 index 00000000000..67b260b2348 --- /dev/null +++ b/source/blender/blenkernel/BKE_paint.h @@ -0,0 +1,51 @@ +/* + * ***** 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) 2009 by Nicholas Bishop + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BKE_PAINT_H +#define BKE_PAINT_H + +struct Brush; +struct Object; +struct Paint; +struct Scene; + +void paint_init(struct Paint *p, const char *brush_name); +void free_paint(struct Paint *p); +void copy_paint(struct Paint *orig, struct Paint *new); + +struct Paint *paint_get_active(struct Scene *sce); +struct Brush *paint_brush(struct Paint *paint); +void paint_brush_set(struct Paint *paint, struct Brush *br); +void paint_brush_slot_add(struct Paint *p); +void paint_brush_slot_remove(struct Paint *p); + +/* testing face select mode + * Texture paint could be removed since selected faces are not used + * however hiding faces is useful */ +int paint_facesel_test(struct Object *ob); + +#endif diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 8062f807055..5d9dddfe30d 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -30,6 +30,8 @@ #define BKE_POINTCACHE_H #include "DNA_ID.h" +#include "DNA_object_force.h" +#include "DNA_boid_types.h" #include "MEM_guardedalloc.h" @@ -55,9 +57,11 @@ #define PTCACHE_FILE_WRITE 1 /* PTCacheID types */ -#define PTCACHE_TYPE_SOFTBODY 0 -#define PTCACHE_TYPE_PARTICLES 1 -#define PTCACHE_TYPE_CLOTH 2 +#define PTCACHE_TYPE_SOFTBODY 0 +#define PTCACHE_TYPE_PARTICLES 1 +#define PTCACHE_TYPE_CLOTH 2 +#define PTCACHE_TYPE_SMOKE_DOMAIN_LOW 3 +#define PTCACHE_TYPE_SMOKE_DOMAIN_HIGH 4 /* PTCache read return code */ #define PTCACHE_READ_EXACT 1 @@ -69,46 +73,70 @@ struct Object; struct Scene; struct SoftBody; struct ParticleSystem; +struct ParticleKey; struct ClothModifierData; +struct SmokeModifierData; struct PointCache; struct ListBase; +/* temp structure for read/write */ +typedef struct PTCacheData { + int index; + float loc[3]; + float vel[3]; + float rot[4]; + float ave[3]; + float size; + float times[3]; + struct BoidData boids; +} PTCacheData; + typedef struct PTCacheFile { FILE *fp; + + int totpoint, type; + unsigned int data_types; + + struct PTCacheData data; + void *cur[BPHYS_TOT_DATA]; } PTCacheFile; typedef struct PTCacheID { struct PTCacheID *next, *prev; + struct Scene *scene; struct Object *ob; - void *data; + void *calldata; int type; int stack_index; - struct PointCache *cache; -} PTCacheID; - -typedef struct PTCacheWriter { - struct PTCacheID *pid; - int cfra; - int totelem; + /* flags defined in DNA_object_force.h */ + unsigned int data_types, info_types; - void (*set_elem)(int index, void *calldata, float *data); - void *calldata; -} PTCacheWriter; + /* copies point data to cache data */ + int (*write_elem)(int index, void *calldata, void **data); + /* copies point data to cache data */ + int (*write_stream)(PTCacheFile *pf, void *calldata); + /* copies cache cata to point data */ + void (*read_elem)(int index, void *calldata, void **data, float frs_sec, float cfra, float *old_data); + /* copies cache cata to point data */ + void (*read_stream)(PTCacheFile *pf, void *calldata); + /* interpolated between previously read point data and cache data */ + void (*interpolate_elem)(int index, void *calldata, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data); -typedef struct PTCacheReader { - struct Scene *scene; - struct PTCacheID *pid; - float cfra; - int totelem; + /* total number of simulated points */ + int (*totpoint)(void *calldata); + /* number of points written for current cache frame (currently not used) */ + int (*totwrite)(void *calldata); - void (*set_elem)(int elem_index, void *calldata, float *data); - void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2); - void *calldata; + int (*write_header)(PTCacheFile *pf); + int (*read_header)(PTCacheFile *pf); - int *old_frame; -} PTCacheReader; + struct PointCache *cache; + /* used for setting the current cache from ptcaches list */ + struct PointCache **cache_ptr; + struct ListBase *ptcaches; +} PTCacheID; typedef struct PTCacheBaker { struct Scene *scene; @@ -123,49 +151,75 @@ typedef struct PTCacheBaker { void *progresscontext; } PTCacheBaker; -/* Creating ID's */ +/* Particle functions */ +void BKE_ptcache_make_particle_key(struct ParticleKey *key, int index, void **data, float time); + +/**************** Creating ID's ****************************/ void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb); void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys); void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd); +void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd, int num); void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob); -/* Global funcs */ +/***************** Global funcs ****************************/ void BKE_ptcache_remove(void); -/* ID specific functions */ +/************ ID specific functions ************************/ void BKE_ptcache_id_clear(PTCacheID *id, int mode, int cfra); int BKE_ptcache_id_exist(PTCacheID *id, int cfra); int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode); void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale); int BKE_ptcache_object_reset(struct Scene *scene, struct Object *ob, int mode); -/* File reading/writing */ -PTCacheFile *BKE_ptcache_file_open(PTCacheID *id, int mode, int cfra); -void BKE_ptcache_file_close(PTCacheFile *pf); -int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot); -int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot); - void BKE_ptcache_update_info(PTCacheID *pid); -/* General cache reading/writing */ -int BKE_ptcache_read_cache(PTCacheReader *reader); -int BKE_ptcache_write_cache(PTCacheWriter *writer); +/*********** General cache reading/writing ******************/ + +/* Size of cache data type. */ +int BKE_ptcache_data_size(int data_type); + +/* Copy a specific data type from cache data to point data. */ +void BKE_ptcache_data_get(void **data, int type, int index, void *to); + +/* Copy a specific data type from point data to cache data. */ +void BKE_ptcache_data_set(void **data, int type, void *from); + +/* Main cache reading call. */ +int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec); -/* Continue physics */ +/* Main cache writing call. */ +int BKE_ptcache_write_cache(PTCacheID *pid, int cfra); + +/****************** Continue physics ***************/ void BKE_ptcache_set_continue_physics(struct Scene *scene, int enable); int BKE_ptcache_get_continue_physics(void); -/* Point Cache */ -struct PointCache *BKE_ptcache_add(void); +/******************* Allocate & free ***************/ +struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches); +void BKE_ptache_free_mem(struct PointCache *cache); void BKE_ptcache_free(struct PointCache *cache); -struct PointCache *BKE_ptcache_copy(struct PointCache *cache); +void BKE_ptcache_free_list(struct ListBase *ptcaches); +struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, struct ListBase *ptcaches_old); + +/********************** Baking *********************/ -/* Baking */ +/* Bakes cache with cache_step sized jumps in time, not accurate but very fast. */ void BKE_ptcache_quick_cache_all(struct Scene *scene); + +/* Bake cache or simulate to current frame with settings defined in the baker. */ void BKE_ptcache_make_cache(struct PTCacheBaker* baker); + +/* Convert disk cache to memory cache. */ +void BKE_ptcache_disk_to_mem(struct PTCacheID *pid); + +/* Convert memory cache to disk cache. */ +void BKE_ptcache_mem_to_disk(struct PTCacheID *pid); + +/* Convert disk cache to memory cache and vice versa. Clears the cache that was converted. */ void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid); +/* Loads simulation from external (disk) cache files. */ void BKE_ptcache_load_external(struct PTCacheID *pid); #endif diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 9bb246f88cc..12a13a2b50c 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -40,6 +40,12 @@ struct AviCodecData; struct QuicktimeCodecData; struct RenderData; struct Text; +struct Main; + +#define SCE_COPY_EMPTY 0 +#define SCE_COPY_LINK_OB 1 +#define SCE_COPY_LINK_DATA 2 +#define SCE_COPY_FULL 3 /* note; doesn't work when scene is empty */ #define SETLOOPER(s, b) sce= s, b= (Base*)sce->base.first; b; b= (Base*)(b->next?b->next:sce->set?(sce=sce->set)->base.first:NULL) @@ -48,13 +54,16 @@ struct Text; void free_avicodecdata(struct AviCodecData *acd); void free_qtcodecdata(struct QuicktimeCodecData *acd); -void free_scene(struct Scene *me); +void free_scene(struct Scene *sce); struct Scene *add_scene(char *name); struct Base *object_in_scene(struct Object *ob, struct Scene *sce); void set_scene_bg(struct Scene *sce); void set_scene_name(char *name); +struct Scene *copy_scene(struct Main *bmain, struct Scene *sce, int type); +void unlink_scene(struct Main *bmain, struct Scene *sce, struct Scene *newsce); + int next_object(struct Scene *scene, int val, struct Base **base, struct Object **ob); struct Object *scene_find_camera(struct Scene *sc); diff --git a/source/blender/blenkernel/BKE_sculpt.h b/source/blender/blenkernel/BKE_sculpt.h index 54cafc984a6..9e5647a8775 100644 --- a/source/blender/blenkernel/BKE_sculpt.h +++ b/source/blender/blenkernel/BKE_sculpt.h @@ -33,7 +33,7 @@ struct MFace; struct MultireModifierData; struct MVert; -struct Sculpt; +struct Object; struct StrokeCache; typedef struct SculptSession { @@ -63,13 +63,10 @@ typedef struct SculptSession { float (*mesh_co_orig)[3]; /* Copy of the mesh vertices' locations */ float *layer_disps; /* Displacements for each vertex */ - void *cursor; /* wm handle */ - struct SculptStroke *stroke; - struct StrokeCache *cache; } SculptSession; -void sculptsession_free(struct Sculpt *sculpt); +void free_sculptsession(SculptSession **); #endif diff --git a/source/blender/blenkernel/BKE_sequence.h b/source/blender/blenkernel/BKE_sequence.h index 35cff5c9422..f72617c8312 100644 --- a/source/blender/blenkernel/BKE_sequence.h +++ b/source/blender/blenkernel/BKE_sequence.h @@ -184,3 +184,7 @@ int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test); void free_imbuf_seq(struct ListBase * seqbasep, int check_mem_usage); void seq_update_sound(struct Sequence *seq); + +void clear_scene_in_allseqs(struct Scene *sce); + + diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index 0d9682cf842..d8053281ceb 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -68,8 +68,5 @@ extern void sbObjectToSoftbody(struct Object *ob); /* pass NULL to unlink again */ extern void sbSetInterruptCallBack(int (*f)(void)); -/* writing to cache for bake editing */ -extern void softbody_write_cache(struct Object *ob, struct SoftBody *soft, int cfra); - #endif diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index ef66b29f112..1dd90b4dbda 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -39,8 +39,6 @@ struct Main; void sound_init(); -void sound_reinit(struct bContext *C); - void sound_exit(); struct bSound* sound_new_file(struct Main *main, char* filename); diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h new file mode 100644 index 00000000000..5d5f8cddf47 --- /dev/null +++ b/source/blender/blenkernel/BKE_unit.h @@ -0,0 +1,68 @@ +/** + * + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BKE_UNIT_H +#define BKE_UNIT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* in all cases the value is assumed to be scaled by the user preference */ + +/* humanly readable representation of a value in units (used for button drawing) */ +void bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, int split, int pad); + +/* replace units with values, used before python button evaluation */ +int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pref, int system, int type); + +/* the size of the unit used for this value (used for calculating the ckickstep) */ +double bUnit_ClosestScalar(double value, int system, int type); + +/* base scale for these units */ +double bUnit_BaseScalar(int system, int type); + +/* loop over scales, coudl add names later */ +//double bUnit_Iter(void **unit, char **name, int system, int type); + +void bUnit_GetSystem(void **usys_pt, int *len, int system, int type); +char* bUnit_GetName(void *usys_pt, int index); +char* bUnit_GetNameDisplay(void *usys_pt, int index); +double bUnit_GetScaler(void *usys_pt, int index); + +/* aligned with PropertyUnit */ +#define B_UNIT_NONE 0 +#define B_UNIT_LENGTH 1 +#define B_UNIT_AREA 2 +#define B_UNIT_VOLUME 3 +#define B_UNIT_MASS 4 +#define B_UNIT_ROTATION 5 +#define B_UNIT_TIME 6 +#define B_UNIT_VELOCITY 7 +#define B_UNIT_ACCELERATION 8 + +#ifdef __cplusplus +} +#endif + +#endif /* BKE_UNIT_H */ diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index f5287e4e100..eba5032997d 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -62,11 +62,6 @@ #define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; } #define SHIFT4(type, a, b, c, d) { type tmp; tmp = a; a = d; d = c; c = b; b = tmp; } -/* string compare */ -#define STREQ(str, a) ( strcmp((str), (a))==0 ) -#define STREQ2(str, a, b) ( STREQ(str, a) || STREQ(str, b) ) -#define STREQ3(str, a, b, c) ( STREQ2(str, a, b) || STREQ(str, c) ) - /* min/max */ #define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) #define MIN3(x,y,z) MIN2( MIN2((x),(y)) , (z) ) @@ -100,8 +95,6 @@ if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \ if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; } -#define MINSIZE(val, size) ( ((val)>=0.0) ? (((val)<(size)) ? (size): (val)) : ( ((val)>(-size)) ? (-size) : (val))) - /* some math and copy defines */ #define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 950947f0d24..c1dfc2cf639 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -55,12 +55,6 @@ IF(WITH_QUICKTIME) ADD_DEFINITIONS(-DWITH_QUICKTIME) ENDIF(WITH_QUICKTIME) -IF(WITH_SDL) - SET(INC ${INC} ${SDL_INC}) -ELSE(WITH_SDL) - ADD_DEFINITIONS(-DDISABLE_SDL) -ENDIF(WITH_SDL) - IF(WITH_FFMPEG) SET(INC ${INC} ${FFMPEG_INC}) ADD_DEFINITIONS(-DWITH_FFMPEG) diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 090f256ab9f..84cccd8b939 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -72,6 +72,7 @@ #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_object.h" +#include "BKE_paint.h" #include "BKE_subsurf.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -2076,7 +2077,7 @@ static void clear_mesh_caches(Object *ob) static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) { Object *obact = scene->basact?scene->basact->object:NULL; - int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT); + int editing = paint_facesel_test(ob)|(ob && ob->mode & OB_MODE_PARTICLE_EDIT); int needMapping = editing && (ob==obact); float min[3], max[3]; diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 983f1ecc31c..204935cc38d 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -342,6 +342,21 @@ void BKE_keyingset_add_destination (KeyingSet *ks, ID *id, const char group_name BLI_addtail(&ks->paths, ksp); } +/* Copy all KeyingSets in the given list */ +void BKE_keyingsets_copy(ListBase *newlist, ListBase *list) +{ + KeyingSet *ksn; + KS_Path *kspn; + + BLI_duplicatelist(newlist, list); + + for(ksn=newlist->first; ksn; ksn=ksn->next) { + BLI_duplicatelist(&ksn->paths, &ksn->paths); + + for(kspn=ksn->paths.first; kspn; kspn=kspn->next) + kspn->rna_path= MEM_dupallocN(kspn->rna_path); + } +} /* Freeing Tools --------------------------- */ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 2e4e5596450..746dc6c59cc 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -226,7 +226,7 @@ static void clear_global(void) G.main= NULL; - G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT + G_PARTICLEEDIT); + G.f &= ~(G_FACESELECT); } /* make sure path names are correct for OS */ diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 30a35cbe91c..612f6d2051d 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -35,6 +35,7 @@ #include "DNA_brush_types.h" #include "DNA_color_types.h" #include "DNA_image_types.h" +#include "DNA_object_types.h" #include "DNA_texture_types.h" #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" @@ -50,6 +51,7 @@ #include "BKE_image.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_paint.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -61,7 +63,7 @@ /* Datablock add/copy/free/make_local */ -Brush *add_brush(char *name) +Brush *add_brush(const char *name) { Brush *brush; @@ -152,7 +154,7 @@ void make_local_brush(Brush *brush) } for(scene= G.main->scene.first; scene; scene=scene->id.next) - if(scene->toolsettings->imapaint.brush==brush) { + if(paint_brush(&scene->toolsettings->imapaint.paint)==brush) { if(scene->id.lib) lib= 1; else local= 1; } @@ -174,9 +176,9 @@ void make_local_brush(Brush *brush) brushn->id.flag |= LIB_FAKEUSER; for(scene= G.main->scene.first; scene; scene=scene->id.next) - if(scene->toolsettings->imapaint.brush==brush) + if(paint_brush(&scene->toolsettings->imapaint.paint)==brush) if(scene->id.lib==0) { - scene->toolsettings->imapaint.brush= brushn; + paint_brush_set(&scene->toolsettings->imapaint.paint, brushn); brushn->id.us++; brush->id.us--; } @@ -185,20 +187,7 @@ void make_local_brush(Brush *brush) /* Library Operations */ -Brush **current_brush_source(Scene *sce) -{ - if(G.f & G_SCULPTMODE) - return &sce->toolsettings->sculpt->brush; - else if(G.f & G_VERTEXPAINT) - return &sce->toolsettings->vpaint->brush; - else if(G.f & G_WEIGHTPAINT) - return &sce->toolsettings->wpaint->brush; - else if(G.f & G_TEXTUREPAINT) - return &sce->toolsettings->imapaint.brush; - return NULL; -} - -int brush_set_nr(Brush **current_brush, int nr) +int brush_set_nr(Brush **current_brush, int nr, const char *name) { ID *idtest, *id; @@ -207,7 +196,7 @@ int brush_set_nr(Brush **current_brush, int nr) if(idtest==0) { /* new brush */ if(id) idtest= (ID *)copy_brush((Brush *)id); - else idtest= (ID *)add_brush("Brush"); + else idtest= (ID *)add_brush(name); idtest->us--; } if(idtest!=id) { @@ -300,6 +289,13 @@ void brush_curve_preset(Brush *b, BrushCurvePreset preset) curvemapping_changed(b->curve, 0); } +static MTex *brush_active_texture(Brush *brush) +{ + if(brush && brush->texact >= 0) + return brush->mtex[brush->texact]; + return NULL; +} + int brush_texture_set_nr(Brush *brush, int nr) { ID *idtest, *id=NULL; @@ -374,10 +370,10 @@ int brush_clone_image_delete(Brush *brush) return 0; } -void brush_check_exists(Brush **brush) +void brush_check_exists(Brush **brush, const char *name) { if(*brush==NULL) - brush_set_nr(brush, 1); + brush_set_nr(brush, 1, name); } /* Brush Sampling */ @@ -1077,8 +1073,11 @@ void brush_radial_control_invoke(wmOperator *op, Brush *br, float size_weight) original_value = br->size * size_weight; else if(mode == WM_RADIALCONTROL_STRENGTH) original_value = br->alpha; - else if(mode == WM_RADIALCONTROL_ANGLE) - original_value = br->rot; + else if(mode == WM_RADIALCONTROL_ANGLE) { + MTex *mtex = brush_active_texture(br); + if(mtex) + original_value = mtex->rot; + } RNA_float_set(op->ptr, "initial_value", original_value); op->customdata = brush_gen_radial_control_imbuf(br); @@ -1094,8 +1093,11 @@ int brush_radial_control_exec(wmOperator *op, Brush *br, float size_weight) br->size = new_value * size_weight; else if(mode == WM_RADIALCONTROL_STRENGTH) br->alpha = new_value; - else if(mode == WM_RADIALCONTROL_ANGLE) - br->rot = new_value * conv; + else if(mode == WM_RADIALCONTROL_ANGLE) { + MTex *mtex = brush_active_texture(br); + if(mtex) + mtex->rot = new_value * conv; + } return OPERATOR_FINISHED; } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 089dafeb8c7..3acaaecb1e8 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -340,92 +340,6 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving) } } -int modifiers_indexInObject(Object *ob, ModifierData *md_seek); -static void cloth_write_state(int index, void *cloth_v, float *data) -{ - Cloth *cloth= cloth_v; - ClothVertex *vert = cloth->verts + index; - - memcpy(data, vert->x, 3 * sizeof(float)); - memcpy(data + 3, vert->xconst, 3 * sizeof(float)); - memcpy(data + 6, vert->v, 3 * sizeof(float)); -} -static void cloth_read_state(int index, void *cloth_v, float *data) -{ - Cloth *cloth= cloth_v; - ClothVertex *vert = cloth->verts + index; - - memcpy(vert->x, data, 3 * sizeof(float)); - memcpy(vert->xconst, data + 3, 3 * sizeof(float)); - memcpy(vert->v, data + 6, 3 * sizeof(float)); -} -static void cloth_cache_interpolate(int index, void *cloth_v, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) -{ - Cloth *cloth= cloth_v; - ClothVertex *vert = cloth->verts + index; - ParticleKey keys[4]; - float dfra; - - if(cfra1 == cfra2) { - cloth_read_state(index, cloth, data1); - return; - } - - memcpy(keys[1].co, data1, 3 * sizeof(float)); - memcpy(keys[1].vel, data1 + 6, 3 * sizeof(float)); - - memcpy(keys[2].co, data2, 3 * sizeof(float)); - memcpy(keys[2].vel, data2 + 6, 3 * sizeof(float)); - - dfra = cfra2 - cfra1; - - VecMulf(keys[1].vel, dfra); - VecMulf(keys[2].vel, dfra); - - psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); - - VecMulf(keys->vel, 1.0f / dfra); - - memcpy(vert->x, keys->co, 3 * sizeof(float)); - memcpy(vert->v, keys->vel, 3 * sizeof(float)); - - /* not sure what to do with this - jahka */ - memcpy(vert->xconst, data1 + 3, 3 * sizeof(float)); -} -void cloth_write_cache(Object *ob, ClothModifierData *clmd, int cfra) -{ - PTCacheWriter writer; - PTCacheID pid; - - BKE_ptcache_id_from_cloth(&pid, ob, clmd); - - writer.calldata = clmd->clothObject; - writer.cfra = cfra; - writer.set_elem = cloth_write_state; - writer.pid = &pid; - writer.totelem = clmd->clothObject->numverts; - - BKE_ptcache_write_cache(&writer); -} - -int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr) -{ - PTCacheReader reader; - PTCacheID pid; - - BKE_ptcache_id_from_cloth(&pid, ob, clmd); - - reader.calldata = clmd->clothObject; - reader.cfra = cfra; - reader.interpolate_elem = cloth_cache_interpolate; - reader.old_frame = old_framenr; - reader.pid = &pid; - reader.scene = scene; - reader.set_elem = cloth_read_state; - reader.totelem = clmd->clothObject->numverts; - - return BKE_ptcache_read_cache(&reader); -} void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { PTCacheID pid; @@ -512,7 +426,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, PTCacheID pid; float timescale; int framedelta, framenr, startframe, endframe; - int cache_result, old_framenr; + int cache_result; clmd->scene= scene; /* nice to pass on later :) */ framenr= (int)scene->r.cfra; @@ -583,7 +497,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, return result; /* try to read from cache */ - cache_result = cloth_read_cache(scene, ob, clmd, framenr, &old_framenr); + cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { cache->flag |= PTCACHE_SIMULATION_VALID; @@ -600,7 +514,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, implicit_set_positions(clmd); cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= old_framenr; } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { /* if baked and nothing in cache, do nothing */ @@ -624,7 +537,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, else { /* if on second frame, write cache for first frame */ if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - cloth_write_cache(ob, clmd, startframe); + BKE_ptcache_write_cache(&pid, startframe); clmd->sim_parms->timescale *= framenr - cache->simframe; @@ -638,7 +551,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, cache->last_exact= 0; } else - cloth_write_cache(ob, clmd, framenr); + BKE_ptcache_write_cache(&pid, framenr); cloth_to_object (ob, clmd, result); } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 78c29a96bff..c38b994849a 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -34,6 +34,7 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_object_types.h" #include "RNA_access.h" @@ -43,6 +44,7 @@ #include "BKE_context.h" #include "BKE_main.h" #include "BKE_screen.h" +#include "BKE_global.h" #include <string.h> @@ -217,7 +219,10 @@ struct ARegion *CTX_wm_menu(const bContext *C) struct ReportList *CTX_wm_reports(const bContext *C) { - return &(C->wm.manager->reports); + if (C->wm.manager) + return &(C->wm.manager->reports); + + return NULL; } View3D *CTX_wm_view3d(const bContext *C) @@ -656,6 +661,69 @@ Scene *CTX_data_scene(const bContext *C) return C->data.scene; } +int CTX_data_mode_enum(const bContext *C) +{ + Object *obedit= CTX_data_edit_object(C); + + if(obedit) { + switch(obedit->type) { + case OB_MESH: + return CTX_MODE_EDIT_MESH; + case OB_CURVE: + return CTX_MODE_EDIT_CURVE; + case OB_SURF: + return CTX_MODE_EDIT_SURFACE; + case OB_FONT: + return CTX_MODE_EDIT_TEXT; + case OB_ARMATURE: + return CTX_MODE_EDIT_ARMATURE; + case OB_MBALL: + return CTX_MODE_EDIT_METABALL; + case OB_LATTICE: + return CTX_MODE_EDIT_LATTICE; + } + } + else { + Object *ob = CTX_data_active_object(C); + + if(ob) { + if(ob->mode & OB_MODE_POSE) return CTX_MODE_POSE; + else if(ob->mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT; + else if(ob->mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT; + else if(ob->mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX; + else if(ob->mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE; + else if(ob->mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE; + } + } + + return CTX_MODE_OBJECT; +} + + +/* would prefer if we can use the enum version below over this one - Campbell */ +/* must be aligned with above enum */ +static char *data_mode_strings[] = { + "mesh_edit", + "curve_edit", + "surface_edit", + "text_edit", + "armature_edit", + "mball_edit", + "lattice_edit", + "posemode", + "sculpt_mode", + "weightpaint", + "vertexpaint", + "texturepaint", + "particlemode", + "objectmode", + 0 +}; +char *CTX_data_mode_string(const bContext *C) +{ + return data_mode_strings[CTX_data_mode_enum(C)]; +} + void CTX_data_scene_set(bContext *C, Scene *scene) { C->data.scene= scene; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index a72f26f6157..2f0e0931588 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -160,7 +160,7 @@ static AdrBit2Path ma_mode_bits[]= { // {MA_SHADOW, "shadow", 0}, // {MA_SHLESS, "shadeless", 0}, // ... - {MA_RAYTRANSP, "raytrace_transparency.enabled", 0}, + {MA_RAYTRANSP, "transparency", 0}, {MA_RAYMIRROR, "raytrace_mirror.enabled", 0}, // {MA_HALO, "type", MA_TYPE_HALO} }; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 08a19cada7d..50db2bfe706 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -170,7 +170,7 @@ void init_material(Material *ma) ma->sss_front= 1.0f; ma->sss_back= 1.0f; - ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR; + ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RAYBIAS|MA_TANGENT_STR; ma->preview = NULL; } @@ -678,9 +678,6 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) if(needtang) ma->mode |= MA_NORMAP_TANG; else ma->mode &= ~MA_NORMAP_TANG; - if(r_mode & R_RADIO) - if(ma->mode & MA_RADIO) needuv= 1; - if(ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) { needuv= 1; if(r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */ @@ -689,7 +686,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */ if(r_mode & R_RAYTRACE) { - if(ma->mode & (MA_RAYMIRROR|MA_RAYTRANSP|MA_SHADOW_TRA)) { + if((ma->mode & (MA_RAYMIRROR|MA_SHADOW_TRA)) || ((ma->mode && MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) { ma->texco |= NEED_UV|TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM; if(r_mode & R_OSA) ma->texco |= TEXCO_OSA; } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index f8795edc878..53d1baa5c9c 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5858,8 +5858,7 @@ static void smokeModifier_updateDepgraph( ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { - SmokeModifierData *smd = (SmokeModifierData *) md; - /* + /*SmokeModifierData *smd = (SmokeModifierData *) md; if(smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { if(smd->domain->fluid_group) @@ -5893,7 +5892,7 @@ static void clothModifier_initData(ModifierData *md) clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms"); clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms"); - clmd->point_cache = BKE_ptcache_add(); + clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches); /* check for alloc failing */ if(!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache) @@ -5972,12 +5971,13 @@ static void clothModifier_copyData(ModifierData *md, ModifierData *target) MEM_freeN(tclmd->sim_parms); if(tclmd->coll_parms) MEM_freeN(tclmd->coll_parms); - if(tclmd->point_cache) - BKE_ptcache_free(tclmd->point_cache); + + BKE_ptcache_free_list(&tclmd->ptcaches); + tclmd->point_cache = NULL; tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms); tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms); - tclmd->point_cache = BKE_ptcache_copy(clmd->point_cache); + tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches); tclmd->clothObject = NULL; } @@ -6001,8 +6001,9 @@ static void clothModifier_freeData(ModifierData *md) MEM_freeN(clmd->sim_parms); if(clmd->coll_parms) MEM_freeN(clmd->coll_parms); - if(clmd->point_cache) - BKE_ptcache_free(clmd->point_cache); + + BKE_ptcache_free_list(&clmd->ptcaches); + clmd->point_cache = NULL; } } diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 22a471f6521..e91f318adad 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -220,6 +220,7 @@ static void multires_subdisp(DerivedMesh *orig, Mesh *me, DerivedMesh *final, in int skip = multires_side_tot[totlvl - lvl] - 1; int i, j, k; + memset(&mmd_sub, 0, sizeof(MultiresModifierData)); mmd_sub.lvl = mmd_sub.totlvl = totlvl; mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0); @@ -465,6 +466,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int dista MultiresModifierData mmd_sub; orig = CDDM_from_mesh(me, NULL); + memset(&mmd_sub, 0, sizeof(MultiresModifierData)); mmd_sub.lvl = mmd_sub.totlvl = mmd->lvl; mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0); totsubvert = mrdm->getNumVerts(mrdm); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 0f42ba0d2e2..836f4281eb9 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3112,3 +3112,29 @@ void free_nodesystem(void) BLI_freelistN(&node_all_shaders); BLI_freelistN(&node_all_textures); } + +/* called from unlink_scene, when deleting a scene goes over all scenes + * other than the input, checks if they have render layer nodes referencing + * the to-be-deleted scene, and resets them to NULL. */ + +/* XXX needs to get current scene then! */ +void clear_scene_in_nodes(Main *bmain, Scene *sce) +{ + Scene *sce1; + bNode *node; + + for(sce1= bmain->scene.first; sce1; sce1=sce1->id.next) { + if(sce1!=sce) { + if(sce1->nodetree) { + for(node= sce1->nodetree->nodes.first; node; node= node->next) { + if(node->type==CMP_NODE_R_LAYERS) { + Scene *nodesce= (Scene *)node->id; + + if (nodesce==sce) node->id = NULL; + } + } + } + } + } +} + diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 150a5aa97aa..0e45aedc3ed 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -107,6 +107,7 @@ #include "BKE_sca.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_sculpt.h" #include "BKE_softbody.h" #include "LBM_fluidsim.h" @@ -222,6 +223,34 @@ void object_free_display(Object *ob) freedisplist(&ob->disp); } +void free_sculptsession(SculptSession **ssp) +{ + if(ssp && *ssp) { + SculptSession *ss = *ssp; + if(ss->projverts) + MEM_freeN(ss->projverts); + + if(ss->fmap) + MEM_freeN(ss->fmap); + + if(ss->fmap_mem) + MEM_freeN(ss->fmap_mem); + + if(ss->texcache) + MEM_freeN(ss->texcache); + + if(ss->layer_disps) + MEM_freeN(ss->layer_disps); + + if(ss->mesh_co_orig) + MEM_freeN(ss->mesh_co_orig); + + MEM_freeN(ss); + + *ssp = NULL; + } +} + /* do not free object itself */ void free_object(Object *ob) { @@ -276,6 +305,8 @@ void free_object(Object *ob) if(ob->soft) sbFree(ob->soft); if(ob->bsoft) bsbFree(ob->bsoft); if(ob->gpulamp.first) GPU_lamp_free(ob); + + free_sculptsession(&ob->sculpt); } static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin) @@ -1026,7 +1057,7 @@ SoftBody *copy_softbody(SoftBody *sb) sbn->scratch= NULL; - sbn->pointcache= BKE_ptcache_copy(sb->pointcache); + sbn->pointcache= BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches); return sbn; } @@ -1085,7 +1116,7 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys) psysn->reactevents.first = psysn->reactevents.last = NULL; psysn->renderdata = NULL; - psysn->pointcache= BKE_ptcache_copy(psys->pointcache); + psysn->pointcache= BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches); id_us_plus((ID *)psysn->part); @@ -1211,6 +1242,9 @@ Object *copy_object(Object *ob) copy_defgroups(&obn->defbase, &ob->defbase); copy_constraints(&obn->constraints, &ob->constraints); + obn->mode = 0; + obn->sculpt = NULL; + /* increase user numbers */ id_us_plus((ID *)obn->data); id_us_plus((ID *)obn->dup_group); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c new file mode 100644 index 00000000000..80016f23d7c --- /dev/null +++ b/source/blender/blenkernel/intern/paint.c @@ -0,0 +1,181 @@ +/* + * ***** 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) 2009 by Nicholas Bishop + * 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_brush_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_brush.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_paint.h" + +#include <stdlib.h> +#include <string.h> + +Paint *paint_get_active(Scene *sce) +{ + if(sce && sce->basact && sce->basact->object) { + ToolSettings *ts = sce->toolsettings; + + switch(sce->basact->object->mode) { + case OB_MODE_SCULPT: + return &ts->sculpt->paint; + case OB_MODE_VERTEX_PAINT: + return &ts->vpaint->paint; + case OB_MODE_WEIGHT_PAINT: + return &ts->wpaint->paint; + case OB_MODE_TEXTURE_PAINT: + return &ts->imapaint.paint; + } + } + + return NULL; +} + +Brush *paint_brush(Paint *p) +{ + return p && p->brushes ? p->brushes[p->active_brush_index] : NULL; +} + +void paint_brush_set(Paint *p, Brush *br) +{ + if(p && !br) { + /* Setting to NULL removes the current slot */ + paint_brush_slot_remove(p); + } + else if(p) { + int found = 0; + + if(p->brushes) { + int i; + + /* See if there's already a slot with the brush */ + for(i = 0; i < p->brush_count; ++i) { + if(p->brushes[i] == br) { + p->active_brush_index = i; + found = 1; + break; + } + } + + } + + if(!found) { + paint_brush_slot_add(p); + id_us_plus(&br->id); + } + + /* Make sure the current slot is the new brush */ + p->brushes[p->active_brush_index] = br; + } +} + +static void paint_brush_slots_alloc(Paint *p, const int count) +{ + p->brush_count = count; + if(count == 0) + p->brushes = NULL; + else + p->brushes = MEM_callocN(sizeof(Brush*) * count, "Brush slots"); +} + +void paint_brush_slot_add(Paint *p) +{ + if(p) { + Brush **orig = p->brushes; + int orig_count = p->brushes ? p->brush_count : 0; + + /* Increase size of brush slot array */ + paint_brush_slots_alloc(p, orig_count + 1); + if(orig) { + memcpy(p->brushes, orig, sizeof(Brush*) * orig_count); + MEM_freeN(orig); + } + + p->active_brush_index = orig_count; + } +} + +void paint_brush_slot_remove(Paint *p) +{ + if(p && p->brushes) { + Brush **orig = p->brushes; + int src, dst; + + /* Decrease size of brush slot array */ + paint_brush_slots_alloc(p, p->brush_count - 1); + if(p->brushes) { + for(src = 0, dst = 0; dst < p->brush_count; ++src) { + if(src != p->active_brush_index) { + p->brushes[dst] = orig[src]; + ++dst; + } + } + } + MEM_freeN(orig); + + if(p->active_brush_index >= p->brush_count) + p->active_brush_index = p->brush_count - 1; + if(p->active_brush_index < 0) + p->active_brush_index = 0; + } +} + +int paint_facesel_test(Object *ob) +{ + return (G.f&G_FACESELECT) && (ob && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))); + +} + +void paint_init(Paint *p, const char *name) +{ + Brush *brush; + + /* If there's no brush, create one */ + brush = paint_brush(p); + brush_check_exists(&brush, name); + paint_brush_set(p, brush); +} + +void free_paint(Paint *paint) +{ + if(paint->brushes) + MEM_freeN(paint->brushes); +} + +void copy_paint(Paint *orig, Paint *new) +{ + if(orig->brushes) { + int i; + new->brushes = MEM_dupallocN(orig->brushes); + for(i = 0; i < orig->brush_count; ++i) + id_us_plus((ID *)new->brushes[i]); + } +} diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index e4f8a484061..e1987d34a6c 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -321,7 +321,7 @@ int psys_ob_has_hair(Object *ob) } int psys_in_edit_mode(Scene *scene, ParticleSystem *psys) { - return ((G.f & G_PARTICLEEDIT) && psys==psys_get_current((scene->basact)->object) && psys->edit); + return ((scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys==psys_get_current((scene->basact)->object) && psys->edit); } int psys_check_enabled(Object *ob, ParticleSystem *psys) { @@ -431,9 +431,6 @@ void psys_free(Object *ob, ParticleSystem * psys) int nr = 0; ParticleSystem * tpsys; - if(ob->particlesystem.first == NULL && G.f & G_PARTICLEEDIT) - G.f &= ~G_PARTICLEEDIT; - psys_free_path_cache(psys); free_hair(psys, 1); @@ -484,8 +481,8 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->reactevents.first) BLI_freelistN(&psys->reactevents); - if(psys->pointcache) - BKE_ptcache_free(psys->pointcache); + BKE_ptcache_free_list(&psys->ptcaches); + psys->pointcache = NULL; if(psys->targets.first) BLI_freelistN(&psys->targets); @@ -980,13 +977,13 @@ static void get_pointcache_keys_for_time(Object *ob, ParticleSystem *psys, int i while(pm && pm->next && (float)pm->frame < t) pm = pm->next; - copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1); - copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1); + BKE_ptcache_make_particle_key(key2, pm->index_array ? pm->index_array[index] : index, pm->data, (float)pm->frame); + BKE_ptcache_make_particle_key(key1, pm->prev->index_array ? pm->prev->index_array[index] : index, pm->prev->data, (float)pm->prev->frame); } else if(cache->mem_cache.first) { PTCacheMem *pm2 = cache->mem_cache.first; - copy_particle_key(key2, ((ParticleKey *)pm2->data) + index, 1); - copy_particle_key(key1, ((ParticleKey *)pm2->data) + index, 1); + BKE_ptcache_make_particle_key(key2, pm2->index_array ? pm2->index_array[index] : index, pm2->data, (float)pm2->frame); + copy_particle_key(key1, key2, 1); } } } @@ -3038,7 +3035,7 @@ void object_add_particle_system(Scene *scene, Object *ob) psys->flag &= ~PSYS_CURRENT; psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); - psys->pointcache = BKE_ptcache_add(); + psys->pointcache = BKE_ptcache_add(&psys->ptcaches); BLI_addtail(&ob->particlesystem, psys); psys->part = psys_new_settings("ParticleSettings", NULL); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index b5d58e9db8c..dcd3fcd2f89 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2260,56 +2260,21 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) { PointCache *cache = psys->pointcache; - PTCacheFile *pf = NULL; - PTCacheMem *pm = NULL; PTCacheID pid; - int cfra, sfra = cache->startframe, efra = cache->endframe; - int totelem = psys->totpart; - int float_count = sizeof(ParticleKey) / sizeof(float); - int tot = totelem * float_count; if((cache->flag & PTCACHE_DISK_CACHE)==0 || cache->mem_cache.first) return; BKE_ptcache_id_from_particles(&pid, ob, psys); - for(cfra=sfra; cfra <= efra; cfra++) { - pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra); - - if(pf) { - pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache temp mem"); - pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache temp mem data"); - - if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) { - printf("Error reading from disk cache\n"); - - MEM_freeN(pm->data); - MEM_freeN(pm); - BKE_ptcache_file_close(pf); - return; - } - - pm->frame = cfra; - pm->totpoint = totelem; - - BLI_addtail(&cache->mem_cache, pm); - - BKE_ptcache_file_close(pf); - } - } + BKE_ptcache_disk_to_mem(&pid); } void psys_clear_temp_pointcache(ParticleSystem *psys) { - PTCacheMem *pm = psys->pointcache->mem_cache.first; - if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0) return; - for(; pm; pm=pm->next) { - MEM_freeN(pm->data); - } - - BLI_freelistN(&psys->pointcache->mem_cache); + BKE_ptache_free_mem(psys->pointcache); } void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra) { @@ -2318,88 +2283,6 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra *sfra = MAX2(1, (int)part->sta); *efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra); } -static void particle_write_state(int index, void *psys_ptr, float *data) -{ - ParticleSystem *psys= psys_ptr; - - memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey)); -} -static void particle_read_state(int index, void *psys_ptr, float *data) -{ - ParticleSystem *psys= psys_ptr; - ParticleData *pa = psys->particles + index; - ParticleKey *key = (ParticleKey *)data; - - if(key->time > pa->state.time) - copy_particle_key(&pa->prev_state, &pa->state, 1); - - copy_particle_key(&pa->state, key, 1); -} -static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) -{ - ParticleSystem *psys= psys_ptr; - ParticleData *pa = psys->particles + index; - ParticleKey keys[4]; - float dfra; - - cfra = MIN2(cfra, pa->dietime); - cfra1 = MIN2(cfra1, pa->dietime); - cfra2 = MIN2(cfra2, pa->dietime); - - keys[1] = *((ParticleKey*)data1); - keys[2] = *((ParticleKey*)data2); - - if(cfra1 == cfra2) { - copy_particle_key(&pa->state, &keys[1], 1); - return; - } - - dfra = cfra2 - cfra1; - - VecMulf(keys[1].vel, dfra / frs_sec); - VecMulf(keys[2].vel, dfra / frs_sec); - - psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); - QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); - - VecMulf(pa->state.vel, frs_sec / dfra); - - pa->state.time = cfra; -} -static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra) -{ - PTCacheWriter writer; - PTCacheID pid; - - BKE_ptcache_id_from_particles(&pid, ob, psys); - - writer.calldata = psys; - writer.cfra = cfra; - writer.set_elem = particle_write_state; - writer.pid = &pid; - writer.totelem = psys->totpart; - - BKE_ptcache_write_cache(&writer); -} - -static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int *old_frame) -{ - PTCacheReader reader; - PTCacheID pid; - - BKE_ptcache_id_from_particles(&pid, ob, psys); - - reader.calldata = psys; - reader.cfra = cfra; - reader.interpolate_elem = particle_cache_interpolate; - reader.old_frame = old_frame; - reader.pid = &pid; - reader.scene = scene; - reader.set_elem = particle_read_state; - reader.totelem = psys->totpart; - - return BKE_ptcache_read_cache(&reader); -} /************************************************/ /* Effectors */ @@ -3843,7 +3726,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) alloc=1; - if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT))) + if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))) distr=1; if(distr){ @@ -4237,7 +4120,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle int totpart, oldtotpart, totchild, oldtotchild, p; float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0; - int framenr, framedelta, startframe, endframe, old_framenr; + int framenr, framedelta, startframe, endframe; part= psys->part; cache= psys->pointcache; @@ -4327,8 +4210,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle if(alloc) { realloc_particles(ob, psys, totpart); - if(usecache && !only_children_changed) + if(usecache && !only_children_changed) { BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); + BKE_ptcache_id_from_particles(&pid, ob, psys); + } } if(!only_children_changed) @@ -4358,7 +4243,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* try to read from the cache */ if(usecache) { - int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr); + int result = BKE_ptcache_read_cache(&pid, cfra, scene->r.frs_sec); if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) { cached_step(scene, ob, psmd, psys, cfra); @@ -4369,14 +4254,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle cache->flag |= PTCACHE_SIMULATION_VALID; if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) - write_particles_to_cache(ob, psys, cfra); + BKE_ptcache_write_cache(&pid, (int)cfra); return; } else if(result==PTCACHE_READ_OLD) { - /* set old cfra */ - psys->cfra = (float)old_framenr; - + psys->cfra = (float)cache->simframe; for(p=0, pa=psys->particles; p<totpart; p++, pa++) { /* update alive status */ if(pa->time > psys->cfra) @@ -4402,7 +4285,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* if on second frame, write cache for first frame */ if(usecache && psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - write_particles_to_cache(ob, psys, startframe); + BKE_ptcache_write_cache(&pid, startframe); if(part->phystype==PART_PHYS_KEYED) psys_count_keyed_targets(ob,psys); @@ -4448,7 +4331,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* only write cache starting from second frame */ if(usecache && framenr != startframe) - write_particles_to_cache(ob, psys, framenr); + BKE_ptcache_write_cache(&pid, (int)cfra); /* for keyed particles the path is allways known so it can be drawn */ if(part->phystype==PART_PHYS_KEYED) { diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index beb72c2c13f..09170d92866 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -39,6 +39,7 @@ #include "DNA_object_force.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" +#include "DNA_smoke_types.h" #include "BLI_blenlib.h" @@ -52,11 +53,14 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_scene.h" +#include "BKE_smoke.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" #include "BLI_blenlib.h" +#include "smoke_API.h" + /* needed for directory lookup */ #ifndef WIN32 #include <dirent.h> @@ -77,8 +81,308 @@ #endif #endif -/* Creating ID's */ +static void ptcache_data_to(void **data, int type, int index, void *to); +static void ptcache_data_from(void **data, int type, void *from); + +/* Common functions */ +static int ptcache_read_basic_header(PTCacheFile *pf) +{ + int error=0; + + /* Custom functions should read these basic elements too! */ + if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp)) + error = 1; + + if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp)) + error = 1; + + return !error; +} +static int ptcache_write_basic_header(PTCacheFile *pf) +{ + /* Custom functions should write these basic elements too! */ + if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp)) + return 0; + + if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp)) + return 0; + + return 1; +} +/* Softbody functions */ +static int ptcache_write_softbody(int index, void *soft_v, void **data) +{ + SoftBody *soft= soft_v; + BodyPoint *bp = soft->bpoint + index; + + ptcache_data_from(data, BPHYS_DATA_LOCATION, bp->pos); + ptcache_data_from(data, BPHYS_DATA_VELOCITY, bp->vec); + + return 1; +} +static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data) +{ + SoftBody *soft= soft_v; + BodyPoint *bp = soft->bpoint + index; + + if(old_data) { + memcpy(bp->pos, data, 3 * sizeof(float)); + memcpy(bp->vec, data + 3, 3 * sizeof(float)); + } + else { + ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, bp->pos); + ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, bp->vec); + } +} +static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +{ + SoftBody *soft= soft_v; + BodyPoint *bp = soft->bpoint + index; + ParticleKey keys[4]; + float dfra; + + if(cfra1 == cfra2) + return; + + VECCOPY(keys[1].co, bp->pos); + VECCOPY(keys[1].vel, bp->vec); + + if(old_data) { + memcpy(keys[2].co, old_data, 3 * sizeof(float)); + memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float)); + } + else + BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + + dfra = cfra2 - cfra1; + + VecMulf(keys[1].vel, dfra); + VecMulf(keys[2].vel, dfra); + + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); + VecMulf(keys->vel, 1.0f / dfra); + + VECCOPY(bp->pos, keys->co); + VECCOPY(bp->vec, keys->vel); +} +static int ptcache_totpoint_softbody(void *soft_v) +{ + SoftBody *soft= soft_v; + return soft->totpoint; +} +/* Particle functions */ +static int ptcache_write_particle(int index, void *psys_v, void **data) +{ + ParticleSystem *psys= psys_v; + ParticleData *pa = psys->particles + index; + float times[3] = {pa->time, pa->dietime, pa->lifetime}; + + if(data[BPHYS_DATA_INDEX]) { + int step = psys->pointcache->step; + /* No need to store unborn or died particles */ + if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time) + return 0; + } + + ptcache_data_from(data, BPHYS_DATA_INDEX, &index); + ptcache_data_from(data, BPHYS_DATA_LOCATION, pa->state.co); + ptcache_data_from(data, BPHYS_DATA_VELOCITY, pa->state.vel); + ptcache_data_from(data, BPHYS_DATA_ROTATION, pa->state.rot); + ptcache_data_from(data, BPHYS_DATA_AVELOCITY, pa->state.ave); + ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size); + ptcache_data_from(data, BPHYS_DATA_TIMES, times); + + if(pa->boid) + ptcache_data_from(data, BPHYS_DATA_TIMES, &pa->boid); + + return 1; +} +void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) +{ + ptcache_data_to(data, BPHYS_DATA_LOCATION, index, key->co); + ptcache_data_to(data, BPHYS_DATA_VELOCITY, index, key->vel); + ptcache_data_to(data, BPHYS_DATA_ROTATION, index, key->rot); + ptcache_data_to(data, BPHYS_DATA_AVELOCITY, index, key->ave); + key->time = time; +} +static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) +{ + ParticleSystem *psys= psys_v; + ParticleData *pa = psys->particles + index; + + if(cfra > pa->state.time) + memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey)); + + if(old_data){ + /* old format cache */ + memcpy(&pa->state, old_data, sizeof(ParticleKey)); + return; + } + + BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); + + if(data[BPHYS_DATA_SIZE]) + ptcache_data_to(data, BPHYS_DATA_SIZE, 0, &pa->size); + + if(data[BPHYS_DATA_TIMES]) { + float times[3]; + ptcache_data_to(data, BPHYS_DATA_TIMES, 0, ×); + pa->time = times[0]; + pa->dietime = times[1]; + pa->lifetime = times[2]; + } + + if(pa->boid) + ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &pa->boid); + + /* determine velocity from previous location */ + if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { + if(cfra > pa->prev_state.time) { + VecSubf(pa->state.vel, pa->state.co, pa->prev_state.co); + VecMulf(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); + } + else { + VecSubf(pa->state.vel, pa->prev_state.co, pa->state.co); + VecMulf(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); + } + } + + /* determine rotation from velocity */ + if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { + vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot); + } +} +static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +{ + ParticleSystem *psys= psys_v; + ParticleData *pa = psys->particles + index; + ParticleKey keys[4]; + float dfra; + + cfra = MIN2(cfra, pa->dietime); + cfra1 = MIN2(cfra1, pa->dietime); + cfra2 = MIN2(cfra2, pa->dietime); + + if(cfra1 == cfra2) + return; + + memcpy(keys+1, &pa->state, sizeof(ParticleKey)); + if(old_data) + memcpy(keys+2, old_data, sizeof(ParticleKey)); + else + BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + + dfra = cfra2 - cfra1; + + VecMulf(keys[1].vel, dfra / frs_sec); + VecMulf(keys[2].vel, dfra / frs_sec); + + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); + QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); + + VecMulf(pa->state.vel, frs_sec / dfra); + + pa->state.time = cfra; +} + +static int ptcache_totpoint_particle(void *psys_v) +{ + ParticleSystem *psys = psys_v; + return psys->totpart; +} +static int ptcache_totwrite_particle(void *psys_v) +{ + ParticleSystem *psys = psys_v; + int totwrite = 0; + + /* TODO for later */ + //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0) { + // ParticleData *pa= psys->particles; + // int p, step = psys->pointcache->step; + + // for(p=0; p<psys->totpart; p++,pa++) + // totwrite += (pa->time - step > pa->state.time || pa->dietime + step > pa->state.time); + //} + //else + totwrite= psys->totpart; + + return totwrite; +} + +/* Cloth functions */ +static int ptcache_write_cloth(int index, void *cloth_v, void **data) +{ + ClothModifierData *clmd= cloth_v; + Cloth *cloth= clmd->clothObject; + ClothVertex *vert = cloth->verts + index; + + ptcache_data_from(data, BPHYS_DATA_LOCATION, vert->x); + ptcache_data_from(data, BPHYS_DATA_VELOCITY, vert->v); + ptcache_data_from(data, BPHYS_DATA_XCONST, vert->xconst); + + return 1; +} +static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data) +{ + ClothModifierData *clmd= cloth_v; + Cloth *cloth= clmd->clothObject; + ClothVertex *vert = cloth->verts + index; + + if(old_data) { + memcpy(vert->x, data, 3 * sizeof(float)); + memcpy(vert->xconst, data + 3, 3 * sizeof(float)); + memcpy(vert->v, data + 6, 3 * sizeof(float)); + } + else { + ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, vert->x); + ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, vert->v); + ptcache_data_to(data, BPHYS_DATA_XCONST, 0, vert->xconst); + } +} +static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +{ + ClothModifierData *clmd= cloth_v; + Cloth *cloth= clmd->clothObject; + ClothVertex *vert = cloth->verts + index; + ParticleKey keys[4]; + float dfra; + + if(cfra1 == cfra2) + return; + + VECCOPY(keys[1].co, vert->x); + VECCOPY(keys[1].vel, vert->v); + + if(old_data) { + memcpy(keys[2].co, old_data, 3 * sizeof(float)); + memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float)); + } + else + BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + + dfra = cfra2 - cfra1; + + VecMulf(keys[1].vel, dfra); + VecMulf(keys[2].vel, dfra); + + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); + + VecMulf(keys->vel, 1.0f / dfra); + + VECCOPY(vert->x, keys->co); + VECCOPY(vert->v, keys->vel); + + /* should vert->xconst be interpolated somehow too? - jahka */ +} + +static int ptcache_totpoint_cloth(void *cloth_v) +{ + ClothModifierData *clmd= cloth_v; + return clmd->clothObject->numverts; +} + +/* Creating ID's */ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { ParticleSystemModifierData *psmd; @@ -88,9 +392,24 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; - pid->data= sb; + pid->calldata= sb; pid->type= PTCACHE_TYPE_SOFTBODY; pid->cache= sb->pointcache; + pid->cache_ptr= &sb->pointcache; + pid->ptcaches= &sb->ptcaches; + pid->totpoint= pid->totwrite= ptcache_totpoint_softbody; + + pid->write_elem= ptcache_write_softbody; + pid->write_stream = NULL; + pid->read_stream = NULL; + pid->read_elem= ptcache_read_softbody; + pid->interpolate_elem= ptcache_interpolate_softbody; + + pid->write_header= ptcache_write_basic_header; + pid->read_header= ptcache_read_basic_header; + + pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); + pid->info_types= 0; if(sb->particles) { psmd= psys_get_modifier(ob, sb->particles); @@ -113,21 +432,173 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; - pid->data= psys; + pid->calldata= psys; pid->type= PTCACHE_TYPE_PARTICLES; pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)psmd); pid->cache= psys->pointcache; + pid->cache_ptr= &psys->pointcache; + pid->ptcaches= &psys->ptcaches; + + pid->write_elem= ptcache_write_particle; + pid->write_stream = NULL; + pid->read_stream = NULL; + pid->read_elem= ptcache_read_particle; + pid->interpolate_elem= ptcache_interpolate_particle; + + pid->totpoint= ptcache_totpoint_particle; + pid->totwrite= ptcache_totwrite_particle; + + pid->write_header= ptcache_write_basic_header; + pid->read_header= ptcache_read_basic_header; + + pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); + + /* TODO for later */ + //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0) + // pid->data_types|= (1<<BPHYS_DATA_INDEX); + + if(psys->part->phystype == PART_PHYS_BOIDS) + pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS); + + if(psys->part->rotmode || psys->part->avemode) + pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION); + + if(psys->part->flag & PART_ROT_DYN) + pid->data_types|= (1<<BPHYS_DATA_ROTATION); + + pid->info_types= (1<<BPHYS_DATA_TIMES); +} + +#if 0 // XXX smoke pointcache stuff breaks compiling now +/* Smoke functions */ +static int ptcache_totpoint_smoke(void *smoke_v) +{ + SmokeModifierData *smd= (SmokeModifierData *)smoke_v; + SmokeDomainSettings *sds = smd->domain; + + if(sds->fluid) + { + return sds->res[0]*sds->res[1]*sds->res[2]; + } + else + return 0; +} + +// forward decleration +static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size); + +static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) +{ + SmokeModifierData *smd= (SmokeModifierData *)smoke_v; + SmokeDomainSettings *sds = smd->domain; + + if(sds->fluid) + { + size_t res = sds->res[0]*sds->res[1]*sds->res[2]; + float *dens, *densold, *heat, *heatold, *vx, *vy, *vz; + + smoke_export(sds->fluid, &dens, &densold, &heat, &heatold, &vx, &vy, &vz); + + ptcache_file_write(pf, dens, res, sizeof(float)); + ptcache_file_write(pf, densold, res, sizeof(float)); + ptcache_file_write(pf, heat, res, sizeof(float)); + ptcache_file_write(pf, heatold, res, sizeof(float)); + ptcache_file_write(pf, vx, res, sizeof(float)); + ptcache_file_write(pf, vy, res, sizeof(float)); + ptcache_file_write(pf, vz, res, sizeof(float)); + + return 1; + } + + return 0; +} + +// forward decleration +static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size); + +static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v) +{ + SmokeModifierData *smd= (SmokeModifierData *)smoke_v; + SmokeDomainSettings *sds = smd->domain; + + if(sds->fluid) + { + size_t res = sds->res[0]*sds->res[1]*sds->res[2]; + float *dens, *densold, *heat, *heatold, *vx, *vy, *vz; + + smoke_export(sds->fluid, &dens, &densold, &heat, &heatold, &vx, &vy, &vz); + + ptcache_file_read(pf, dens, res, sizeof(float)); + ptcache_file_read(pf, densold, res, sizeof(float)); + ptcache_file_read(pf, heat, res, sizeof(float)); + ptcache_file_read(pf, heatold, res, sizeof(float)); + ptcache_file_read(pf, vx, res, sizeof(float)); + ptcache_file_read(pf, vy, res, sizeof(float)); + ptcache_file_read(pf, vz, res, sizeof(float)); + + } +} +void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd, int num) +{ + SmokeDomainSettings *sds = smd->domain; + + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->calldata= smd; + + // if(num == 0) + pid->type= PTCACHE_TYPE_SMOKE_DOMAIN_LOW; + // else if(num == 1) + // pid->type= PTCACHE_TYPE_SMOKE_DOMAIN_HIGH; + + pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)smd); + + pid->cache= sds->point_cache; + pid->cache_ptr= &sds->point_cache; + pid->ptcaches= &sds->ptcaches; + + + pid->totpoint= pid->totwrite= ptcache_totpoint_smoke; + + pid->write_elem= NULL; + pid->read_elem= NULL; + pid->read_stream = ptcache_read_smoke; + pid->write_stream = ptcache_write_smoke; + pid->interpolate_elem= NULL; + + pid->write_header= ptcache_write_basic_header; + pid->read_header= ptcache_read_basic_header; + + pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy + pid->info_types= 0; } +#endif // XXX smoke poitcache stuff breaks compiling void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd) { memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; - pid->data= clmd; + pid->calldata= clmd; pid->type= PTCACHE_TYPE_CLOTH; pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)clmd); pid->cache= clmd->point_cache; + pid->cache_ptr= &clmd->point_cache; + pid->ptcaches= &clmd->ptcaches; + pid->totpoint= pid->totwrite= ptcache_totpoint_cloth; + + pid->write_elem= ptcache_write_cloth; + pid->write_stream = NULL; + pid->read_stream = NULL; + pid->read_elem= ptcache_read_cloth; + pid->interpolate_elem= ptcache_interpolate_cloth; + + pid->write_header= ptcache_write_basic_header; + pid->read_header= ptcache_read_basic_header; + + pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST); + pid->info_types= 0; } void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob) @@ -162,9 +633,24 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob) BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md); BLI_addtail(lb, pid); } + /* + // enabled on next commit + if(md->type == eModifierType_Smoke) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if(smd->type & MOD_SMOKE_TYPE_DOMAIN) + { + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md, 0); + BLI_addtail(lb, pid); + } + } + */ } } + +/* File handling */ + /* Takes an Object ID and returns a unique name - id: object id - cfra: frame for the cache, can be negative @@ -177,7 +663,7 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob) static int ptcache_path(PTCacheID *pid, char *filename) { Library *lib; - int i; + size_t i; lib= (pid)? pid->ob->id.lib: NULL; @@ -235,7 +721,7 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho } } else { - int temp = strlen(pid->cache->name); + int temp = (int)strlen(pid->cache->name); strcpy(newname, pid->cache->name); newname+=temp; len += temp; @@ -258,7 +744,7 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho } /* youll need to close yourself after! */ -PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra) +static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) { PTCacheFile *pf; FILE *fp = NULL; @@ -291,136 +777,224 @@ PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra) return pf; } -void BKE_ptcache_file_close(PTCacheFile *pf) +static void ptcache_file_close(PTCacheFile *pf) { fclose(pf->fp); MEM_freeN(pf); } -int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot) +static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size) { - return (fread(f, sizeof(float), tot, pf->fp) == tot); + return (fread(f, size, tot, pf->fp) == tot); } - -int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot) +static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size) { - return (fwrite(f, sizeof(float), tot, pf->fp) == tot); + return (fwrite(f, size, tot, pf->fp) == tot); } - -static int ptcache_pid_elemsize(PTCacheID *pid) +static int ptcache_file_read_data(PTCacheFile *pf) { - if(pid->type==PTCACHE_TYPE_SOFTBODY) - return 6 * sizeof(float); - else if(pid->type==PTCACHE_TYPE_PARTICLES) - return sizeof(ParticleKey); - else if(pid->type==PTCACHE_TYPE_CLOTH) - return 9 * sizeof(float); + int i; - return 0; -} -static int ptcache_pid_totelem(PTCacheID *pid) -{ - if(pid->type==PTCACHE_TYPE_SOFTBODY) { - SoftBody *soft = pid->data; - return soft->totpoint; - } - else if(pid->type==PTCACHE_TYPE_PARTICLES) { - ParticleSystem *psys = pid->data; - return psys->totpart; + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, BKE_ptcache_data_size(i))) + return 0; } - else if(pid->type==PTCACHE_TYPE_CLOTH) { - ClothModifierData *clmd = pid->data; - return clmd->clothObject->numverts; + + return 1; +} +static int ptcache_file_write_data(PTCacheFile *pf) +{ + int i; + + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, BKE_ptcache_data_size(i))) + return 0; } + + return 1; +} +static int ptcache_file_read_header_begin(PTCacheFile *pf) +{ + int error=0; + char bphysics[8]; + + pf->data_types = 0; + + if(fread(bphysics, sizeof(char), 8, pf->fp) != 8) + error = 1; + + if(!error && strncmp(bphysics, "BPHYSICS", 8)) + error = 1; - return 0; + if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp)) + error = 1; + + /* if there was an error set file as it was */ + if(error) + fseek(pf->fp, 0, SEEK_SET); + + return !error; } -void BKE_ptcache_update_info(PTCacheID *pid) + +static int ptcache_file_write_header_begin(PTCacheFile *pf) { - PointCache *cache = pid->cache; - int totframes = 0; - char mem_info[64]; + char *bphysics = "BPHYSICS"; + + if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) + return 0; - if(cache->flag & PTCACHE_EXTERNAL) { - int cfra = cache->startframe; + if(!fwrite(&pf->type, sizeof(int), 1, pf->fp)) + return 0; + + return 1; +} - 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); +/* Data pointer handling */ +int BKE_ptcache_data_size(int data_type) +{ + switch(data_type) { + case BPHYS_DATA_INDEX: + return sizeof(int); + case BPHYS_DATA_LOCATION: + case BPHYS_DATA_VELOCITY: + case BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ + case BPHYS_DATA_TIMES: + return 3 * sizeof(float); + case BPHYS_DATA_ROTATION: + return 4 * sizeof(float); + case BPHYS_DATA_SIZE: + return sizeof(float); + case BPHYS_DATA_BOIDS: + return sizeof(BoidData); + default: + return 0; + } +} +static void ptcache_data_to(void **data, int type, int index, void *to) +{ + if(data[type]) { + if(index) + memcpy(to, (char*)data[type] + index * BKE_ptcache_data_size(type), BKE_ptcache_data_size(type)); else - sprintf(cache->info, "No valid data to read!"); - return; + memcpy(to, data[type], BKE_ptcache_data_size(type)); } +} - if(cache->flag & PTCACHE_DISK_CACHE) { - int cfra = cache->startframe; +static void ptcache_data_from(void **data, int type, void *from) +{ + if(data[type]) + memcpy(data[type], from, BKE_ptcache_data_size(type)); +} - for(; cfra<=cache->endframe; cfra++) { - if(BKE_ptcache_id_exist(pid, cfra)) - totframes++; - } +static void ptcache_file_init_pointers(PTCacheFile *pf) +{ + int data_types = pf->data_types; + + pf->cur[BPHYS_DATA_INDEX] = data_types & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : NULL; + pf->cur[BPHYS_DATA_LOCATION] = data_types & (1<<BPHYS_DATA_LOCATION) ? &pf->data.loc : NULL; + pf->cur[BPHYS_DATA_VELOCITY] = data_types & (1<<BPHYS_DATA_VELOCITY) ? &pf->data.vel : NULL; + pf->cur[BPHYS_DATA_ROTATION] = data_types & (1<<BPHYS_DATA_ROTATION) ? &pf->data.rot : NULL; + pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ? &pf->data.ave : NULL; + pf->cur[BPHYS_DATA_SIZE] = data_types & (1<<BPHYS_DATA_SIZE) ? &pf->data.size : NULL; + pf->cur[BPHYS_DATA_TIMES] = data_types & (1<<BPHYS_DATA_TIMES) ? &pf->data.times : NULL; + pf->cur[BPHYS_DATA_BOIDS] = data_types & (1<<BPHYS_DATA_BOIDS) ? &pf->data.boids : NULL; +} - sprintf(mem_info, "%i frames on disk", totframes); - } - else { - PTCacheMem *pm = cache->mem_cache.first; - float framesize = 0.0f, bytes = 0.0f; - int mb; +static void ptcache_mem_init_pointers(PTCacheMem *pm) +{ + int data_types = pm->data_types; + int i; - if(pm) - framesize = (float)ptcache_pid_elemsize(pid) * (float)pm->totpoint; - - for(; pm; pm=pm->next) - totframes++; + for(i=0; i<BPHYS_TOT_DATA; i++) + pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL; +} - bytes = totframes * framesize; +static void ptcache_mem_incr_pointers(PTCacheMem *pm) +{ + int i; - mb = (bytes > 1024.0f * 1024.0f); + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(pm->cur[i]) + pm->cur[i] = (char*)pm->cur[i] + BKE_ptcache_data_size(i); + } +} +static void ptcache_alloc_data(PTCacheMem *pm) +{ + int data_types = pm->data_types; + int totpoint = pm->totpoint; + int i; - sprintf(mem_info, "%i frames in memory (%.1f %s)", - totframes, - bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), - mb ? "Mb" : "kb"); + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(data_types & (1<<i)) + pm->data[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data"); } +} +static void ptcache_free_data(void *data[]) +{ + int i; - if(cache->flag & PTCACHE_OUTDATED) { - sprintf(cache->info, "%s, cache is outdated!", mem_info); + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(data[i]) + MEM_freeN(data[i]); } - else if(cache->flag & PTCACHE_FRAMES_SKIPPED) { - sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact); +} +static void ptcache_copy_data(void *from[], void *to[]) +{ + int i; + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(from[i]) + memcpy(to[i], from[i], BKE_ptcache_data_size(i)); } - else - sprintf(cache->info, "%s.", mem_info); } + + + +static int ptcache_pid_old_elemsize(PTCacheID *pid) +{ + if(pid->type==PTCACHE_TYPE_SOFTBODY) + return 6 * sizeof(float); + else if(pid->type==PTCACHE_TYPE_PARTICLES) + return sizeof(ParticleKey); + else if(pid->type==PTCACHE_TYPE_CLOTH) + return 9 * sizeof(float); + + return 0; +} + /* reads cache from disk or memory */ /* possible to get old or interpolated result */ -int BKE_ptcache_read_cache(PTCacheReader *reader) +int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) { - PTCacheID *pid = reader->pid; PTCacheFile *pf=NULL, *pf2=NULL; PTCacheMem *pm=NULL, *pm2=NULL; - int totelem = reader->totelem; - float cfra = reader->cfra; + float old_data1[14], old_data2[14]; int cfrai = (int)cfra; - int elemsize = ptcache_pid_elemsize(pid); - int i, incr = elemsize / sizeof(float); - float frs_sec = reader->scene->r.frs_sec; - int cfra1=0, cfra2; - int ret = 0; + int old_elemsize = ptcache_pid_old_elemsize(pid); + int i; + + int cfra1 = 0, cfra2 = 0; + int totpoint = 0, totpoint2 = 0; + int *index = &i, *index2 = &i; + int use_old = 0, old_frame; + + int ret = 0, error = 0; - if(totelem == 0) + /* nothing to read to */ + if(pid->totpoint(pid->calldata) == 0) return 0; + if(pid->cache->flag & PTCACHE_READ_INFO) { + pid->cache->flag &= ~PTCACHE_READ_INFO; + BKE_ptcache_read_cache(pid, 0, frs_sec); + } + /* first check if we have the actual frame cached */ if(cfra == (float)cfrai) { if(pid->cache->flag & PTCACHE_DISK_CACHE) { - pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); } else { pm = pid->cache->mem_cache.first; @@ -432,240 +1006,297 @@ int BKE_ptcache_read_cache(PTCacheReader *reader) } } - /* if found, use exact frame */ - if(pf || pm) { - float *data; - - if(pm) - data = pm->data; - else - data = MEM_callocN(elemsize, "pointcache read data"); + /* no exact cache frame found so try to find cached frames around cfra */ + if(!pm && !pf) { + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pf=NULL; + while(cfrai > pid->cache->startframe && !pf) { + cfrai--; + pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + cfra1 = cfrai; + } - for(i=0; i<totelem; i++) { - if(pf) { - if(!BKE_ptcache_file_read_floats(pf, data, incr)) { - BKE_ptcache_file_close(pf); - MEM_freeN(data); - return 0; - } + old_frame = cfrai; - reader->set_elem(i, reader->calldata, data); + cfrai = (int)cfra; + while(cfrai < pid->cache->endframe && !pf2) { + cfrai++; + pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); + cfra2 = cfrai; } - else { - reader->set_elem(i, reader->calldata, data); - data += incr; + + if(pf && !pf2) { + pf2 = pf; + pf = NULL; } } + else if(pid->cache->mem_cache.first){ + pm = pid->cache->mem_cache.first; - if(pf) { - BKE_ptcache_file_close(pf); - pf = NULL; - MEM_freeN(data); - } + while(pm->next && pm->next->frame < cfra) + pm= pm->next; - ret = PTCACHE_READ_EXACT; - } + if(pm) { + old_frame = pm->frame; + cfra1 = pm->frame; + } - if(ret) - ; - /* no exact cache frame found so try to find cached frames around cfra */ - else if(pid->cache->flag & PTCACHE_DISK_CACHE) { - pf=NULL; - while(cfrai > pid->cache->startframe && !pf) { - cfrai--; - pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra1 = cfrai; - } + pm2 = pid->cache->mem_cache.last; - if(reader->old_frame) - *(reader->old_frame) = cfrai; + if(pm2 && pm2->frame < cfra) + pm2 = NULL; + else { + while(pm2->prev && pm2->prev->frame > cfra) + pm2= pm2->prev; - cfrai = (int)cfra; - while(cfrai < pid->cache->endframe && !pf2) { - cfrai++; - pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai); - cfra2 = cfrai; + if(pm2) + cfra2 = pm2->frame; + } + + if(pm && !pm2) { + pm2 = pm; + pm = NULL; + } } } - else if(pid->cache->mem_cache.first){ - pm = pid->cache->mem_cache.first; - while(pm->next && pm->next->frame < cfra) - pm= pm->next; + if(!pm && !pm2 && !pf && !pf2) + return 0; - if(pm) { - if(reader->old_frame) - *(reader->old_frame) = pm->frame; - cfra1 = pm->frame; + if(pm) { + ptcache_mem_init_pointers(pm); + totpoint = pm->totpoint; + index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i; + } + if(pm2) { + ptcache_mem_init_pointers(pm2); + totpoint2 = pm2->totpoint; + index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i; + } + if(pf) { + if(ptcache_file_read_header_begin(pf)) { + if(pf->type != pid->type) { + /* todo report error */ + ptcache_file_close(pf); + pf = NULL; + } + else if(pid->read_header(pf)) { + ptcache_file_init_pointers(pf); + totpoint = pf->totpoint; + index = pf->data_types & BPHYS_DATA_INDEX ? &pf->data.index : &i; + } } - - pm2 = pid->cache->mem_cache.last; - - if(pm2 && pm2->frame < cfra) - pm2 = NULL; else { - while(pm2->prev && pm2->prev->frame > cfra) - pm2= pm2->prev; - - if(pm2) - cfra2 = pm2->frame; + /* fall back to old cache file format */ + use_old = 1; + totpoint = pid->totpoint(pid->calldata); } } - - if(ret) - ; - else if((pf && pf2) || (pm && pm2)) { - /* interpolate from nearest frames if cache isn't outdated */ - float *data1, *data2; - - if(pm) { - data1 = pm->data; - data2 = pm2->data; + if(pf2) { + if(ptcache_file_read_header_begin(pf2)) { + if(pf2->type != pid->type) { + /* todo report error */ + ptcache_file_close(pf2); + pf2 = NULL; + } + else if(pid->read_header(pf2)) { + ptcache_file_init_pointers(pf2); + totpoint2 = pf2->totpoint; + index2 = pf->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i; + } } else { - data1 = MEM_callocN(elemsize, "pointcache read data1"); - data2 = MEM_callocN(elemsize, "pointcache read data2"); + /* fall back to old cache file format */ + use_old = 1; + totpoint2 = pid->totpoint(pid->calldata); } + } - for(i=0; i<totelem; i++) { - if(pf && pf2) { - if(!BKE_ptcache_file_read_floats(pf, data1, incr)) { - BKE_ptcache_file_close(pf); - BKE_ptcache_file_close(pf2); - MEM_freeN(data1); - MEM_freeN(data2); - return 0; - } - if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) { - BKE_ptcache_file_close(pf); - BKE_ptcache_file_close(pf2); - MEM_freeN(data1); - MEM_freeN(data2); - return 0; - } - reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2); + /* don't read old cache if allready simulated past cached frame */ + if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe) + error = 1; + if(cfra1 && cfra1==cfra2) + error = 1; + + if(!error) + { + if(pf && pid->read_stream) { + if(totpoint != pid->totpoint(pid->calldata)) + error = 1; + else + { + // we have stream writing here + pid->read_stream(pf, pid->calldata); + } + } + } + + totpoint = MIN2(totpoint, pid->totpoint(pid->calldata)); + + if(!error) + { + for(i=0; i<totpoint; i++) { + /* read old cache file format */ + if(use_old) { + if(pid->read_elem && ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize)) + pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1); + else + { error = 1; break; } } else { - reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2); - data1 += incr; - data2 += incr; + if(pid->read_elem && (pm || ptcache_file_read_data(pf))) + pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL); + else + { error = 1; break; } } - } - if(pf) { - BKE_ptcache_file_close(pf); - pf = NULL; - BKE_ptcache_file_close(pf2); - pf2 = NULL; - MEM_freeN(data1); - MEM_freeN(data2); + if(pm) { + ptcache_mem_incr_pointers(pm); + index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i; + } } - - ret = PTCACHE_READ_INTERPOLATED; } - else if(pf || pm) { - /* use last valid cache frame */ - float *data; - - /* don't read cache if allready simulated past cached frame */ - if(cfra1 && cfra1 <= pid->cache->simframe) { - if(pf) - BKE_ptcache_file_close(pf); - if(pf2) - BKE_ptcache_file_close(pf2); - return 0; + if(!error) + { + if(pf2 && pid->read_stream) { + if(totpoint2 != pid->totpoint(pid->calldata)) + error = 1; + else + { + // we have stream writing here + pid->read_stream(pf2, pid->calldata); + } } + } - if(pm) - data = pm->data; - else - data = MEM_callocN(elemsize, "pointcache read data"); - - for(i=0; i<totelem; i++) { - if(pf) { - if(!BKE_ptcache_file_read_floats(pf, data, incr)) { - BKE_ptcache_file_close(pf); - if(pf2) - BKE_ptcache_file_close(pf2); - return 0; + totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata)); + + if(!error) + { + for(i=0; i<totpoint2; i++) { + /* read old cache file format */ + if(use_old) { + if(pid->read_elem && ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) { + if(!pf && pf2) + pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2); + else if(pid->interpolate_elem) + pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2); + else + { error = 1; break; } } - reader->set_elem(i, reader->calldata, data); + else + { error = 1; break; } } else { - reader->set_elem(i, reader->calldata, data); - data += incr; + if(pid->read_elem && (pm2 || ptcache_file_read_data(pf2))) { + if((!pf && pf2) || (!pm && pm2)) + pid->read_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, (float)cfra2, NULL); + else if(pid->interpolate_elem) + pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL); + else + { error = 1; break; } + } + else + { error = 1; break; } } - } - if(pf) { - BKE_ptcache_file_close(pf); - pf = NULL; - MEM_freeN(data); - } - if(pf2) { - BKE_ptcache_file_close(pf2); - pf = NULL; + if(pm2) { + ptcache_mem_incr_pointers(pm2); + index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i; + } } + } + if(pm || pf) + ret = (pm2 || pf2) ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT; + else if(pm2 || pf2) { ret = PTCACHE_READ_OLD; + pid->cache->simframe = old_frame; } - if(pf) - BKE_ptcache_file_close(pf); - if(pf2) - BKE_ptcache_file_close(pf2); + if(pf) { + ptcache_file_close(pf); + pf = NULL; + } + + if(pf2) { + ptcache_file_close(pf2); + pf = NULL; + } if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) { + cfrai = (int)cfra; /* clear invalid cache frames so that better stuff can be simulated */ if(pid->cache->flag & PTCACHE_OUTDATED) { - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai); } else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) { if(cfra <= pid->cache->last_exact) pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfra,pid->cache->last_exact)); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact)); } } - return ret; + return (error ? 0 : ret); } +/* TODO for later */ +//static void ptcache_make_index_array(PTCacheMem *pm, int totpoint) +//{ +// int i, *index; +// +// if(pm->index_array) { +// MEM_freeN(pm->index_array); +// pm->index_array = NULL; +// } +// +// if(!pm->data[BPHYS_DATA_INDEX]) +// return; +// +// pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array"); +// index = pm->data[BPHYS_DATA_INDEX]; +// +// for(i=0; i<pm->totpoint; i++, index++) +// pm->index_array[*index] = i; +//} /* writes cache to disk or memory */ -int BKE_ptcache_write_cache(PTCacheWriter *writer) +int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) { - PointCache *cache = writer->pid->cache; + PointCache *cache = pid->cache; PTCacheFile *pf= NULL; - int elemsize = ptcache_pid_elemsize(writer->pid); - int i, incr = elemsize / sizeof(float); + int i; + int totpoint = pid->totpoint(pid->calldata); int add = 0, overwrite = 0; - float temp[14]; - if(writer->totelem == 0 || writer->cfra <= 0) + if(totpoint == 0 || cfra < 0 + || (cfra ? pid->data_types == 0 : pid->info_types == 0)) return 0; if(cache->flag & PTCACHE_DISK_CACHE) { - int cfra = cache->endframe; + int efra = cache->endframe; + if(cfra==0) + add = 1; /* allways start from scratch on the first frame */ - if(writer->cfra == cache->startframe) { - BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra); + else if(cfra == cache->startframe) { + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); cache->flag &= ~PTCACHE_REDO_NEEDED; add = 1; } else { - int ocfra; + int ofra; /* find last cached frame */ - while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra)) - cfra--; + while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) + efra--; /* find second last cached frame */ - ocfra = cfra-1; - while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra)) - ocfra--; + ofra = efra-1; + while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) + ofra--; - if(cfra >= cache->startframe && writer->cfra > cfra) { - if(ocfra >= cache->startframe && cfra - ocfra < cache->step) + if(efra >= cache->startframe && cfra > efra) { + if(ofra >= cache->startframe && efra - ofra < cache->step) overwrite = 1; else add = 1; @@ -674,74 +1305,92 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) if(add || overwrite) { if(overwrite) - BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, cfra); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra); - pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra); + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); if(!pf) return 0; - for(i=0; i<writer->totelem; i++) { - writer->set_elem(i, writer->calldata, temp); - BKE_ptcache_file_write_floats(pf, temp, incr); + pf->type = pid->type; + pf->totpoint = cfra ? totpoint : pid->totwrite(pid->calldata); + pf->data_types = cfra ? pid->data_types : pid->info_types; + + if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) { + ptcache_file_close(pf); + return 0; } + + ptcache_file_init_pointers(pf); + + if(pf && pid->write_stream) { + // we have stream writing here + pid->write_stream(pf, pid->calldata); + } + else + for(i=0; i<totpoint; i++) { + if(pid->write_elem && pid->write_elem(i, pid->calldata, pf->cur)) + if(!ptcache_file_write_data(pf)) { + ptcache_file_close(pf); + return 0; + } + } } } else { PTCacheMem *pm; PTCacheMem *pm2; - float *pmdata; pm2 = cache->mem_cache.first; + /* don't write info file in memory */ + if(cfra==0) + return 1; /* allways start from scratch on the first frame */ - if(writer->cfra == cache->startframe) { - BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra); + if(cfra == cache->startframe) { + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); cache->flag &= ~PTCACHE_REDO_NEEDED; add = 1; } - else { + else if (cache->mem_cache.last) { pm2 = cache->mem_cache.last; - if(pm2 && writer->cfra > pm2->frame) { + if(pm2 && cfra > pm2->frame) { if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step) overwrite = 1; else add = 1; } } + else + add = 1; - if(overwrite) { - pm = cache->mem_cache.last; - pmdata = pm->data; - - for(i=0; i<writer->totelem; i++, pmdata+=incr) { - writer->set_elem(i, writer->calldata, temp); - memcpy(pmdata, temp, elemsize); - } + if(add || overwrite) { + if(overwrite) + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame); - pm->frame = writer->cfra; - } - else if(add) { pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data"); - pmdata = pm->data; - for(i=0; i<writer->totelem; i++, pmdata+=incr) { - writer->set_elem(i, writer->calldata, temp); - memcpy(pmdata, temp, elemsize); - } + pm->totpoint = pid->totwrite(pid->calldata); + pm->data_types = cfra ? pid->data_types : pid->info_types; + + ptcache_alloc_data(pm); + ptcache_mem_init_pointers(pm); - pm->frame = writer->cfra; - pm->totpoint = writer->totelem; + for(i=0; i<totpoint; i++) { + if(pid->write_elem && pid->write_elem(i, pid->calldata, pm->cur)) + ptcache_mem_incr_pointers(pm); + } + //ptcache_make_index_array(pm, pid->totpoint(pid->calldata)); + pm->frame = cfra; BLI_addtail(&cache->mem_cache, pm); } } if(add || overwrite) { - if(writer->cfra - cache->last_exact == 1 - || writer->cfra == cache->startframe) { - cache->last_exact = writer->cfra; + if(cfra - cache->last_exact == 1 + || cfra == cache->startframe) { + cache->last_exact = cfra; cache->flag &= ~PTCACHE_FRAMES_SKIPPED; } else @@ -749,9 +1398,9 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) } if(pf) - BKE_ptcache_file_close(pf); + ptcache_file_close(pf); - BKE_ptcache_update_info(writer->pid); + BKE_ptcache_update_info(pid); return 1; } @@ -759,7 +1408,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer) * mode - PTCACHE_CLEAR_ALL, */ - +/* Clears & resets */ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) { int len; /* store the length of the string */ @@ -806,7 +1455,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) BLI_delete(path_full, 0, 0); } else { /* read the number of the file */ - int frame, len2 = strlen(de->d_name); + int frame, len2 = (int)strlen(de->d_name); char num[7]; if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ @@ -833,7 +1482,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) if(mode == PTCACHE_CLEAR_ALL) { pid->cache->last_exact = 0; for(; pm; pm=pm->next) - MEM_freeN(pm->data); + ptcache_free_data(pm->data); BLI_freelistN(&pid->cache->mem_cache); } else { while(pm) { @@ -841,7 +1490,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { link = pm; pm = pm->next; - MEM_freeN(link->data); + ptcache_free_data(link->data); BLI_freelinkN(&pid->cache->mem_cache, link); } else @@ -863,7 +1512,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) for(; pm; pm=pm->next) { if(pm->frame == cfra) { - MEM_freeN(pm->data); + ptcache_free_data(pm->data); BLI_freelinkN(&pid->cache->mem_cache, pm); break; } @@ -985,11 +1634,13 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) cache->last_exact= 0; if(pid->type == PTCACHE_TYPE_CLOTH) - cloth_free_modifier(pid->ob, pid->data); + cloth_free_modifier(pid->ob, pid->calldata); else if(pid->type == PTCACHE_TYPE_SOFTBODY) - sbFreeSimulation(pid->data); + sbFreeSimulation(pid->calldata); else if(pid->type == PTCACHE_TYPE_PARTICLES) - psys_reset(pid->data, PSYS_RESET_DEPSGRAPH); + psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); + else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN_LOW) + smokeModifier_reset(pid->calldata); } if(clear) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); @@ -1038,6 +1689,17 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } + /* + // enabled on next commit + if(md->type == eModifierType_Smoke) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if(smd->type & MOD_SMOKE_TYPE_DOMAIN) + { + BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md, 0); + reset |= BKE_ptcache_id_reset(scene, &pid, mode); + } + } + */ } return reset; @@ -1107,9 +1769,9 @@ int BKE_ptcache_get_continue_physics() return CONTINUE_PHYSICS; } -/* Point Cache */ +/* Point Cache handling */ -PointCache *BKE_ptcache_add() +PointCache *BKE_ptcache_add(ListBase *ptcaches) { PointCache *cache; @@ -1118,23 +1780,41 @@ PointCache *BKE_ptcache_add() cache->endframe= 250; cache->step= 10; + BLI_addtail(ptcaches, cache); + return cache; } -void BKE_ptcache_free(PointCache *cache) +void BKE_ptache_free_mem(PointCache *cache) { PTCacheMem *pm = cache->mem_cache.first; + if(pm) { - for(; pm; pm=pm->next) - MEM_freeN(pm->data); + for(; pm; pm=pm->next) { + ptcache_free_data(pm->data); + if(pm->index_array) + MEM_freeN(pm->index_array); + } BLI_freelistN(&cache->mem_cache); } - +} +void BKE_ptcache_free(PointCache *cache) +{ + BKE_ptache_free_mem(cache); MEM_freeN(cache); } +void BKE_ptcache_free_list(ListBase *ptcaches) +{ + PointCache *cache = ptcaches->first; + + for(; cache; cache=cache->next) + BKE_ptache_free_mem(cache); -PointCache *BKE_ptcache_copy(PointCache *cache) + BLI_freelistN(ptcaches); +} + +static PointCache *ptcache_copy(PointCache *cache) { PointCache *ncache; @@ -1149,7 +1829,18 @@ PointCache *BKE_ptcache_copy(PointCache *cache) return ncache; } +/* returns first point cache */ +PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old) +{ + PointCache *cache = ptcaches_old->first; + ptcaches_new->first = ptcaches_new->last = NULL; + + for(; cache; cache=cache->next) + BLI_addtail(ptcaches_new, ptcache_copy(cache)); + + return ptcaches_new->first; +} /* Baking */ @@ -1227,7 +1918,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache = pid->cache; if((cache->flag & PTCACHE_BAKED)==0) { if(pid->type==PTCACHE_TYPE_PARTICLES) - psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); + psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); if(bake || cache->flag & PTCACHE_REDO_NEEDED) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); @@ -1253,12 +1944,12 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache = pid->cache; if((cache->flag & PTCACHE_BAKED)==0) { if(pid->type==PTCACHE_TYPE_PARTICLES) { - ParticleSystem *psys = (ParticleSystem*)pid->data; + ParticleSystem *psys = (ParticleSystem*)pid->calldata; /* skip hair & keyed particles */ if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED) continue; - psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe); + psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); } if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) @@ -1285,10 +1976,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) scene->r.framelen = 1.0; for(; CFRA <= endframe; CFRA+=step) { - float prog; + int prog; if(bake) - prog = (int)(100.0 * (float)(CFRA - startframe)/(float)(endframe-startframe)); + prog = (int)(100.0f * (float)(CFRA - startframe)/(float)(endframe-startframe)); else prog = CFRA; @@ -1307,15 +1998,19 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if(pid) { cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); cache->flag |= PTCACHE_SIMULATION_VALID; - if(bake) + if(bake) { cache->flag |= PTCACHE_BAKED; + /* write info file */ + if(cache->flag & PTCACHE_DISK_CACHE) + BKE_ptcache_write_cache(pid, 0); + } } else for(base=scene->base.first; base; base= base->next) { BKE_ptcache_ids_from_object(&pidlist, base->object); for(pid=pidlist.first; pid; pid=pid->next) { /* skip hair particles */ - if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->data)->part->type == PART_HAIR) + if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR) continue; cache = pid->cache; @@ -1327,8 +2022,11 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) cache->flag |= PTCACHE_SIMULATION_VALID; - if(bake) + if(bake) { cache->flag |= PTCACHE_BAKED; + if(cache->flag & PTCACHE_DISK_CACHE) + BKE_ptcache_write_cache(pid, 0); + } } BLI_freelistN(&pidlist); } @@ -1341,97 +2039,141 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) /* TODO: call redraw all windows somehow */ } - -void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { +/* Helpers */ +void BKE_ptcache_disk_to_mem(PTCacheID *pid) +{ PointCache *cache = pid->cache; PTCacheFile *pf; PTCacheMem *pm; - int totelem=0; - int float_count=0; - int tot; - int last_exact = cache->last_exact; - if (!G.relbase_valid){ - cache->flag &= ~PTCACHE_DISK_CACHE; - printf("File must be saved before using disk cache!\n"); - return; - } + int cfra, sfra = cache->startframe, efra = cache->endframe; + int i; - totelem = ptcache_pid_totelem(pid); - float_count = ptcache_pid_elemsize(pid) / sizeof(float); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - if(totelem==0 || float_count==0) - return; + for(cfra=sfra; cfra <= efra; cfra++) { + pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); - tot = totelem*float_count; + if(pf) { + if(!ptcache_file_read_header_begin(pf)) { + printf("Can't yet convert old cache format\n"); + cache->flag |= PTCACHE_DISK_CACHE; + ptcache_file_close(pf); + return; + } - /* MEM -> DISK */ - if(cache->flag & PTCACHE_DISK_CACHE) { - pm = cache->mem_cache.first; + if(pf->type != pid->type || !pid->read_header(pf)) { + cache->flag |= PTCACHE_DISK_CACHE; + ptcache_file_close(pf); + return; + } + + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + pm->totpoint = pf->totpoint; + pm->data_types = pf->data_types; + pm->frame = cfra; - for(; pm; pm=pm->next) { - pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); + ptcache_alloc_data(pm); + ptcache_mem_init_pointers(pm); + ptcache_file_init_pointers(pf); - if(pf) { - if(fwrite(pm->data, sizeof(float), tot, pf->fp) != tot) { - printf("Error writing to disk cache\n"); + for(i=0; i<pm->totpoint; i++) { + if(!ptcache_file_read_data(pf)) { + printf("Error reading from disk cache\n"); - cache->flag &= ~PTCACHE_DISK_CACHE; + cache->flag |= PTCACHE_DISK_CACHE; + + ptcache_free_data(pm->data); + MEM_freeN(pm); + ptcache_file_close(pf); - BKE_ptcache_file_close(pf); return; } - BKE_ptcache_file_close(pf); + ptcache_copy_data(pf->cur, pm->cur); + ptcache_mem_incr_pointers(pm); } - else - printf("Error creating disk cache file\n"); - } - cache->flag &= ~PTCACHE_DISK_CACHE; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - cache->flag |= PTCACHE_DISK_CACHE; + //ptcache_make_index_array(pm, pid->totpoint(pid->calldata)); + + BLI_addtail(&pid->cache->mem_cache, pm); + + ptcache_file_close(pf); + } } - /* DISK -> MEM */ - else { - int cfra; - int sfra = cache->startframe; - int efra = cache->endframe; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); +} +void BKE_ptcache_mem_to_disk(PTCacheID *pid) +{ + PointCache *cache = pid->cache; + PTCacheFile *pf; + PTCacheMem *pm; + int i; - for(cfra=sfra; cfra <= efra; cfra++) { - pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + pm = cache->mem_cache.first; - if(pf) { - pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache mem data"); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) { - printf("Error reading from disk cache\n"); + for(; pm; pm=pm->next) { + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); - cache->flag |= PTCACHE_DISK_CACHE; + if(pf) { + pf->data_types = pm->data_types; + pf->totpoint = pm->totpoint; + pf->type = pid->type; - MEM_freeN(pm->data); - MEM_freeN(pm); - BKE_ptcache_file_close(pf); - return; - } + ptcache_mem_init_pointers(pm); + ptcache_file_init_pointers(pf); - pm->frame = cfra; - pm->totpoint = totelem; + if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) { + printf("Error writing to disk cache\n"); + cache->flag &= ~PTCACHE_DISK_CACHE; - BLI_addtail(&pid->cache->mem_cache, pm); + ptcache_file_close(pf); + return; + } + + for(i=0; i<pm->totpoint; i++) { + ptcache_copy_data(pm->cur, pf->cur); + if(!ptcache_file_write_data(pf)) { + printf("Error writing to disk cache\n"); + cache->flag &= ~PTCACHE_DISK_CACHE; - BKE_ptcache_file_close(pf); + ptcache_file_close(pf); + return; + } + ptcache_mem_incr_pointers(pm); } + + ptcache_file_close(pf); + + /* write info file */ + if(cache->flag & PTCACHE_BAKED) + BKE_ptcache_write_cache(pid, 0); } + else + printf("Error creating disk cache file\n"); + } +} +void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) +{ + PointCache *cache = pid->cache; + int last_exact = cache->last_exact; - cache->flag |= PTCACHE_DISK_CACHE; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + if (!G.relbase_valid){ cache->flag &= ~PTCACHE_DISK_CACHE; + printf("File must be saved before using disk cache!\n"); + return; } + + if(cache->flag & PTCACHE_DISK_CACHE) + BKE_ptcache_mem_to_disk(pid); + else + BKE_ptcache_disk_to_mem(pid); + + cache->flag ^= PTCACHE_DISK_CACHE; + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + cache->flag ^= PTCACHE_DISK_CACHE; cache->last_exact = last_exact; @@ -1440,15 +2182,16 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { void BKE_ptcache_load_external(PTCacheID *pid) { + /*todo*/ PointCache *cache = pid->cache; int len; /* store the length of the string */ + int info = 0; /* 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) @@ -1475,15 +2218,19 @@ void BKE_ptcache_load_external(PTCacheID *pid) 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); + int frame, len2 = (int)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); + if(frame) { + cache->startframe = MIN2(cache->startframe, frame); + cache->endframe = MAX2(cache->endframe, frame); + } + else + info = 1; } } } @@ -1492,18 +2239,36 @@ void BKE_ptcache_load_external(PTCacheID *pid) 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); + /* read totpoint from info file (frame 0) */ + if(info) { + pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0); + + if(pf) { + if(ptcache_file_read_header_begin(pf)) { + if(pf->type == pid->type && pid->read_header(pf)) { + cache->totpoint = pf->totpoint; + cache->flag |= PTCACHE_READ_INFO; + } + else { + cache->totpoint = 0; + } + } + ptcache_file_close(pf); + } + } + /* or from any old format cache file */ + else { + float old_data[14]; + int elemsize = ptcache_pid_old_elemsize(pid); + pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe); + + if(pf) { + while(ptcache_file_read(pf, old_data, 1, elemsize)) + cache->totpoint++; + + ptcache_file_close(pf); + } } } @@ -1511,3 +2276,65 @@ void BKE_ptcache_load_external(PTCacheID *pid) BKE_ptcache_update_info(pid); } + +void BKE_ptcache_update_info(PTCacheID *pid) +{ + PointCache *cache = pid->cache; + 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 && cache->totpoint) + sprintf(cache->info, "%i points found!", cache->totpoint); + else + sprintf(cache->info, "No valid data to read!"); + return; + } + + if(cache->flag & PTCACHE_DISK_CACHE) { + int cfra = cache->startframe; + + for(; cfra<=cache->endframe; cfra++) { + if(BKE_ptcache_id_exist(pid, cfra)) + totframes++; + } + + sprintf(mem_info, "%i frames on disk", totframes); + } + else { + PTCacheMem *pm = cache->mem_cache.first; + float framesize = 0.0f, bytes = 0.0f; + int mb; + + if(pm) + framesize = (float)ptcache_pid_old_elemsize(pid) * (float)pm->totpoint; + + for(; pm; pm=pm->next) + totframes++; + + bytes = totframes * framesize; + + mb = (bytes > 1024.0f * 1024.0f); + + sprintf(mem_info, "%i frames in memory (%.1f %s)", + totframes, + bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), + mb ? "Mb" : "kb"); + } + + if(cache->flag & PTCACHE_OUTDATED) { + sprintf(cache->info, "%s, cache is outdated!", mem_info); + } + else if(cache->flag & PTCACHE_FRAMES_SKIPPED) { + sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact); + } + else + sprintf(cache->info, "%s.", mem_info); +} diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 0a93874f24e..8488d7ab247 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -54,6 +54,7 @@ #include "DNA_meta_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" #include "DNA_texture_types.h" #include "DNA_userdef_types.h" @@ -75,8 +76,8 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_paint.h" #include "BKE_scene.h" -#include "BKE_sculpt.h" #include "BKE_sequence.h" #include "BKE_world.h" #include "BKE_utildefines.h" @@ -125,7 +126,112 @@ void free_qtcodecdata(QuicktimeCodecData *qcd) } } -/* copy_scene moved to src/header_info.c... should be back */ +Scene *copy_scene(Main *bmain, Scene *sce, int type) +{ + Scene *scen; + ToolSettings *ts; + Base *base, *obase; + + if(type == SCE_COPY_EMPTY) { + ListBase lb; + scen= add_scene(sce->id.name+2); + + lb= scen->r.layers; + scen->r= sce->r; + scen->r.layers= lb; + } + else { + scen= copy_libblock(sce); + BLI_duplicatelist(&(scen->base), &(sce->base)); + + clear_id_newpoins(); + + id_us_plus((ID *)scen->world); + id_us_plus((ID *)scen->set); + id_us_plus((ID *)scen->ima); + id_us_plus((ID *)scen->gm.dome.warptext); + + scen->ed= NULL; + scen->theDag= NULL; + scen->obedit= NULL; + scen->toolsettings= MEM_dupallocN(sce->toolsettings); + + ts= scen->toolsettings; + if(ts) { + if(ts->vpaint) { + ts->vpaint= MEM_dupallocN(ts->vpaint); + ts->vpaint->paintcursor= NULL; + ts->vpaint->vpaint_prev= NULL; + ts->vpaint->wpaint_prev= NULL; + copy_paint(&ts->vpaint->paint, &ts->vpaint->paint); + } + if(ts->wpaint) { + ts->wpaint= MEM_dupallocN(ts->wpaint); + ts->wpaint->paintcursor= NULL; + ts->wpaint->vpaint_prev= NULL; + ts->wpaint->wpaint_prev= NULL; + copy_paint(&ts->wpaint->paint, &ts->wpaint->paint); + } + if(ts->sculpt) { + ts->sculpt= MEM_dupallocN(ts->sculpt); + copy_paint(&ts->sculpt->paint, &ts->sculpt->paint); + } + + copy_paint(&ts->imapaint.paint, &ts->imapaint.paint); + ts->imapaint.paintcursor= NULL; + + ts->particle.paintcursor= NULL; + } + + BLI_duplicatelist(&(scen->markers), &(sce->markers)); + BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces)); + BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers)); + BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); + + scen->nodetree= ntreeCopyTree(sce->nodetree, 0); + + obase= sce->base.first; + base= scen->base.first; + while(base) { + id_us_plus(&base->object->id); + if(obase==sce->basact) scen->basact= base; + + obase= obase->next; + base= base->next; + } + } + + /* make a private copy of the avicodecdata */ + if(sce->r.avicodecdata) { + scen->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata); + scen->r.avicodecdata->lpFormat = MEM_dupallocN(scen->r.avicodecdata->lpFormat); + scen->r.avicodecdata->lpParms = MEM_dupallocN(scen->r.avicodecdata->lpParms); + } + + /* make a private copy of the qtcodecdata */ + if(sce->r.qtcodecdata) { + scen->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata); + scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms); + } + + /* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations + * are done outside of blenkernel with ED_objects_single_users! */ + + /* camera */ + if(type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) { + ID_NEW(scen->camera); + } + + /* world */ + if(type == SCE_COPY_FULL) { + if(scen->world) { + id_us_plus((ID *)scen->world); + scen->world= copy_world(scen->world); + } + } + + return scen; +} /* do not free scene itself */ void free_scene(Scene *sce) @@ -166,15 +272,20 @@ void free_scene(Scene *sce) BLI_freelistN(&sce->r.layers); if(sce->toolsettings) { - if(sce->toolsettings->vpaint) + if(sce->toolsettings->vpaint) { + free_paint(&sce->toolsettings->vpaint->paint); MEM_freeN(sce->toolsettings->vpaint); - if(sce->toolsettings->wpaint) + } + if(sce->toolsettings->wpaint) { + free_paint(&sce->toolsettings->wpaint->paint); MEM_freeN(sce->toolsettings->wpaint); + } if(sce->toolsettings->sculpt) { - sculptsession_free(sce->toolsettings->sculpt); + free_paint(&sce->toolsettings->sculpt->paint); MEM_freeN(sce->toolsettings->sculpt); } - + free_paint(&sce->toolsettings->imapaint.paint); + MEM_freeN(sce->toolsettings); sce->toolsettings = NULL; } @@ -280,6 +391,9 @@ Scene *add_scene(char *name) sce->toolsettings->proportional_size = 1.0f; + + sce->unit.scale_length = 1.0f; + pset= &sce->toolsettings->particle; pset->flag= PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER; pset->emitterdist= 0.25f; @@ -294,7 +408,7 @@ Scene *add_scene(char *name) pset->brush[PE_BRUSH_CUT].strength= 100; sce->jumpframe = 10; - sce->audio.mixrate = 44100; + sce->r.audio.mixrate = 44100; strcpy(sce->r.backbuf, "//backbuf"); strcpy(sce->r.pic, U.renderdir); @@ -387,7 +501,7 @@ void set_scene_bg(Scene *scene) base->flag |= flag; /* not too nice... for recovering objects with lost data */ - if(ob->pose==NULL) base->flag &= ~OB_POSEMODE; + //if(ob->pose==NULL) base->flag &= ~OB_POSEMODE; ob->flag= base->flag; ob->ctime= -1234567.0; /* force ipo to be calculated later */ @@ -410,6 +524,30 @@ void set_scene_name(char *name) //XXX error("Can't find scene: %s", name); } +void unlink_scene(Main *bmain, Scene *sce, Scene *newsce) +{ + Scene *sce1; + bScreen *sc; + + /* check all sets */ + for(sce1= bmain->scene.first; sce1; sce1= sce1->id.next) + if(sce1->set == sce) + sce1->set= NULL; + + /* check all sequences */ + clear_scene_in_allseqs(sce); + + /* check render layer nodes in other scenes */ + clear_scene_in_nodes(bmain, sce); + + /* al screens */ + for(sc= bmain->screen.first; sc; sc= sc->id.next) + if(sc->scene == sce) + sc->scene= newsce; + + free_libblock(&bmain->scene, sce); +} + /* used by metaballs * doesnt return the original duplicated object, only dupli's */ @@ -674,33 +812,6 @@ void scene_add_render_layer(Scene *sce) srl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z; } -void sculptsession_free(Sculpt *sculpt) -{ - SculptSession *ss= sculpt->session; - if(ss) { - if(ss->projverts) - MEM_freeN(ss->projverts); - - if(ss->fmap) - MEM_freeN(ss->fmap); - - if(ss->fmap_mem) - MEM_freeN(ss->fmap_mem); - - if(ss->texcache) - MEM_freeN(ss->texcache); - - if(ss->layer_disps) - MEM_freeN(ss->layer_disps); - - if(ss->mesh_co_orig) - MEM_freeN(ss->mesh_co_orig); - - MEM_freeN(ss); - sculpt->session= NULL; - } -} - /* render simplification */ int get_render_subsurf_level(RenderData *r, int lvl) diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 8224f0dd3f3..22ea41276ff 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -207,7 +207,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive // printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]); // dt max is 0.1 - smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, 2.5 / FPS); + smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, 0.1); smd->domain->wt = smoke_turbulence_init(smd->domain->res, (smd->domain->flags & MOD_SMOKE_HIGHRES) ? (smd->domain->amplify + 1) : 0, smd->domain->noise); smd->time = scene->r.cfra; smd->domain->firstframe = smd->time; @@ -228,6 +228,17 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive // update particle lifetime to be one frame // smd->flow->psys->part->lifetime = scene->r.efra + 1; +/* + if(!smd->flow->bvh) + { + // smd->flow->bvh = MEM_callocN(sizeof(BVHTreeFromMesh), "smoke_bvhfromfaces"); + // bvhtree_from_mesh_faces(smd->flow->bvh, dm, 0.0, 2, 6); + + // copy obmat + // Mat4CpyMat4(smd->flow->mat, ob->obmat); + // Mat4CpyMat4(smd->flow->mat_old, ob->obmat); + } +*/ return 1; } @@ -249,7 +260,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive int *tridivs = NULL; float cell_len = 1.0 / 50.0; // for res = 50 size_t newdivs = 0; - size_t max_points = 0; + //size_t max_points = 0; size_t quads = 0, facecounter = 0; // copy obmat @@ -291,7 +302,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive size_t j, k; int divs1 = tridivs[3 * facecounter + 0]; int divs2 = tridivs[3 * facecounter + 1]; - int divs3 = tridivs[3 * facecounter + 2]; + //int divs3 = tridivs[3 * facecounter + 2]; float side1[3], side2[3], trinormorg[3], trinorm[3]; if(again == 1 && mface[i].v4) @@ -527,6 +538,14 @@ void smokeModifier_freeFlow(SmokeModifierData *smd) { if(smd->flow) { +/* + if(smd->flow->bvh) + { + free_bvhtree_from_mesh(smd->flow->bvh); + MEM_freeN(smd->flow->bvh); + } + smd->flow->bvh = NULL; +*/ MEM_freeN(smd->flow); smd->flow = NULL; } @@ -604,7 +623,14 @@ void smokeModifier_reset(struct SmokeModifierData *smd) } else if(smd->flow) { - + /* + if(smd->flow->bvh) + { + free_bvhtree_from_mesh(smd->flow->bvh); + MEM_freeN(smd->flow->bvh); + } + smd->flow->bvh = NULL; + */ } else if(smd->coll) { @@ -662,11 +688,11 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->omega = 1.0; smd->domain->alpha = -0.001; smd->domain->beta = 0.1; - smd->domain->flags = 0; // MOD_SMOKE_DISSOLVE_INV; + smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG; smd->domain->strength = 2.0; smd->domain->noise = MOD_SMOKE_NOISEWAVE; smd->domain->visibility = 1; - // smd->domain->diss_speed = 50; + smd->domain->diss_speed = 5; // init 3dview buffer smd->domain->tvox = NULL; @@ -723,6 +749,12 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM { // XXX TODO smd->time = scene->r.cfra; + + // rigid movement support + /* + Mat4CpyMat4(smd->flow->mat_old, smd->flow->mat); + Mat4CpyMat4(smd->flow->mat, ob->obmat); + */ } else if(scene->r.cfra < smd->time) { @@ -763,8 +795,13 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM tstart(); - // if(sds->flags & MOD_SMOKE_DISSOLVE) - // smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG, sds->flags & MOD_SMOKE_DISSOLVE_INV); + if(sds->flags & MOD_SMOKE_DISSOLVE) + { + smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); + + if(sds->wt) + smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); + } /* reset view for new frame */ if(sds->viewsettings < MOD_SMOKE_VIEW_USEBIG) @@ -830,7 +867,10 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM float *velocity_x = smoke_get_velocity_x(sds->fluid); float *velocity_y = smoke_get_velocity_y(sds->fluid); float *velocity_z = smoke_get_velocity_z(sds->fluid); - int bigres[3]; + unsigned char *obstacle = smoke_get_obstacle(sds->fluid); + int bigres[3]; + + printf("found flow psys\n"); // mostly copied from particle code for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) @@ -867,15 +907,20 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM // 2. set cell values (heat, density and velocity) index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) // this is inflow + if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index] & 2)) // this is inflow { + // heat[index] += sfs->temp * 0.1; + // density[index] += sfs->density * 0.1; + heat[index] = sfs->temp; density[index] = sfs->density; + /* velocity_x[index] = pa->state.vel[0]; velocity_y[index] = pa->state.vel[1]; velocity_z[index] = pa->state.vel[2]; */ + obstacle[index] |= 2; // we need different handling for the high-res feature if(bigdensity) @@ -894,7 +939,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } } } - else // outflow + else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow { heat[index] = 0.f; density[index] = 0.f; @@ -920,7 +965,21 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } } } - } + } + else + { + /* + for() + { + // no psys + BVHTreeNearest nearest; + + nearest.index = -1; + nearest.dist = FLT_MAX; + + BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh); + }*/ + } } } @@ -1058,7 +1117,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM smd->time = scene->r.cfra; // simulate the actual smoke (c++ code in intern/smoke) - smoke_step(sds->fluid); + smoke_step(sds->fluid, smd->time); if(sds->wt) smoke_turbulence_step(sds->wt, sds->fluid); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 0a1963c84f2..68f918b0c68 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3687,87 +3687,6 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, } } -static void softbody_write_state(int index, void *soft_v, float *data) -{ - SoftBody *soft= soft_v; - BodyPoint *bp = soft->bpoint + index; - - memcpy(data, bp->pos, 3 * sizeof(float)); - memcpy(data + 3, bp->vec, 3 * sizeof(float)); -} -static void softbody_read_state(int index, void *soft_v, float *data) -{ - SoftBody *soft= soft_v; - BodyPoint *bp = soft->bpoint + index; - - memcpy(bp->pos, data, 3 * sizeof(float)); - memcpy(bp->vec, data + 3, 3 * sizeof(float)); -} -static void softbody_cache_interpolate(int index, void *soft_v, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) -{ - SoftBody *soft= soft_v; - BodyPoint *bp = soft->bpoint + index; - ParticleKey keys[4]; - float dfra; - - if(cfra1 == cfra2) { - softbody_read_state(index, soft, data1); - return; - } - - memcpy(keys[1].co, data1, 3 * sizeof(float)); - memcpy(keys[1].vel, data1 + 3, 3 * sizeof(float)); - - memcpy(keys[2].co, data2, 3 * sizeof(float)); - memcpy(keys[2].vel, data2 + 3, 3 * sizeof(float)); - - dfra = cfra2 - cfra1; - - VecMulf(keys[1].vel, dfra); - VecMulf(keys[2].vel, dfra); - - psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); - - VecMulf(keys->vel, 1.0f / dfra); - - memcpy(bp->pos, keys->co, 3 * sizeof(float)); - memcpy(bp->vec, keys->vel, 3 * sizeof(float)); -} -void softbody_write_cache(Object *ob, SoftBody *soft, int cfra) -{ - PTCacheWriter writer; - PTCacheID pid; - - BKE_ptcache_id_from_softbody(&pid, ob, soft); - - writer.calldata = soft; - writer.cfra = cfra; - writer.set_elem = softbody_write_state; - writer.pid = &pid; - writer.totelem = soft->totpoint; - - BKE_ptcache_write_cache(&writer); -} - -int softbody_read_cache(Scene *scene, Object *ob, SoftBody *soft, float cfra, int *old_framenr) -{ - PTCacheReader reader; - PTCacheID pid; - - BKE_ptcache_id_from_softbody(&pid, ob, soft); - - reader.calldata = soft; - reader.cfra = cfra; - reader.interpolate_elem = softbody_cache_interpolate; - reader.old_frame = old_framenr; - reader.pid = &pid; - reader.scene = scene; - reader.set_elem = softbody_read_state; - reader.totelem = soft->totpoint; - - return BKE_ptcache_read_cache(&reader); -} - /* +++ ************ maintaining scratch *************** */ static void sb_new_scratch(SoftBody *sb) { @@ -3827,7 +3746,7 @@ SoftBody *sbNew(Scene *scene) sb->shearstiff = 1.0f; sb->solverflags |= SBSO_OLDERR; - sb->pointcache = BKE_ptcache_add(); + sb->pointcache = BKE_ptcache_add(&sb->ptcaches); return sb; } @@ -3836,7 +3755,8 @@ SoftBody *sbNew(Scene *scene) void sbFree(SoftBody *sb) { free_softbody_intern(sb); - BKE_ptcache_free(sb->pointcache); + BKE_ptcache_free_list(&sb->ptcaches); + sb->pointcache = NULL; MEM_freeN(sb); } @@ -4135,7 +4055,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i PTCacheID pid; float dtime, timescale; int framedelta, framenr, startframe, endframe; - int cache_result, old_framenr; + int cache_result; cache= sb->pointcache; @@ -4221,7 +4141,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i } /* try to read from cache */ - cache_result = softbody_read_cache(scene, ob, sb, framenr, &old_framenr); + cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { cache->flag |= PTCACHE_SIMULATION_VALID; @@ -4235,7 +4155,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i else if(cache_result==PTCACHE_READ_OLD) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= old_framenr; } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { /* if baked and nothing in cache, do nothing */ @@ -4263,7 +4182,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i else { /* if on second frame, write cache for first frame */ if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - softbody_write_cache(ob, sb, startframe); + BKE_ptcache_write_cache(&pid, startframe); softbody_update_positions(ob, sb, vertexCos, numVerts); @@ -4279,7 +4198,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i if(sb->particles==0) softbody_to_object(ob, vertexCos, numVerts, 0); - softbody_write_cache(ob, sb, framenr); + BKE_ptcache_write_cache(&pid, framenr); } } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 347837d1dd0..a3275792a85 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -34,19 +34,7 @@ void sound_init() { AUD_Specs specs; - specs.channels = AUD_CHANNELS_STEREO; - specs.format = AUD_FORMAT_S16; - specs.rate = AUD_RATE_44100; - - if(!AUD_init(AUD_SDL_DEVICE, specs, AUD_DEFAULT_BUFFER_SIZE)) - if(!AUD_init(AUD_OPENAL_DEVICE, specs, AUD_DEFAULT_BUFFER_SIZE*4)) - AUD_init(AUD_NULL_DEVICE, specs, AUD_DEFAULT_BUFFER_SIZE); -} - -void sound_reinit(struct bContext *C) -{ - AUD_Specs specs; - int device, buffersize; + int device, buffersize, success; device = U.audiodevice; buffersize = U.mixbufsize; @@ -66,8 +54,15 @@ void sound_reinit(struct bContext *C) if(specs.channels <= AUD_CHANNELS_INVALID) specs.channels = AUD_CHANNELS_STEREO; - if(!AUD_init(device, specs, buffersize)) - AUD_init(AUD_NULL_DEVICE, specs, buffersize); + if(!AUD_init(device, specs, buffersize)) { + if(device == AUD_SDL_DEVICE) + success= AUD_init(AUD_OPENAL_DEVICE, specs, AUD_DEFAULT_BUFFER_SIZE*4); + else + success= AUD_init(AUD_SDL_DEVICE, specs, AUD_DEFAULT_BUFFER_SIZE*4); + + if(!success) + AUD_init(AUD_NULL_DEVICE, specs, buffersize); + } } void sound_exit() @@ -421,7 +416,7 @@ void sound_scrub(struct bContext *C) int cfra = CFRA; float fps = FPS; - if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) + if(scene->r.audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) { AUD_lock(); diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c new file mode 100644 index 00000000000..e56d8f173e5 --- /dev/null +++ b/source/blender/blenkernel/intern/unit.c @@ -0,0 +1,582 @@ +/** + * + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <math.h> + +#if defined(WIN32) && (!(defined snprintf)) +#define snprintf _snprintf +#endif + +#define TEMP_STR_SIZE 256 + +#define SEP_CHR '#' +#define SEP_STR "#" + +#define EUL 0.000001 + + +/* define a single unit */ +typedef struct bUnitDef { + char *name; + char *name_plural; /* abused a bit for the display name */ + char *name_short; /* this is used for display*/ + char *name_alt; /* can be NULL */ + + char *name_display; /* can be NULL */ + + double scalar; + double bias; /* not used yet, needed for converting temperature */ + int flag; +} bUnitDef; + +#define B_UNIT_DEF_NONE 0 +#define B_UNIT_DEF_SUPPRESS 1 /* Use for units that are not used enough to be translated into for common use */ + +/* define a single unit */ +typedef struct bUnitCollection { + struct bUnitDef *units; + int base_unit; /* use for 0.0, or none given */ + int flag; /* options for this system */ + int length; /* to quickly find the last item */ +} bUnitCollection; + +/* Dummy */ +static struct bUnitDef buDummyDef[] = { + {"", NULL, "", NULL, NULL, 1.0, 0.0}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0, sizeof(buDummyDef)}; + + +/* Lengths */ +static struct bUnitDef buMetricLenDef[] = { + {"kilometer", "kilometers", "km", NULL, "Kilometers", 1000.0, 0.0, B_UNIT_DEF_NONE}, + {"hectometer", "hectometers", "hm", NULL, "10 Meters", 100.0, 0.0, B_UNIT_DEF_SUPPRESS}, + {"dekameter", "dekameters", "dkm",NULL, "10 Meters", 10.0, 0.0, B_UNIT_DEF_SUPPRESS}, + {"meter", "meters", "m", NULL, "Meters", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", 0.1, 0.0, B_UNIT_DEF_SUPPRESS}, + {"centimeter", "centimeters", "cm", NULL, "Centimeters", 0.01, 0.0, B_UNIT_DEF_NONE}, + {"millimeter", "millimeters", "mm", NULL, "Millimeters", 0.001, 0.0, B_UNIT_DEF_NONE}, + {"micrometer", "micrometers", "um", "µm", "Micrometers", 0.000001, 0.0, B_UNIT_DEF_NONE}, // micron too? + + /* These get displayed because of float precision problems in the transform header, + * could work around, but for now probably people wont use these */ + /* + {"nanometer", "Nanometers", "nm", NULL, 0.000000001, 0.0, B_UNIT_DEF_NONE}, + {"picometer", "Picometers", "pm", NULL, 0.000000000001, 0.0,B_UNIT_DEF_NONE}, + */ + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buMetricLenCollecton = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef)/sizeof(bUnitDef)}; + +static struct bUnitDef buImperialLenDef[] = { + {"mile", "miles", "mi", "m", "Miles", 1609.344, 0.0, B_UNIT_DEF_NONE}, + {"furlong", "furlongs", "fur", NULL, "Furlongs",201.168, 0.0, B_UNIT_DEF_SUPPRESS}, + {"chain", "chains", "ch", NULL, "Chains", 0.9144*22.0, 0.0, B_UNIT_DEF_SUPPRESS}, + {"yard", "yards", "yd", NULL, "Yards", 0.9144, 0.0, B_UNIT_DEF_NONE}, + {"foot", "feet", "'", "ft", "Feet", 0.3048, 0.0, B_UNIT_DEF_NONE}, + {"inch", "inches", "\"", "in", "Inches", 0.0254, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"thou", "thous", "mil", NULL, "Thous", 0.0000254, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef)/sizeof(bUnitDef)}; + + +/* Time */ +static struct bUnitDef buNaturalTimeDef[] = { + /* weeks? - probably not needed for blender */ + {"day", "days", "d", NULL, "Days", 90000.0, 0.0, B_UNIT_DEF_NONE}, + {"hour", "hours", "hr", "h", "Hours", 3600.0, 0.0, B_UNIT_DEF_NONE}, + {"minute", "minutes", "min", "m", "Minutes", 60.0, 0.0, B_UNIT_DEF_NONE}, + {"second", "seconds", "sec", "s", "Seconds", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"millisecond", "milliseconds", "ms", NULL, "Milliseconds", 0.001, 0.0 , B_UNIT_DEF_NONE}, + {"microsecond", "microseconds", "us", NULL, "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef)/sizeof(bUnitDef)}; + +#define UNIT_SYSTEM_MAX 3 +static struct bUnitCollection *bUnitSystems[][8] = { + {0,0,0,0,0,0,0,0}, + {0,&buMetricLenCollecton, 0,0,0,0, &buNaturalTimeCollecton,0}, /* metric */ + {0,&buImperialLenCollecton, 0,0,0,0, &buNaturalTimeCollecton,0}, /* imperial */ + {0,0,0,0,0,0,0,0} +}; + +/* internal, has some option not exposed */ +static bUnitCollection *unit_get_system(int system, int type) +{ + return bUnitSystems[system][type]; /* select system to use, metric/imperial/other? */ +} + +static bUnitDef *unit_default(bUnitCollection *usys) +{ + return &usys->units[usys->base_unit]; +} + +static bUnitDef *unit_best_fit(double value, bUnitCollection *usys, bUnitDef *unit_start, int suppress) +{ + bUnitDef *unit; + double value_abs= value>0.0?value:-value; + + for(unit= unit_start ? unit_start:usys->units; unit->name; unit++) { + + if(suppress && (unit->flag & B_UNIT_DEF_SUPPRESS)) + continue; + + if (value_abs >= unit->scalar*(1.0-EUL)) /* scale down scalar so 1cm doesnt convert to 10mm because of float error */ + return unit; + } + + return unit_default(usys); +} + + + +/* convert into 2 units and 2 values for "2ft, 3inch" syntax */ +static void unit_dual_convert(double value, bUnitCollection *usys, + bUnitDef **unit_a, bUnitDef **unit_b, double *value_a, double *value_b) +{ + bUnitDef *unit= unit_best_fit(value, usys, NULL, 1); + + *value_a= floor(value/unit->scalar) * unit->scalar; + *value_b= value - (*value_a); + + *unit_a= unit; + *unit_b= unit_best_fit(*value_b, usys, *unit_a, 1); +} + +static int unit_as_string(char *str, int len_max, double value, int prec, bUnitCollection *usys, + /* non exposed options */ + bUnitDef *unit, char pad) +{ + double value_conv; + int len, i; + + if(unit) { + /* use unit without finding the best one */ + } + else if(value == 0.0) { + /* use the default units since there is no way to convert */ + unit= unit_default(usys); + } + else { + unit= unit_best_fit(value, usys, NULL, 1); + } + + value_conv= value/unit->scalar; + + /* Convert to a string */ + { + char conv_str[6] = {'%', '.', '0'+prec, 'l', 'f', '\0'}; /* "%.2lf" when prec is 2, must be under 10 */ + len= snprintf(str, len_max, conv_str, (float)value_conv); + + if(len >= len_max) + len= len_max; + } + + /* Add unit prefix and strip zeros */ + + /* replace trailing zero's with spaces + * so the number is less complicated but allignment in a button wont + * jump about while dragging */ + i= len-1; + + while(i>0 && str[i]=='0') { /* 4.300 -> 4.3 */ + str[i--]= pad; + } + + if(i>0 && str[i]=='.') { /* 10. -> 10 */ + str[i--]= pad; + } + + /* Now add the suffix */ + if(i<len_max) { + int j=0; + i++; + while(unit->name_short[j] && (i < len_max)) { + str[i++]= unit->name_short[j++]; + } + + if(pad) { + /* this loop only runs if so many zeros were removed that + * the unit name only used padded chars, + * In that case add padding for the name. */ + + while(i<=len+j && (i < len_max)) { + str[i++]= pad; + } + } + } + + /* terminate no matter whats done with padding above */ + if(i >= len_max) + i= len_max-1; + + str[i] = '\0'; + return i; +} + + +/* Used for drawing number buttons, try keep fast */ +void bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, int split, int pad) +{ + bUnitCollection *usys = unit_get_system(system, type); + + if(usys==NULL || usys->units[0].name==NULL) + usys= &buDummyCollecton; + + if(split) { + int i; + bUnitDef *unit_a, *unit_b; + double value_a, value_b; + + unit_dual_convert(value, usys, &unit_a, &unit_b, &value_a, &value_b); + + /* check the 2 is a smaller unit */ + if(unit_b > unit_a) { + i= unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0'); + + /* is there enough space for at least 1 char of the next unit? */ + if(i+2 < len_max) { + str[i++]= ' '; + + /* use low precision since this is a smaller unit */ + unit_as_string(str+i, len_max-i, value_b, prec?1:0, usys, unit_b, '\0'); + } + return; + } + } + + unit_as_string(str, len_max, value, prec, usys, NULL, pad?' ':'\0'); +} + + +static char *unit_find_str(char *str, char *substr) +{ + char *str_found; + + if(substr && substr[0] != '\0') { + str_found= strstr(str, substr); + if(str_found) { + /* previous char cannot be a letter */ + if (str_found == str || isalpha(*(str_found-1))==0) { + /* next char cannot be alphanum */ + int len_name = strlen(substr); + + if (!isalpha(*(str_found+len_name))) { + return str_found; + } + } + } + + } + return NULL; + +} + +/* Note that numbers are added within brackets + * ") " - is used to detect numbers we added so we can detect if commas need to be added + * + * "1m1cm+2mm" - Original value + * "1*1#1*0.01#+2*0.001#" - Replace numbers + * "1*1,1*0.01 +2*0.001 " - Add comma's if ( - + * / % ^ < > ) not found in between + * + */ + +/* not too strict, (- = * /) are most common */ +static int ch_is_op(char op) +{ + switch(op) { + case '+': + case '-': + case '*': + case '/': + case '|': + case '<': + case '>': + case '^': + case '!': + case '=': + return 1; + default: + return 0; + } +} + +static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit, char *replace_str) +{ + char *str_found; + + if((len_max>0) && (str_found= unit_find_str(str, replace_str))) { /* XXX - investigate, does not respect len_max properly */ + int len, len_num, len_name, len_move, found_ofs; + + found_ofs = (int)(str_found-str); + + len= strlen(str); + + len_name = strlen(replace_str); + len_move= (len - (found_ofs+len_name)) + 1; /* 1+ to copy the string terminator */ + len_num= snprintf(str_tmp, TEMP_STR_SIZE, "*%lg"SEP_STR, unit->scalar/scale_pref); /* # removed later */ + + if(len_num > len_max) + len_num= len_max; + + if(found_ofs+len_num+len_move > len_max) { + /* can't move the whole string, move just as much as will fit */ + len_move -= (found_ofs+len_num+len_move) - len_max; + } + + if(len_move>0) { + /* resize the last part of the string */ + memmove(str_found+len_num, str_found+len_name, len_move); /* may grow or shrink the string */ + } + + if(found_ofs+len_num > len_max) { + /* not even the number will fit into the string, only copy part of it */ + len_num -= (found_ofs+len_num) - len_max; + } + + if(len_num > 0) { + /* its possible none of the number could be copied in */ + memcpy(str_found, str_tmp, len_num); /* without the string terminator */ + } + + /* since the null terminator wont be moved if the stringlen_max + * was not long enough to fit everything in it */ + str[len_max-1]= '\0'; + return found_ofs + len_num; + } + return 0; +} + +static int unit_replace(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit) +{ + int ofs= 0; + ofs += unit_scale_str(str+ofs, len_max-ofs, str_tmp, scale_pref, unit, unit->name_short); + ofs += unit_scale_str(str+ofs, len_max-ofs, str_tmp, scale_pref, unit, unit->name_plural); + ofs += unit_scale_str(str+ofs, len_max-ofs, str_tmp, scale_pref, unit, unit->name_alt); + ofs += unit_scale_str(str+ofs, len_max-ofs, str_tmp, scale_pref, unit, unit->name); + return ofs; +} + +static int unit_find(char *str, bUnitDef *unit) +{ + if (unit_find_str(str, unit->name_short)) return 1; + if (unit_find_str(str, unit->name_plural)) return 1; + if (unit_find_str(str, unit->name_alt)) return 1; + if (unit_find_str(str, unit->name)) return 1; + + return 0; +} + +/* make a copy of the string that replaces the units with numbers + * this is used before parsing + * This is only used when evaluating user input and can afford to be a bit slower + * + * This is to be used before python evaluation so.. + * 10.1km -> 10.1*1000.0 + * ...will be resolved by python. + * + * values will be split by a comma's + * 5'2" -> 5'0.0254, 2*0.3048 + * + * str_prev is optional, when valid it is used to get a base unit when none is set. + * + * return true of a change was made. + */ +int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pref, int system, int type) +{ + bUnitCollection *usys = unit_get_system(system, type); + + bUnitDef *unit; + char str_tmp[TEMP_STR_SIZE]; + int change= 0; + + if(usys==NULL || usys->units[0].name==NULL) { + return 0; + } + + + { /* make lowercase */ + int i; + char *ch= str; + + for(i=0; (i>=len_max || *ch=='\0'); i++, ch++) + if((*ch>='A') && (*ch<='Z')) + *ch += ('a'-'A'); + } + + + for(unit= usys->units; unit->name; unit++) { + + if(unit->flag & B_UNIT_DEF_SUPPRESS) + continue; + + /* incase there are multiple instances */ + while(unit_replace(str, len_max, str_tmp, scale_pref, unit)) + change= 1; + } + unit= NULL; + + { + /* try other unit systems now, so we can evaluate imperial when metric is set for eg. */ + bUnitCollection *usys_iter; + int system_iter; + + for(system_iter= 1; system_iter<UNIT_SYSTEM_MAX; system_iter++) { + if (system_iter != system) { + usys_iter= unit_get_system(system_iter, type); + for(unit= usys_iter->units; unit->name; unit++) { + + if((unit->flag & B_UNIT_DEF_SUPPRESS) == 0) { + int ofs = 0; + /* incase there are multiple instances */ + while((ofs=unit_replace(str+ofs, len_max-ofs, str_tmp, scale_pref, unit))) + change= 1; + } + } + } + } + } + unit= NULL; + + if(change==0) { + /* no units given so infer a unit from the previous string or default */ + if(str_prev) { + /* see which units the original value had */ + for(unit= usys->units; unit->name; unit++) { + + if(unit->flag & B_UNIT_DEF_SUPPRESS) + continue; + + if (unit_find(str_prev, unit)) + break; + } + } + + if(unit==NULL) + unit= unit_default(usys); + + /* add the unit prefic and re-run, use brackets incase there was an expression given */ + if(snprintf(str_tmp, sizeof(str_tmp), "(%s)%s", str, unit->name) < sizeof(str_tmp)) { + strncpy(str, str_tmp, len_max); + return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type); + } + else { + /* snprintf would not fit into str_tmp, cant do much in this case + * check for this because otherwise bUnit_ReplaceString could call its self forever */ + return 0; + } + + } + + /* replace # with commas when there is no operator between it and the next number + * + * "1*1# 3*100# * 3" -> "1 *1, 3 *100 * 3" + * + * */ + { + char *str_found= str; + char *ch= str; + + while((str_found= strchr(str_found, SEP_CHR))) { + + int op_found= 0; + /* any operators after this?*/ + for(ch= str_found+1; *ch!='\0'; ch++) { + + if(*ch==' ' || *ch=='\t') { + /* do nothing */ + } + else if (ch_is_op(*ch) || *ch==',') { /* found an op, no need to insert a ,*/ + op_found= 1; + break; + } + else { /* found a non-op character */ + op_found= 0; + break; + } + } + + *str_found++ = op_found ? ' ':','; + } + } + + // printf("replace %s\n", str); + return change; +} + + +double bUnit_ClosestScalar(double value, int system, int type) +{ + bUnitCollection *usys = unit_get_system(system, type); + bUnitDef *unit; + + if(usys==NULL) + return -1; + + unit= unit_best_fit(value, usys, NULL, 1); + if(unit==NULL) + return -1; + + return unit->scalar; +} + +double bUnit_BaseScalar(int system, int type) +{ + bUnitCollection *usys = unit_get_system(system, type); + return unit_default(usys)->scalar; +} + +/* external access */ +void bUnit_GetSystem(void **usys_pt, int *len, int system, int type) +{ + bUnitCollection *usys = unit_get_system(system, type); + *usys_pt= usys; + + if(usys==NULL) { + *len= 0; + return; + } + + *len= usys->length; +} + +char *bUnit_GetName(void *usys_pt, int index) +{ + return ((bUnitCollection *)usys_pt)->units[index].name; +} +char *bUnit_GetNameDisplay(void *usys_pt, int index) +{ + return ((bUnitCollection *)usys_pt)->units[index].name_display; +} + +double bUnit_GetScaler(void *usys_pt, int index) +{ + return ((bUnitCollection *)usys_pt)->units[index].scalar; +} |