Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Susano Pinto <andresusanopinto@gmail.com>2009-08-17 21:43:49 +0400
committerAndre Susano Pinto <andresusanopinto@gmail.com>2009-08-17 21:43:49 +0400
commit950b770c1ea0c05a907abc93ad7174a02432843f (patch)
tree12936d6440bc7a0710a2fc776d1e122e000ea71e /source/blender/blenkernel
parent0e3acbaa386384f1b1d27a2b4e0f0dcd07c0e0e2 (diff)
parent931ffbedaa3e76a6ebec3df2af22176e504158db (diff)
svn merge -r 22371:22571 https://svn.blender.org/svnroot/bf-blender/branches/blender2.5/blender
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_animsys.h3
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_brush.h7
-rw-r--r--source/blender/blenkernel/BKE_cloth.h4
-rw-r--r--source/blender/blenkernel/BKE_context.h22
-rw-r--r--source/blender/blenkernel/BKE_global.h12
-rw-r--r--source/blender/blenkernel/BKE_node.h5
-rw-r--r--source/blender/blenkernel/BKE_paint.h51
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h136
-rw-r--r--source/blender/blenkernel/BKE_scene.h11
-rw-r--r--source/blender/blenkernel/BKE_sculpt.h7
-rw-r--r--source/blender/blenkernel/BKE_sequence.h4
-rw-r--r--source/blender/blenkernel/BKE_softbody.h3
-rw-r--r--source/blender/blenkernel/BKE_sound.h2
-rw-r--r--source/blender/blenkernel/BKE_unit.h68
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h7
-rw-r--r--source/blender/blenkernel/CMakeLists.txt6
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c3
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c15
-rw-r--r--source/blender/blenkernel/intern/blender.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c52
-rw-r--r--source/blender/blenkernel/intern/cloth.c95
-rw-r--r--source/blender/blenkernel/intern/context.c70
-rw-r--r--source/blender/blenkernel/intern/ipo.c2
-rw-r--r--source/blender/blenkernel/intern/material.c7
-rw-r--r--source/blender/blenkernel/intern/modifier.c17
-rw-r--r--source/blender/blenkernel/intern/multires.c2
-rw-r--r--source/blender/blenkernel/intern/node.c26
-rw-r--r--source/blender/blenkernel/intern/object.c38
-rw-r--r--source/blender/blenkernel/intern/paint.c181
-rw-r--r--source/blender/blenkernel/intern/particle.c19
-rw-r--r--source/blender/blenkernel/intern/particle_system.c141
-rw-r--r--source/blender/blenkernel/intern/pointcache.c1593
-rw-r--r--source/blender/blenkernel/intern/scene.c181
-rw-r--r--source/blender/blenkernel/intern/smoke.c85
-rw-r--r--source/blender/blenkernel/intern/softbody.c95
-rw-r--r--source/blender/blenkernel/intern/sound.c27
-rw-r--r--source/blender/blenkernel/intern/unit.c582
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, &times);
+ 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;
+}