Sculpt Branch:

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.
This commit is contained in:
Brecht Van Lommel 2009-12-10 14:26:06 +00:00
parent 6639ba6b86
commit acadb8c39f
19 changed files with 749 additions and 638 deletions

@ -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")

@ -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 */

@ -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

@ -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 */

@ -168,7 +168,15 @@
#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); \

@ -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;
}
}

@ -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

@ -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;
}

@ -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++)

@ -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 */

@ -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);

@ -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;

@ -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);

@ -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;
}

@ -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")

@ -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;

@ -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

@ -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;
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);
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;
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");

@ -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);