Sculpt Branch:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 10 Dec 2009 14:26:06 +0000 (14:26 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 10 Dec 2009 14:26:06 +0000 (14:26 +0000)
Revised external multires file saving. Now it is more manual in that you
have to specify where to save it, like an image file, but still saved at
the same time as the .blend. It would ideally be automatic, but this is
difficult to implement, so for now this should at least be more reliable.

19 files changed:
release/scripts/ui/properties_data_modifier.py
source/blender/blenkernel/BKE_btex.h [deleted file]
source/blender/blenkernel/BKE_customdata.h
source/blender/blenkernel/BKE_customdata_file.h [new file with mode: 0644]
source/blender/blenkernel/BKE_utildefines.h
source/blender/blenkernel/intern/btex.c [deleted file]
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/customdata_file.c [new file with mode: 0644]
source/blender/blenkernel/intern/multires.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/space_file/file_draw.c
source/blender/editors/space_file/filelist.c
source/blender/editors/space_file/filesel.c
source/blender/makesdna/DNA_space_types.h
source/blender/makesrna/intern/rna_modifier.c
source/blender/windowmanager/intern/wm_operators.c

index 8194027..97c8f60 100644 (file)
@@ -438,7 +438,6 @@ class DATA_PT_modifiers(DataButtonsPanel):
         col.prop(md, "levels", text="Preview")
         col.prop(md, "sculpt_levels", text="Sculpt")
         col.prop(md, "render_levels", text="Render")
-        col.prop(md, "optimal_display")
 
         if wide_ui:
             col = split.column()
@@ -446,9 +445,20 @@ class DATA_PT_modifiers(DataButtonsPanel):
         col.enabled = ob.mode != 'EDIT'
         col.operator("object.multires_subdivide", text="Subdivide")
         col.operator("object.multires_higher_levels_delete", text="Delete Higher")
+        col.prop(md, "optimal_display")
+
+        layout.separator()
+
+        col = layout.column()
         row = col.row()
-        row.enabled = md.total_levels > 0
-        row.prop(md, "external")
+        if md.external:
+            row.operator("object.multires_pack_external", text="Pack External")
+            row.label()
+            row = col.row()
+            row.prop(md, "filename", text="")
+        else:
+            row.operator("object.multires_save_external", text="Save External...")
+            row.label()
 
     def PARTICLE_INSTANCE(self, layout, ob, md, wide_ui):
         layout.prop(md, "object")
diff --git a/source/blender/blenkernel/BKE_btex.h b/source/blender/blenkernel/BKE_btex.h
deleted file mode 100644 (file)
index cb73fd1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef BKE_BTEX_H
-#define BKE_BTEX_H
-
-#define BTEX_TYPE_IMAGE        0
-#define BTEX_TYPE_MESH 1
-
-#define BTEX_LAYER_NAME_MAX    64
-
-typedef struct BTex BTex;
-typedef struct BTexLayer BTexLayer;
-
-/* Create/Free */
-
-BTex *btex_create(int type);
-void btex_free(BTex *btex);
-
-/* File read/write/remove */
-
-int btex_read_open(BTex *btex, char *filename);
-int btex_read_layer(BTex *btex, BTexLayer *blay);
-int btex_read_data(BTex *btex, int size, void *data);
-void btex_read_close(BTex *btex);
-
-int btex_write_open(BTex *btex, char *filename);
-int btex_write_layer(BTex *btex, BTexLayer *blay);
-int btex_write_data(BTex *btex, int size, void *data);
-void btex_write_close(BTex *btex);
-
-void btex_remove(char *filename);
-
-/* Layers */
-
-BTexLayer *btex_layer_find(BTex *btex, int type, char *name);
-BTexLayer *btex_layer_add(BTex *btex, int type, char *name);
-void btex_layer_remove(BTex *btex, BTexLayer *blay);
-
-/* Mesh */
-
-void btex_mesh_set_grids(BTex *btex, int totgrid, int gridsize, int datasize);
-
-#endif /* BKE_BTEX_H */
-
index 5ce4b39..5f13e70 100644 (file)
@@ -32,6 +32,7 @@
 #ifndef BKE_CUSTOMDATA_H
 #define BKE_CUSTOMDATA_H
 
+struct ID;
 struct CustomData;
 struct CustomDataLayer;
 typedef unsigned int CustomDataMask;
@@ -282,16 +283,15 @@ void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize);
 /* External file storage */
 
 void CustomData_external_add(struct CustomData *data,
-       int type, const char *name, int totelem);
+       struct ID *id, int type, int totelem, const char *filename);
 void CustomData_external_remove(struct CustomData *data,
-       int type, int totelem);
-void CustomData_external_remove_object(struct CustomData *data);
+       struct ID *id, int type, int totelem);
 int CustomData_external_test(struct CustomData *data, int type);
 
 void CustomData_external_write(struct CustomData *data,
-       CustomDataMask mask, int totelem, int free);
+       struct ID *id, CustomDataMask mask, int totelem, int free);
 void CustomData_external_read(struct CustomData *data,
-       CustomDataMask mask, int totelem);
+       struct ID *id, CustomDataMask mask, int totelem);
 
 #endif
 
diff --git a/source/blender/blenkernel/BKE_customdata_file.h b/source/blender/blenkernel/BKE_customdata_file.h
new file mode 100644 (file)
index 0000000..5cbff19
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ *
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_CUSTOMDATA_FILE_H
+#define BKE_CUSTOMDATA_FILE_H
+
+#define CDF_TYPE_IMAGE 0
+#define CDF_TYPE_MESH  1
+
+#define CDF_LAYER_NAME_MAX     64
+
+typedef struct CDataFile CDataFile;
+typedef struct CDataFileLayer CDataFileLayer;
+
+/* Create/Free */
+
+CDataFile *cdf_create(int type);
+void cdf_free(CDataFile *cdf);
+
+/* File read/write/remove */
+
+int cdf_read_open(CDataFile *cdf, char *filename);
+int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay);
+int cdf_read_data(CDataFile *cdf, int size, void *data);
+void cdf_read_close(CDataFile *cdf);
+
+int cdf_write_open(CDataFile *cdf, char *filename);
+int cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay);
+int cdf_write_data(CDataFile *cdf, int size, void *data);
+void cdf_write_close(CDataFile *cdf);
+
+void cdf_remove(char *filename);
+
+/* Layers */
+
+CDataFileLayer *cdf_layer_find(CDataFile *cdf, int type, char *name);
+CDataFileLayer *cdf_layer_add(CDataFile *cdf, int type, char *name, size_t datasize);
+
+#endif /* BKE_CUSTOMDATA_FILE_H */
+
index c0ed843..c052af7 100644 (file)
 #define ENDB MAKE_ID('E','N','D','B')
 
 
-/* This one rotates the bytes in an int */
+/* This one rotates the bytes in an int64, int (32) and short (16) */
+#define SWITCH_INT64(a) { \
+       char s_i, *p_i; \
+       p_i= (char *)&(a); \
+       s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
+       s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
+       s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
+       s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
+
 #define SWITCH_INT(a) { \
        char s_i, *p_i; \
        p_i= (char *)&(a); \
diff --git a/source/blender/blenkernel/intern/btex.c b/source/blender/blenkernel/intern/btex.c
deleted file mode 100644 (file)
index 363e515..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_fileops.h"
-#include "BLI_string.h"
-
-#include "BKE_btex.h"
-#include "BKE_global.h"
-#include "BKE_utildefines.h"
-
-/************************* File Format Definitions ***************************/
-
-#define BTEX_ENDIAN_LITTLE     0
-#define BTEX_ENDIAN_BIG                1
-
-#define BTEX_DATA_FLOAT        0
-
-typedef struct BTexHeader {
-       char ID[4];                                     /* "BTEX" */
-       char endian;                            /* little, big */
-       char version;                           /* non-compatible versions */
-       char subversion;                        /* compatible sub versions */
-       char pad;                                       /* padding */
-
-       int structbytes;                        /* size of this struct in bytes */
-       int type;                                       /* image, mesh */
-       int totlayer;                           /* number of layers in the file */
-} BTexHeader;
-
-typedef struct BTexImageHeader {
-       int structbytes;                        /* size of this struct in bytes */
-       int width;                                      /* image width */
-       int height;                                     /* image height */
-       int tile_size;                          /* tile size (required power of 2) */
-} BTexImageHeader;
-
-typedef struct BTexMeshHeader {
-       int structbytes;                        /* size of this struct in bytes */
-       int totgrid;                            /* number of grids */
-       int gridsize;                           /* width of grids */
-} BTexMeshHeader;
-
-struct BTexLayer {
-       int structbytes;                                /* size of this struct in bytes */
-       int datatype;                                   /* only float for now */
-       int datasize;                                   /* size of data in layer */
-       int type;                                               /* layer type */
-       char name[BTEX_LAYER_NAME_MAX]; /* layer name */
-};
-
-/**************************** Other Definitions ******************************/
-
-#define BTEX_VERSION           0
-#define BTEX_SUBVERSION                0
-#define BTEX_TILE_SIZE         64
-
-struct BTex {
-       int type;
-
-       BTexHeader header;
-       union {
-               BTexImageHeader image;
-               BTexMeshHeader mesh;
-       } btype;
-
-       BTexLayer *layer;
-       int totlayer;
-
-       FILE *readf;
-       FILE *writef;
-       int switchendian;
-       size_t dataoffset;
-};
-
-/********************************* Create/Free *******************************/
-
-static int btex_endian(void)
-{
-       if(ENDIAN_ORDER == L_ENDIAN)
-               return BTEX_ENDIAN_LITTLE;
-       else
-               return BTEX_ENDIAN_BIG;
-}
-
-/*static int btex_data_type_size(int datatype)
-{
-       if(datatype == BTEX_DATA_FLOAT)
-               return sizeof(float);
-       
-       return 0;
-}*/
-
-BTex *btex_create(int type)
-{
-       BTex *btex= MEM_callocN(sizeof(BTex), "BTex");
-
-       btex->type= type;
-
-       return btex;
-}
-
-void btex_free(BTex *btex)
-{
-       btex_read_close(btex);
-       btex_write_close(btex);
-
-       if(btex->layer)
-               MEM_freeN(btex->layer);
-
-       MEM_freeN(btex);
-}
-
-/********************************* Read/Write ********************************/
-
-static int btex_read_header(BTex *btex)
-{
-       BTexHeader *header;
-       BTexImageHeader *image;
-       BTexMeshHeader *mesh;
-       BTexLayer *layer;
-       FILE *f= btex->readf;
-       size_t offset = 0;
-       int a;
-
-       header= &btex->header;
-
-       if(!fread(header, sizeof(BTexHeader), 1, btex->readf))
-               return 0;
-       
-       if(memcmp(header->ID, "BTEX", sizeof(header->ID)) != 0)
-               return 0;
-       if(header->version > BTEX_VERSION)
-               return 0;
-
-       btex->switchendian= header->endian != btex_endian();
-       header->endian= btex_endian();
-
-       if(btex->switchendian) {
-               SWITCH_INT(header->type);
-               SWITCH_INT(header->totlayer);
-               SWITCH_INT(header->structbytes);
-       }
-
-       if(!ELEM(header->type, BTEX_TYPE_IMAGE, BTEX_TYPE_MESH))
-               return 0;
-
-       offset += header->structbytes;
-       header->structbytes= sizeof(BTexHeader);
-
-       if(fseek(f, offset, SEEK_SET) != 0)
-               return 0;
-       
-       if(header->type == BTEX_TYPE_IMAGE) {
-               image= &btex->btype.image;
-               if(!fread(image, sizeof(BTexImageHeader), 1, f))
-                       return 0;
-
-               if(btex->switchendian) {
-                       SWITCH_INT(image->width);
-                       SWITCH_INT(image->height);
-                       SWITCH_INT(image->tile_size);
-                       SWITCH_INT(image->structbytes);
-               }
-
-               offset += image->structbytes;
-               image->structbytes= sizeof(BTexImageHeader);
-       }
-       else if(header->type == BTEX_TYPE_MESH) {
-               mesh= &btex->btype.mesh;
-               if(!fread(mesh, sizeof(BTexMeshHeader), 1, f))
-                       return 0;
-
-               if(btex->switchendian) {
-                       SWITCH_INT(mesh->totgrid);
-                       SWITCH_INT(mesh->gridsize);
-                       SWITCH_INT(mesh->structbytes);
-               }
-
-               offset += mesh->structbytes;
-               mesh->structbytes= sizeof(BTexMeshHeader);
-       }
-
-       if(fseek(f, offset, SEEK_SET) != 0)
-               return 0;
-
-       btex->layer= MEM_callocN(sizeof(BTexLayer)*header->totlayer, "BTexLayer");
-       btex->totlayer= header->totlayer;
-
-       for(a=0; a<header->totlayer; a++) {
-               layer= &btex->layer[a];
-
-               if(!fread(layer, sizeof(BTexLayer), 1, f))
-                       return 0;
-
-               if(btex->switchendian) {
-                       SWITCH_INT(layer->type);
-                       SWITCH_INT(layer->datatype);
-                       SWITCH_INT(layer->datasize);
-                       SWITCH_INT(layer->structbytes);
-               }
-
-               if(layer->datatype != BTEX_DATA_FLOAT)
-                       return 0;
-
-               offset += layer->structbytes;
-               layer->structbytes= sizeof(BTexLayer);
-
-               if(fseek(f, offset, SEEK_SET) != 0)
-                       return 0;
-       }
-
-       btex->dataoffset= offset;
-
-       return 1;
-}
-
-static int btex_write_header(BTex *btex)
-{
-       BTexHeader *header;
-       BTexImageHeader *image;
-       BTexMeshHeader *mesh;
-       BTexLayer *layer;
-       FILE *f= btex->writef;
-       int a;
-
-       header= &btex->header;
-
-       if(!fwrite(header, sizeof(BTexHeader), 1, f))
-               return 0;
-       
-       if(header->type == BTEX_TYPE_IMAGE) {
-               image= &btex->btype.image;
-               if(!fwrite(image, sizeof(BTexImageHeader), 1, f))
-                       return 0;
-       }
-       else if(header->type == BTEX_TYPE_MESH) {
-               mesh= &btex->btype.mesh;
-               if(!fwrite(mesh, sizeof(BTexMeshHeader), 1, f))
-                       return 0;
-       }
-
-       for(a=0; a<header->totlayer; a++) {
-               layer= &btex->layer[a];
-
-               if(!fwrite(layer, sizeof(BTexLayer), 1, f))
-                       return 0;
-       }
-
-       return 1;
-}
-
-int btex_read_open(BTex *btex, char *filename)
-{
-       FILE *f;
-
-       f= fopen(filename, "rb");
-       if(!f)
-               return 0;
-       
-       btex->readf= f;
-
-       if(!btex_read_header(btex)) {
-               btex_read_close(btex);
-               return 0;
-       }
-
-       if(btex->header.type != btex->type) {
-               btex_read_close(btex);
-               return 0;
-       }
-
-       return 1;
-}
-
-int btex_read_layer(BTex *btex, BTexLayer *blay)
-{
-       size_t offset;
-       int a;
-
-       /* seek to right location in file */
-       offset= btex->dataoffset;
-       for(a=0; a<btex->totlayer; a++) {
-               if(&btex->layer[a] == blay)
-                       break;
-               else
-                       offset += btex->layer[a].datasize;
-       }
-
-       return (fseek(btex->readf, offset, SEEK_SET) == 0);
-}
-
-int btex_read_data(BTex *btex, int size, void *data)
-{
-       float *fdata;
-       int a;
-       
-       /* read data */
-       if(!fread(data, size, 1, btex->readf))
-               return 0;
-
-       /* switch endian if necessary */
-       if(btex->switchendian) {
-               fdata= data;
-
-               for(a=0; a<size/sizeof(float); a++)
-                       SWITCH_INT(fdata[a])
-       }
-
-       return 1;
-}
-
-void btex_read_close(BTex *btex)
-{
-       if(btex->readf) {
-               fclose(btex->readf);
-               btex->readf= NULL;
-       }
-}
-
-int btex_write_open(BTex *btex, char *filename)
-{
-       BTexHeader *header;
-       BTexImageHeader *image;
-       BTexMeshHeader *mesh;
-       FILE *f;
-
-       f= fopen(filename, "wb");
-       if(!f)
-               return 0;
-       
-       btex->writef= f;
-
-       /* fill header */
-       header= &btex->header;
-       strcpy(header->ID, "BTEX");
-       header->endian= btex_endian();
-       header->version= BTEX_VERSION;
-       header->subversion= BTEX_SUBVERSION;
-
-       header->structbytes= sizeof(BTexHeader);
-       header->type= btex->type;
-       header->totlayer= btex->totlayer;
-
-       if(btex->type == BTEX_TYPE_IMAGE) {
-               /* fill image header */
-               image= &btex->btype.image;
-               image->structbytes= sizeof(BTexImageHeader);
-               image->tile_size= BTEX_TILE_SIZE;
-       }
-       else if(btex->type == BTEX_TYPE_MESH) {
-               /* fill mesh header */
-               mesh= &btex->btype.mesh;
-               mesh->structbytes= sizeof(BTexMeshHeader);
-       }
-
-       btex_write_header(btex);
-
-       return 1;
-}
-
-int btex_write_layer(BTex *btex, BTexLayer *blay)
-{
-       return 1;
-}
-
-int btex_write_data(BTex *btex, int size, void *data)
-{
-       /* write data */
-       if(!fwrite(data, size, 1, btex->writef))
-               return 0;
-
-       return 1;
-}
-
-void btex_write_close(BTex *btex)
-{
-       if(btex->writef) {
-               fclose(btex->writef);
-               btex->writef= NULL;
-       }
-}
-
-void btex_remove(char *filename)
-{
-       BLI_delete(filename, 0, 0);
-}
-
-/********************************** Layers ***********************************/
-
-BTexLayer *btex_layer_find(BTex *btex, int type, char *name)
-{
-       BTexLayer *layer;
-       int a;
-
-       for(a=0; a<btex->totlayer; a++) {
-               layer= &btex->layer[a];
-
-               if(layer->type == type && strcmp(layer->name, name) == 0)
-                       return layer;
-       }
-       
-       return NULL;
-}
-
-BTexLayer *btex_layer_add(BTex *btex, int type, char *name)
-{
-       BTexLayer *newlayer, *layer;
-
-       /* expand array */
-       newlayer= MEM_callocN(sizeof(BTexLayer)*(btex->totlayer+1), "BTexLayer");
-       memcpy(newlayer, btex->layer, sizeof(BTexLayer)*btex->totlayer);
-       btex->layer= newlayer;
-
-       btex->totlayer++;
-
-       /* fill in new layer */
-       layer= &btex->layer[btex->totlayer-1];
-       layer->structbytes= sizeof(BTexLayer);
-       layer->datatype= BTEX_DATA_FLOAT;
-       layer->type= type;
-       BLI_strncpy(layer->name, name, BTEX_LAYER_NAME_MAX);
-
-       return layer;
-}
-
-void btex_layer_remove(BTex *btex, BTexLayer *layer)
-{
-       BTexLayer *newlayer;
-       int index= layer - btex->layer;
-
-       /* expand array */
-       newlayer= MEM_callocN(sizeof(BTexLayer)*(btex->totlayer-1), "BTexLayer");
-       if(index > 0)
-               memcpy(newlayer, btex->layer, sizeof(BTexLayer)*index);
-       if(index+1 < btex->totlayer)
-               memcpy(newlayer+index, btex->layer+index+1, sizeof(BTexLayer)*(btex->totlayer-(index+1)));
-       btex->layer= newlayer;
-
-       btex->totlayer--;
-}
-
-/********************************* Mesh **************************************/
-
-void btex_mesh_set_grids(BTex *btex, int totgrid, int gridsize, int datasize)
-{
-       BTexLayer *layer;
-       int a;
-
-       btex->btype.mesh.totgrid= totgrid;
-       btex->btype.mesh.gridsize= gridsize;
-
-       for(a=0; a<btex->totlayer; a++) {
-               layer= &btex->layer[a];
-               layer->datasize= datasize;
-       }
-}
-
index f999770..d9e85d5 100644 (file)
@@ -48,8 +48,8 @@
 #include "BLI_mempool.h"
 #include "BLI_string.h"
 
-#include "BKE_btex.h"
 #include "BKE_customdata.h"
+#include "BKE_customdata_file.h"
 #include "BKE_global.h"
 #include "BKE_utildefines.h"
 
@@ -95,11 +95,14 @@ typedef struct LayerTypeInfo {
           default is assumed to be all zeros */
        void (*set_default)(void *data, int count);
 
-    /* a function to read data from a btex file */
-       int (*read)(BTex *btex, void *data, int count);
+    /* a function to read data from a cdf file */
+       int (*read)(CDataFile *cdf, void *data, int count);
 
-    /* a function to write data to a btex file */
-       int (*write)(BTex *btex, void *data, int count);
+    /* a function to write data to a cdf file */
+       int (*write)(CDataFile *cdf, void *data, int count);
+
+    /* a function to determine file size */
+       size_t (*filesize)(CDataFile *cdf, void *data, int count);
 } LayerTypeInfo;
 
 static void layerCopy_mdeformvert(const void *source, void *dest,
@@ -550,7 +553,7 @@ static void layerFree_mdisps(void *data, int count, int size)
        }
 }
 
-static int layerRead_mdisps(BTex *btex, void *data, int count)
+static int layerRead_mdisps(CDataFile *cdf, void *data, int count)
 {
        MDisps *d = data;
        int i;
@@ -559,7 +562,7 @@ static int layerRead_mdisps(BTex *btex, void *data, int count)
                if(!d[i].disps)
                        d[i].disps = MEM_callocN(sizeof(float)*3*d[i].totdisp, "mdisps read");
 
-               if(!btex_read_data(btex, d[i].totdisp*3*sizeof(float), d[i].disps)) {
+               if(!cdf_read_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) {
                        printf("failed to read %d/%d %d\n", i, count, d[i].totdisp);
                        return 0;
                }
@@ -568,13 +571,13 @@ static int layerRead_mdisps(BTex *btex, void *data, int count)
        return 1;
 }
 
-static int layerWrite_mdisps(BTex *btex, void *data, int count)
+static int layerWrite_mdisps(CDataFile *cdf, void *data, int count)
 {
        MDisps *d = data;
        int i;
 
        for(i = 0; i < count; ++i) {
-               if(!btex_write_data(btex, d[i].totdisp*3*sizeof(float), d[i].disps)) {
+               if(!cdf_write_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) {
                        printf("failed to write %d/%d %d\n", i, count, d[i].totdisp);
                        return 0;
                }
@@ -583,6 +586,18 @@ static int layerWrite_mdisps(BTex *btex, void *data, int count)
        return 1;
 }
 
+static size_t layerFilesize_mdisps(CDataFile *cdf, void *data, int count)
+{
+       MDisps *d = data;
+       size_t size = 0;
+       int i;
+
+       for(i = 0; i < count; ++i)
+               size += d[i].totdisp*3*sizeof(float);
+
+       return size;
+}
+
 /* --------- */
 
 static void layerDefault_mloopcol(void *data, int count)
@@ -776,7 +791,7 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
        {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
        {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
        {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
-        layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps},
+        layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps},
        {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol,
         layerSwap_mcol, layerDefault_mcol},
         {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol,
@@ -838,8 +853,6 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
        CustomDataLayer *layer, *newlayer;
        int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0;
 
-       CustomData_external_read(dest, mask, totelem);
-
        for(i = 0; i < source->totlayer; ++i) {
                layer = &source->layers[i];
                typeInfo = layerType_getInfo(layer->type);
@@ -2297,18 +2310,20 @@ int CustomData_verify_versions(struct CustomData *data, int index)
 
 /****************************** External Files *******************************/
 
-static void customdata_external_filename(char filename[FILE_MAX], CustomDataExternal *external)
+static void customdata_external_filename(char filename[FILE_MAX], ID *id, CustomDataExternal *external)
 {
+       char *path = (id->lib)? id->lib->filename: G.sce;
+
        BLI_strncpy(filename, external->filename, FILE_MAX);
-       BLI_convertstringcode(filename, G.sce);
+       BLI_convertstringcode(filename, path);
 }
 
-void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem)
+void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int totelem)
 {
        CustomDataExternal *external= data->external;
        CustomDataLayer *layer;
-       BTex *btex;
-       BTexLayer *blay;
+       CDataFile *cdf;
+       CDataFileLayer *blay;
        char filename[FILE_MAX];
        const LayerTypeInfo *typeInfo;
        int i, update = 0;
@@ -2329,10 +2344,10 @@ void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem
        if(!update)
                return;
 
-       customdata_external_filename(filename, external);
+       customdata_external_filename(filename, id, external);
 
-       btex= btex_create(BTEX_TYPE_MESH);
-       if(!btex_read_open(btex, filename))
+       cdf= cdf_create(CDF_TYPE_MESH);
+       if(!cdf_read_open(cdf, filename))
                return;
 
        for(i=0; i<data->totlayer; i++) {
@@ -2342,11 +2357,11 @@ void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem
                if(!(mask & (1<<layer->type)));
                else if(layer->flag & CD_FLAG_IN_MEMORY);
                else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
-                       blay= btex_layer_find(btex, layer->type, layer->name);
+                       blay= cdf_layer_find(cdf, layer->type, layer->name);
 
                        if(blay) {
-                               if(btex_read_layer(btex, blay)) {
-                                       if(typeInfo->read(btex, layer->data, totelem));
+                               if(cdf_read_layer(cdf, blay)) {
+                                       if(typeInfo->read(cdf, layer->data, totelem));
                                        else break;
                                        layer->flag |= CD_FLAG_IN_MEMORY;
                                }
@@ -2356,16 +2371,16 @@ void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem
                }
        }
 
-       btex_read_close(btex);
-       btex_free(btex);
+       cdf_read_close(cdf);
+       cdf_free(cdf);
 }
 
-void CustomData_external_write(CustomData *data, CustomDataMask mask, int totelem, int free)
+void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, int totelem, int free)
 {
        CustomDataExternal *external= data->external;
        CustomDataLayer *layer;
-       BTex *btex;
-       BTexLayer *blay;
+       CDataFile *cdf;
+       CDataFileLayer *blay;
        const LayerTypeInfo *typeInfo;
        int i, update = 0;
        char filename[FILE_MAX];
@@ -2385,20 +2400,21 @@ void CustomData_external_write(CustomData *data, CustomDataMask mask, int totele
        if(!update)
                return;
 
-       CustomData_external_read(data, mask, totelem);
+       CustomData_external_read(data, id, mask, totelem);
 
-       btex= btex_create(BTEX_TYPE_MESH);
+       cdf= cdf_create(CDF_TYPE_MESH);
 
        for(i=0; i<data->totlayer; i++) {
                layer = &data->layers[i];
                typeInfo = layerType_getInfo(layer->type);
 
-               if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write)
-                       btex_layer_add(btex, layer->type, layer->name);
+               if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize)
+                       cdf_layer_add(cdf, layer->type, layer->name,
+                               typeInfo->filesize(cdf, layer->data, totelem));
        }
 
-       customdata_external_filename(filename, external);
-       if(!btex_write_open(btex, filename))
+       customdata_external_filename(filename, id, external);
+       if(!cdf_write_open(cdf, filename))
                return;
 
        for(i=0; i<data->totlayer; i++) {
@@ -2406,10 +2422,10 @@ void CustomData_external_write(CustomData *data, CustomDataMask mask, int totele
                typeInfo = layerType_getInfo(layer->type);
 
                if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
-                       blay= btex_layer_find(btex, layer->type, layer->name);
+                       blay= cdf_layer_find(cdf, layer->type, layer->name);
 
-                       if(btex_write_layer(btex, blay)) {
-                               if(typeInfo->write(btex, layer->data, totelem));
+                       if(cdf_write_layer(cdf, blay)) {
+                               if(typeInfo->write(cdf, layer->data, totelem));
                                else break;
                        }
                        else
@@ -2418,7 +2434,7 @@ void CustomData_external_write(CustomData *data, CustomDataMask mask, int totele
        }
 
        if(i != data->totlayer) {
-               btex_free(btex);
+               cdf_free(cdf);
                return;
        }
 
@@ -2435,11 +2451,11 @@ void CustomData_external_write(CustomData *data, CustomDataMask mask, int totele
                }
        }
 
-       btex_write_close(btex);
-       btex_free(btex);
+       cdf_write_close(cdf);
+       cdf_free(cdf);
 }
 
-void CustomData_external_add(CustomData *data, int type, const char *name, int totelem)
+void CustomData_external_add(CustomData *data, ID *id, int type, int totelem, const char *filename)
 {
        CustomDataExternal *external= data->external;
        CustomDataLayer *layer;
@@ -2454,23 +2470,20 @@ void CustomData_external_add(CustomData *data, int type, const char *name, int t
                return;
 
        if(!external) {
-               char hex[MAX_ID_NAME*2];
-
                external= MEM_callocN(sizeof(CustomDataExternal), "CustomDataExternal");
-               BLI_strhex(hex, sizeof(hex), name);
-               BLI_snprintf(external->filename, sizeof(external->filename), "//%s_mesh.btex", hex);
+               BLI_strncpy(external->filename, filename, sizeof(external->filename));
                data->external= external;
        }
 
        layer->flag |= CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY;
 }
 
-void CustomData_external_remove(CustomData *data, int type, int totelem)
+void CustomData_external_remove(CustomData *data, ID *id, int type, int totelem)
 {
        CustomDataExternal *external= data->external;
        CustomDataLayer *layer;
-       char filename[FILE_MAX];
-       int layer_index, i, remove_file;
+       //char filename[FILE_MAX];
+       int layer_index; // i, remove_file;
 
        layer_index = CustomData_get_active_layer_index(data, type);
        if(layer_index < 0) return;
@@ -2482,20 +2495,22 @@ void CustomData_external_remove(CustomData *data, int type, int totelem)
 
        if(layer->flag & CD_FLAG_EXTERNAL) {
                if(!(layer->flag & CD_FLAG_IN_MEMORY))
-                       CustomData_external_read(data, (1<<layer->type), totelem);
+                       CustomData_external_read(data, id, (1<<layer->type), totelem);
 
                layer->flag &= ~CD_FLAG_EXTERNAL;
 
+#if 0
                remove_file= 1;
                for(i=0; i<data->totlayer; i++)
                        if(data->layers[i].flag & CD_FLAG_EXTERNAL)
                                remove_file= 0;
 
                if(remove_file) {
-                       customdata_external_filename(filename, external);
-                       btex_remove(filename);
+                       customdata_external_filename(filename, id, external);
+                       cdf_remove(filename);
                        CustomData_external_free(data);
                }
+#endif
        }
 }
 
@@ -2511,7 +2526,8 @@ int CustomData_external_test(CustomData *data, int type)
        return (layer->flag & CD_FLAG_EXTERNAL);
 }
 
-void CustomData_external_remove_object(CustomData *data)
+#if 0
+void CustomData_external_remove_object(CustomData *data, ID *id)
 {
        CustomDataExternal *external= data->external;
        char filename[FILE_MAX];
@@ -2519,8 +2535,9 @@ void CustomData_external_remove_object(CustomData *data)
        if(!external)
                return;
 
-       customdata_external_filename(filename, external);
-       btex_remove(filename);
+       customdata_external_filename(filename, id, external);
+       cdf_remove(filename);
        CustomData_external_free(data);
 }
+#endif
 
diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c
new file mode 100644 (file)
index 0000000..b58ada8
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * $Id$
+ *
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_fileops.h"
+#include "BLI_string.h"
+
+#include "BKE_customdata_file.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+/************************* File Format Definitions ***************************/
+
+#define CDF_ENDIAN_LITTLE      0
+#define CDF_ENDIAN_BIG         1
+
+#define CDF_DATA_FLOAT 0
+
+typedef struct CDataFileHeader {
+       char ID[4];                                     /* "BCDF" */
+       char endian;                            /* little, big */
+       char version;                           /* non-compatible versions */
+       char subversion;                        /* compatible sub versions */
+       char pad;                                       /* padding */
+
+       int structbytes;                        /* size of this struct in bytes */
+       int type;                                       /* image, mesh */
+       int totlayer;                           /* number of layers in the file */
+} CDataFileHeader;
+
+typedef struct CDataFileImageHeader {
+       int structbytes;                        /* size of this struct in bytes */
+       int width;                                      /* image width */
+       int height;                                     /* image height */
+       int tile_size;                          /* tile size (required power of 2) */
+} CDataFileImageHeader;
+
+typedef struct CDataFileMeshHeader {
+       int structbytes;                        /* size of this struct in bytes */
+} CDataFileMeshHeader;
+
+struct CDataFileLayer {
+       int structbytes;                                /* size of this struct in bytes */
+       int datatype;                                   /* only float for now */
+       uint64_t datasize;                              /* size of data in layer */
+       int type;                                               /* layer type */
+       char name[CDF_LAYER_NAME_MAX];  /* layer name */
+};
+
+/**************************** Other Definitions ******************************/
+
+#define CDF_VERSION                    0
+#define CDF_SUBVERSION         0
+#define CDF_TILE_SIZE          64
+
+struct CDataFile {
+       int type;
+
+       CDataFileHeader header;
+       union {
+               CDataFileImageHeader image;
+               CDataFileMeshHeader mesh;
+       } btype;
+
+       CDataFileLayer *layer;
+       int totlayer;
+
+       FILE *readf;
+       FILE *writef;
+       int switchendian;
+       size_t dataoffset;
+};
+
+/********************************* Create/Free *******************************/
+
+static int cdf_endian(void)
+{
+       if(ENDIAN_ORDER == L_ENDIAN)
+               return CDF_ENDIAN_LITTLE;
+       else
+               return CDF_ENDIAN_BIG;
+}
+
+/*static int cdf_data_type_size(int datatype)
+{
+       if(datatype == CDF_DATA_FLOAT)
+               return sizeof(float);
+       
+       return 0;
+}*/
+
+CDataFile *cdf_create(int type)
+{
+       CDataFile *cdf= MEM_callocN(sizeof(CDataFile), "CDataFile");
+
+       cdf->type= type;
+
+       return cdf;
+}
+
+void cdf_free(CDataFile *cdf)
+{
+       cdf_read_close(cdf);
+       cdf_write_close(cdf);
+
+       if(cdf->layer)
+               MEM_freeN(cdf->layer);
+
+       MEM_freeN(cdf);
+}
+
+/********************************* Read/Write ********************************/
+
+static int cdf_read_header(CDataFile *cdf)
+{
+       CDataFileHeader *header;
+       CDataFileImageHeader *image;
+       CDataFileMeshHeader *mesh;
+       CDataFileLayer *layer;
+       FILE *f= cdf->readf;
+       size_t offset = 0;
+       int a;
+
+       header= &cdf->header;
+
+       if(!fread(header, sizeof(CDataFileHeader), 1, cdf->readf))
+               return 0;
+       
+       if(memcmp(header->ID, "BCDF", sizeof(header->ID)) != 0)
+               return 0;
+       if(header->version > CDF_VERSION)
+               return 0;
+
+       cdf->switchendian= header->endian != cdf_endian();
+       header->endian= cdf_endian();
+
+       if(cdf->switchendian) {
+               SWITCH_INT(header->type);
+               SWITCH_INT(header->totlayer);
+               SWITCH_INT(header->structbytes);
+       }
+
+       if(!ELEM(header->type, CDF_TYPE_IMAGE, CDF_TYPE_MESH))
+               return 0;
+
+       offset += header->structbytes;
+       header->structbytes= sizeof(CDataFileHeader);
+
+       if(fseek(f, offset, SEEK_SET) != 0)
+               return 0;
+       
+       if(header->type == CDF_TYPE_IMAGE) {
+               image= &cdf->btype.image;
+               if(!fread(image, sizeof(CDataFileImageHeader), 1, f))
+                       return 0;
+
+               if(cdf->switchendian) {
+                       SWITCH_INT(image->width);
+                       SWITCH_INT(image->height);
+                       SWITCH_INT(image->tile_size);
+                       SWITCH_INT(image->structbytes);
+               }
+
+               offset += image->structbytes;
+               image->structbytes= sizeof(CDataFileImageHeader);
+       }
+       else if(header->type == CDF_TYPE_MESH) {
+               mesh= &cdf->btype.mesh;
+               if(!fread(mesh, sizeof(CDataFileMeshHeader), 1, f))
+                       return 0;
+
+               if(cdf->switchendian)
+                       SWITCH_INT(mesh->structbytes);
+
+               offset += mesh->structbytes;
+               mesh->structbytes= sizeof(CDataFileMeshHeader);
+       }
+
+       if(fseek(f, offset, SEEK_SET) != 0)
+               return 0;
+
+       cdf->layer= MEM_callocN(sizeof(CDataFileLayer)*header->totlayer, "CDataFileLayer");
+       cdf->totlayer= header->totlayer;
+
+       for(a=0; a<header->totlayer; a++) {
+               layer= &cdf->layer[a];
+
+               if(!fread(layer, sizeof(CDataFileLayer), 1, f))
+                       return 0;
+
+               if(cdf->switchendian) {
+                       SWITCH_INT(layer->type);
+                       SWITCH_INT(layer->datatype);
+                       SWITCH_INT64(layer->datasize);
+                       SWITCH_INT(layer->structbytes);
+               }
+
+               if(layer->datatype != CDF_DATA_FLOAT)
+                       return 0;
+
+               offset += layer->structbytes;
+               layer->structbytes= sizeof(CDataFileLayer);
+
+               if(fseek(f, offset, SEEK_SET) != 0)
+                       return 0;
+       }
+
+       cdf->dataoffset= offset;
+
+       return 1;
+}
+
+static int cdf_write_header(CDataFile *cdf)
+{
+       CDataFileHeader *header;
+       CDataFileImageHeader *image;
+       CDataFileMeshHeader *mesh;
+       CDataFileLayer *layer;
+       FILE *f= cdf->writef;
+       int a;
+
+       header= &cdf->header;
+
+       if(!fwrite(header, sizeof(CDataFileHeader), 1, f))
+               return 0;
+       
+       if(header->type == CDF_TYPE_IMAGE) {
+               image= &cdf->btype.image;
+               if(!fwrite(image, sizeof(CDataFileImageHeader), 1, f))
+                       return 0;
+       }
+       else if(header->type == CDF_TYPE_MESH) {
+               mesh= &cdf->btype.mesh;
+               if(!fwrite(mesh, sizeof(CDataFileMeshHeader), 1, f))
+                       return 0;
+       }
+
+       for(a=0; a<header->totlayer; a++) {
+               layer= &cdf->layer[a];
+
+               if(!fwrite(layer, sizeof(CDataFileLayer), 1, f))
+                       return 0;
+       }
+
+       return 1;
+}
+
+int cdf_read_open(CDataFile *cdf, char *filename)
+{
+       FILE *f;
+
+       f= fopen(filename, "rb");
+       if(!f)
+               return 0;
+       
+       cdf->readf= f;
+
+       if(!cdf_read_header(cdf)) {
+               cdf_read_close(cdf);
+               return 0;
+       }
+
+       if(cdf->header.type != cdf->type) {
+               cdf_read_close(cdf);
+               return 0;
+       }
+
+       return 1;
+}
+
+int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay)
+{
+       size_t offset;
+       int a;
+
+       /* seek to right location in file */
+       offset= cdf->dataoffset;
+       for(a=0; a<cdf->totlayer; a++) {
+               if(&cdf->layer[a] == blay)
+                       break;
+               else
+                       offset += cdf->layer[a].datasize;
+       }
+
+       return (fseek(cdf->readf, offset, SEEK_SET) == 0);
+}
+
+int cdf_read_data(CDataFile *cdf, int size, void *data)
+{
+       float *fdata;
+       int a;
+       
+       /* read data */
+       if(!fread(data, size, 1, cdf->readf))
+               return 0;
+
+       /* switch endian if necessary */
+       if(cdf->switchendian) {
+               fdata= data;
+
+               for(a=0; a<size/sizeof(float); a++)
+                       SWITCH_INT(fdata[a])
+       }
+
+       return 1;
+}
+
+void cdf_read_close(CDataFile *cdf)
+{
+       if(cdf->readf) {
+               fclose(cdf->readf);
+               cdf->readf= NULL;
+       }
+}
+
+int cdf_write_open(CDataFile *cdf, char *filename)
+{
+       CDataFileHeader *header;
+       CDataFileImageHeader *image;
+       CDataFileMeshHeader *mesh;
+       FILE *f;
+
+       f= fopen(filename, "wb");
+       if(!f)
+               return 0;
+       
+       cdf->writef= f;
+
+       /* fill header */
+       header= &cdf->header;
+       strcpy(header->ID, "BCDF");
+       header->endian= cdf_endian();
+       header->version= CDF_VERSION;
+       header->subversion= CDF_SUBVERSION;
+
+       header->structbytes= sizeof(CDataFileHeader);
+       header->type= cdf->type;
+       header->totlayer= cdf->totlayer;
+
+       if(cdf->type == CDF_TYPE_IMAGE) {
+               /* fill image header */
+               image= &cdf->btype.image;
+               image->structbytes= sizeof(CDataFileImageHeader);
+               image->tile_size= CDF_TILE_SIZE;
+       }
+       else if(cdf->type == CDF_TYPE_MESH) {
+               /* fill mesh header */
+               mesh= &cdf->btype.mesh;
+               mesh->structbytes= sizeof(CDataFileMeshHeader);
+       }
+
+       cdf_write_header(cdf);
+
+       return 1;
+}
+
+int cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay)
+{
+       return 1;
+}
+
+int cdf_write_data(CDataFile *cdf, int size, void *data)
+{
+       /* write data */
+       if(!fwrite(data, size, 1, cdf->writef))
+               return 0;
+
+       return 1;
+}
+
+void cdf_write_close(CDataFile *cdf)
+{
+       if(cdf->writef) {
+               fclose(cdf->writef);
+               cdf->writef= NULL;
+       }
+}
+
+void cdf_remove(char *filename)
+{
+       BLI_delete(filename, 0, 0);
+}
+
+/********************************** Layers ***********************************/
+
+CDataFileLayer *cdf_layer_find(CDataFile *cdf, int type, char *name)
+{
+       CDataFileLayer *layer;
+       int a;
+
+       for(a=0; a<cdf->totlayer; a++) {
+               layer= &cdf->layer[a];
+
+               if(layer->type == type && strcmp(layer->name, name) == 0)
+                       return layer;
+       }
+       
+       return NULL;
+}
+
+CDataFileLayer *cdf_layer_add(CDataFile *cdf, int type, char *name, size_t datasize)
+{
+       CDataFileLayer *newlayer, *layer;
+
+       /* expand array */
+       newlayer= MEM_callocN(sizeof(CDataFileLayer)*(cdf->totlayer+1), "CDataFileLayer");
+       memcpy(newlayer, cdf->layer, sizeof(CDataFileLayer)*cdf->totlayer);
+       cdf->layer= newlayer;
+
+       cdf->totlayer++;
+
+       /* fill in new layer */
+       layer= &cdf->layer[cdf->totlayer-1];
+       layer->structbytes= sizeof(CDataFileLayer);
+       layer->datatype= CDF_DATA_FLOAT;
+       layer->datasize= datasize;
+       layer->type= type;
+       BLI_strncpy(layer->name, name, CDF_LAYER_NAME_MAX);
+
+       return layer;
+}
+
index 8a76d65..20ba360 100644 (file)
@@ -41,7 +41,6 @@
 #include "BLI_blenlib.h"
 #include "BLI_pbvh.h"
 
-#include "BKE_btex.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_customdata.h"
 #include "BKE_depsgraph.h"
@@ -250,7 +249,7 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object
        int levels = mmd->totlvl - lvl;
        MDisps *mdisps;
 
-       CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface);
+       CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
        mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
 
        multires_force_update(ob);
@@ -286,7 +285,7 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object
                        }
                }
                else {
-                       CustomData_external_remove(&me->fdata, CD_MDISPS, me->totface);
+                       CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
                        CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
                }
        }
@@ -538,7 +537,7 @@ static void multiresModifier_update(DerivedMesh *dm)
        ob = ccgdm->multires.ob;
        me = ccgdm->multires.ob->data;
        mmd = ccgdm->multires.mmd;
-       CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface);
+       CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
        mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
 
        if(mdisps) {
@@ -690,7 +689,7 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i
                memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize);
        }
 
-       CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface);
+       CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
        multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl);
 
        for(i = 0; i < numGrids; i++)
index bc0db6d..280b9ff 100644 (file)
@@ -1457,13 +1457,13 @@ static void write_mdisps(WriteData *wd, int count, MDisps *mdlist, int external)
        }
 }
 
-static void write_customdata(WriteData *wd, int count, CustomData *data, int partial_type, int partial_count)
+static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, int partial_type, int partial_count)
 {
        int i;
 
-       /* write external customdata */
+       /* write external customdata (not for undo) */
        if(data->external && !wd->current)
-               CustomData_external_write(data, CD_MASK_MESH, count, 0);
+               CustomData_external_write(data, id, CD_MASK_MESH, count, 0);
 
        writestruct(wd, DATA, "CustomDataLayer", data->maxlayer, data->layers);
 
@@ -1515,16 +1515,16 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
                        writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
 
                        if(mesh->pv) {
-                               write_customdata(wd, mesh->pv->totvert, &mesh->vdata, -1, 0);
-                               write_customdata(wd, mesh->pv->totedge, &mesh->edata,
+                               write_customdata(wd, &mesh->id, mesh->pv->totvert, &mesh->vdata, -1, 0);
+                               write_customdata(wd, &mesh->id, mesh->pv->totedge, &mesh->edata,
                                        CD_MEDGE, mesh->totedge);
-                               write_customdata(wd, mesh->pv->totface, &mesh->fdata,
+                               write_customdata(wd, &mesh->id, mesh->pv->totface, &mesh->fdata,
                                        CD_MFACE, mesh->totface);
                        }
                        else {
-                               write_customdata(wd, mesh->totvert, &mesh->vdata, -1, 0);
-                               write_customdata(wd, mesh->totedge, &mesh->edata, -1, 0);
-                               write_customdata(wd, mesh->totface, &mesh->fdata, -1, 0);
+                               write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0);
+                               write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0);
+                               write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0);
                        }
 
                        /* PMV data */
index c87210d..848855d 100644 (file)
@@ -143,6 +143,8 @@ void OBJECT_OT_modifier_convert(struct wmOperatorType *ot);
 void OBJECT_OT_modifier_copy(struct wmOperatorType *ot);
 void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot);
 void OBJECT_OT_multires_higher_levels_delete(struct wmOperatorType *ot);
+void OBJECT_OT_multires_save_external(struct wmOperatorType *ot);
+void OBJECT_OT_multires_pack_external(struct wmOperatorType *ot);
 void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);
 void OBJECT_OT_explode_refresh(struct wmOperatorType *ot);
 
index 76c0f29..a0fa0ef 100644 (file)
@@ -44,6 +44,7 @@
 #include "BLI_math.h"
 #include "BLI_listbase.h"
 #include "BLI_string.h"
+#include "BLI_util.h"
 
 #include "BKE_action.h"
 #include "BKE_curve.h"
@@ -794,21 +795,105 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-static int multires_subdivide_poll(bContext *C)
-{
-       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
-       ID *id= ptr.id.data;
-       return (ptr.data && id && !id->lib);
-}
-
 void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
 {
        ot->name= "Multires Subdivide";
        ot->description= "Add a new level of subdivision.";
        ot->idname= "OBJECT_OT_multires_subdivide";
 
+       ot->poll= multires_poll;
        ot->exec= multires_subdivide_exec;
-       ot->poll= multires_subdivide_poll;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/****************** multires save external operator *********************/
+
+static int multires_save_external_exec(bContext *C, wmOperator *op)
+{
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
+       Object *ob= ptr.id.data;
+       Mesh *me= (ob)? ob->data: op->customdata;
+       char path[FILE_MAX];
+
+       if(CustomData_external_test(&me->fdata, CD_MDISPS))
+               return OPERATOR_CANCELLED;
+       
+       RNA_string_get(op->ptr, "path", path);
+       if(G.save_over)
+               BLI_makestringcode(G.sce, path); /* make relative */
+
+       CustomData_external_add(&me->fdata, &me->id, CD_MDISPS, me->totface, path);
+       CustomData_external_write(&me->fdata, &me->id, CD_MASK_MESH, me->totface, 0);
+       
+       return OPERATOR_FINISHED;
+}
+
+static int multires_save_external_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
+       Object *ob= ptr.id.data;
+       Mesh *me= ob->data;
+       char path[FILE_MAX];
+
+       if(CustomData_external_test(&me->fdata, CD_MDISPS))
+               return OPERATOR_CANCELLED;
+
+       if(RNA_property_is_set(op->ptr, "path"))
+               return multires_save_external_exec(C, op);
+       
+       op->customdata= me;
+
+       BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name+2);
+       RNA_string_set(op->ptr, "path", path);
+       
+       WM_event_add_fileselect(C, op);
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+void OBJECT_OT_multires_save_external(wmOperatorType *ot)
+{
+       ot->name= "Multires Save External";
+       ot->description= "Save displacements to an external file.";
+       ot->idname= "OBJECT_OT_multires_save_external";
+
+       ot->poll= multires_poll;
+       ot->exec= multires_save_external_exec;
+       ot->invoke= multires_save_external_invoke;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       WM_operator_properties_filesel(ot, FOLDERFILE|BTXFILE, FILE_SPECIAL);
+}
+
+/****************** multires pack operator *********************/
+
+static int multires_pack_external_exec(bContext *C, wmOperator *op)
+{
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
+       Object *ob= ptr.id.data;
+       Mesh *me= ob->data;
+
+       if(!CustomData_external_test(&me->fdata, CD_MDISPS))
+               return OPERATOR_CANCELLED;
+
+       // XXX don't remove..
+       CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
+       
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_multires_pack_external(wmOperatorType *ot)
+{
+       ot->name= "Multires Pack External";
+       ot->description= "Pack displacements from an external file.";
+       ot->idname= "OBJECT_OT_multires_pack_external";
+
+       ot->poll= multires_poll;
+       ot->exec= multires_pack_external_exec;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
index 13b1155..7376b5a 100644 (file)
@@ -136,6 +136,8 @@ void ED_operatortypes_object(void)
        WM_operatortype_append(OBJECT_OT_modifier_copy);
        WM_operatortype_append(OBJECT_OT_multires_subdivide);
        WM_operatortype_append(OBJECT_OT_multires_higher_levels_delete);
+       WM_operatortype_append(OBJECT_OT_multires_save_external);
+       WM_operatortype_append(OBJECT_OT_multires_pack_external);
        WM_operatortype_append(OBJECT_OT_meshdeform_bind);
        WM_operatortype_append(OBJECT_OT_explode_refresh);
        
index a1f9a9f..93bedd0 100644 (file)
@@ -310,6 +310,8 @@ static int get_file_icon(struct direntry *file)
                return ICON_FILE_SOUND;
        else if (file->flags & FTFONTFILE) 
                return ICON_FILE_FONT;
+       else if (file->flags & BTXFILE) 
+               return ICON_FILE_BLANK;
        else
                return ICON_FILE_BLANK;
 }
index 640f365..81aa63d 100644 (file)
@@ -871,6 +871,8 @@ void filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
                                        || BLI_testextensie(file->relname, ".otf")
                                        || BLI_testextensie(file->relname, ".otc")) {
                                file->flags |= FTFONTFILE;                      
+               } else if(BLI_testextensie(file->relname, ".btx")) {
+                               file->flags |= BTXFILE;
                } else if (has_quicktime){
                        if(             BLI_testextensie(file->relname, ".int")
                                ||  BLI_testextensie(file->relname, ".inta")
index d681a58..bf58054 100644 (file)
@@ -161,6 +161,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
                        params->filter |= RNA_boolean_get(op->ptr, "filter_text") ? TEXTFILE : 0;
                if(RNA_struct_find_property(op->ptr, "filter_folder"))
                        params->filter |= RNA_boolean_get(op->ptr, "filter_folder") ? FOLDERFILE : 0;
+               if(RNA_struct_find_property(op->ptr, "filter_btx"))
+                       params->filter |= RNA_boolean_get(op->ptr, "filter_btx") ? BTXFILE : 0;
                if (params->filter != 0)
                        params->flag |= FILE_FILTER;
 
index 7a76417..83181d1 100644 (file)
@@ -667,6 +667,7 @@ enum FileSortTypeE {
 #define TEXTFILE                       512
 #define MOVIEFILE_ICON         1024 /* movie file that preview can't load */
 #define FOLDERFILE                     2048 /* represents folders for filtering */
+#define BTXFILE                                4096
 
 /* SpaceImage->dt_uv */
 #define SI_UVDT_OUTLINE        0
index ae02489..5a534a8 100644 (file)
@@ -357,15 +357,29 @@ static int rna_MultiresModifier_external_get(PointerRNA *ptr)
        return CustomData_external_test(&me->fdata, CD_MDISPS);
 }
 
-static void rna_MultiresModifier_external_set(PointerRNA *ptr, int value)
+static void rna_MultiresModifier_filename_get(PointerRNA *ptr, char *value)
 {
        Object *ob= (Object*)ptr->id.data;
-       Mesh *me= ob->data;
+       CustomDataExternal *external= ((Mesh*)ob->data)->fdata.external;
+
+       BLI_strncpy(value, (external)? external->filename: "", sizeof(external->filename));
+}
+
+static void rna_MultiresModifier_filename_set(PointerRNA *ptr, const char *value)
+{
+       Object *ob= (Object*)ptr->id.data;
+       CustomDataExternal *external= ((Mesh*)ob->data)->fdata.external;
+
+       if(external)
+               BLI_strncpy(external->filename, value, sizeof(external->filename));
+}
+
+static int rna_MultiresModifier_filename_length(PointerRNA *ptr)
+{
+       Object *ob= (Object*)ptr->id.data;
+       CustomDataExternal *external= ((Mesh*)ob->data)->fdata.external;
 
-       if(CustomData_external_test(&me->fdata, CD_MDISPS) && !value)
-               CustomData_external_remove(&me->fdata, CD_MDISPS, me->totface);
-       else if(!CustomData_external_test(&me->fdata, CD_MDISPS) && value)
-               CustomData_external_add(&me->fdata, CD_MDISPS, me->id.name+2, me->totface);
+       return strlen((external)? external->filename: "");
 }
 
 static int rna_MultiresModifier_external_editable(PointerRNA *ptr)
@@ -580,10 +594,16 @@ static void rna_def_modifier_multires(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Total Levels", "Number of subdivisions for which displacements are stored.");
 
        prop= RNA_def_property(srna, "external", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_funcs(prop, "rna_MultiresModifier_external_get", "rna_MultiresModifier_external_set");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_boolean_funcs(prop, "rna_MultiresModifier_external_get", NULL);
        RNA_def_property_editable_func(prop, "rna_MultiresModifier_external_editable");
        RNA_def_property_ui_text(prop, "External", "Store multires displacements outside the .blend file, to save memory.");
 
+       prop= RNA_def_property(srna, "filename", PROP_STRING, PROP_FILEPATH);
+       RNA_def_property_string_funcs(prop, "rna_MultiresModifier_filename_get", "rna_MultiresModifier_filename_length", "rna_MultiresModifier_filename_set");
+       RNA_def_property_ui_text(prop, "Filename", "Path to external displacements file.");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
        prop= RNA_def_property(srna, "optimal_display", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flags", eMultiresModifierFlag_ControlEdges);
        RNA_def_property_ui_text(prop, "Optimal Display", "Skip drawing/rendering of interior subdivided edges");
index 8c819c1..751785a 100644 (file)
@@ -680,6 +680,8 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type)
        RNA_def_property_flag(prop, PROP_HIDDEN);
        prop= RNA_def_boolean(ot->srna, "filter_text", (filter & TEXTFILE), "Filter text files", "");
        RNA_def_property_flag(prop, PROP_HIDDEN);
+       prop= RNA_def_boolean(ot->srna, "filter_btx", (filter & BTXFILE), "Filter btx files", "");
+       RNA_def_property_flag(prop, PROP_HIDDEN);
        prop= RNA_def_boolean(ot->srna, "filter_folder", (filter & FOLDERFILE), "Filter folders", "");
        RNA_def_property_flag(prop, PROP_HIDDEN);