2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2002-10-12 11:37:38 +00:00
|
|
|
* 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
|
2008-01-07 19:13:47 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2011-02-27 20:40:57 +00:00
|
|
|
*/
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include <fcntl.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <stdio.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
#include <sys/stat.h>
|
2002-11-25 12:02:15 +00:00
|
|
|
|
2018-06-17 17:05:51 +02:00
|
|
|
#ifndef WIN32
|
2002-10-12 11:37:38 +00:00
|
|
|
# include <unistd.h>
|
|
|
|
|
#else
|
|
|
|
|
# include <io.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <string.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-12-27 15:07:19 +00:00
|
|
|
#include "DNA_ID.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_image_types.h"
|
2013-01-27 14:28:45 +00:00
|
|
|
#include "DNA_packedFile_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_sound_types.h"
|
|
|
|
|
#include "DNA_vfont_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_volume_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-08-03 22:12:57 +00:00
|
|
|
#include "BKE_font.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_image.h"
|
2012-08-03 22:12:57 +00:00
|
|
|
#include "BKE_main.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_packedFile.h"
|
2009-06-30 19:20:45 +00:00
|
|
|
#include "BKE_report.h"
|
2012-08-03 22:12:57 +00:00
|
|
|
#include "BKE_sound.h"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "BKE_volume.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2020-11-13 09:57:55 +11:00
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
|
2020-09-10 14:35:09 +02:00
|
|
|
#include "BLO_read_write.h"
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
int BKE_packedfile_seek(PackedFile *pf, int offset, int whence)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
int oldseek = -1, seek = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (pf) {
|
|
|
|
|
oldseek = pf->seek;
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (whence) {
|
2012-05-06 17:22:54 +00:00
|
|
|
case SEEK_CUR:
|
|
|
|
|
seek = oldseek + offset;
|
|
|
|
|
break;
|
|
|
|
|
case SEEK_END:
|
|
|
|
|
seek = pf->size + offset;
|
|
|
|
|
break;
|
|
|
|
|
case SEEK_SET:
|
|
|
|
|
seek = offset;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
oldseek = -1;
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
if (seek < 0) {
|
|
|
|
|
seek = 0;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else if (seek > pf->size) {
|
2002-10-12 11:37:38 +00:00
|
|
|
seek = pf->size;
|
|
|
|
|
}
|
|
|
|
|
pf->seek = seek;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return oldseek;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
void BKE_packedfile_rewind(PackedFile *pf)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_seek(pf, 0, SEEK_SET);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
int BKE_packedfile_read(PackedFile *pf, void *data, int size)
|
2018-06-17 17:05:51 +02:00
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
if ((pf != NULL) && (size >= 0) && (data != NULL)) {
|
|
|
|
|
if (size + pf->seek > pf->size) {
|
|
|
|
|
size = pf->size - pf->seek;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (size > 0) {
|
|
|
|
|
memcpy(data, ((char *)pf->data) + pf->seek, size);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2002-10-12 11:37:38 +00:00
|
|
|
size = 0;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
pf->seek += size;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2002-10-12 11:37:38 +00:00
|
|
|
size = -1;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return size;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
int BKE_packedfile_count_all(Main *bmain)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
Image *ima;
|
|
|
|
|
VFont *vf;
|
2009-08-09 21:16:39 +00:00
|
|
|
bSound *sound;
|
2020-03-17 14:41:48 +01:00
|
|
|
Volume *volume;
|
2009-06-30 19:20:45 +00:00
|
|
|
int count = 0;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
/* let's check if there are packed files... */
|
2019-04-22 09:39:35 +10:00
|
|
|
for (ima = bmain->images.first; ima; ima = ima->id.next) {
|
|
|
|
|
if (BKE_image_has_packedfile(ima)) {
|
2015-04-06 10:40:12 -03:00
|
|
|
count++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
for (vf = bmain->fonts.first; vf; vf = vf->id.next) {
|
|
|
|
|
if (vf->packedfile) {
|
2002-10-12 11:37:38 +00:00
|
|
|
count++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
for (sound = bmain->sounds.first; sound; sound = sound->id.next) {
|
|
|
|
|
if (sound->packedfile) {
|
2009-08-09 21:16:39 +00:00
|
|
|
count++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
|
|
|
|
|
if (volume->packedfile) {
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-30 19:20:45 +00:00
|
|
|
return count;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
void BKE_packedfile_free(PackedFile *pf)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (pf) {
|
2019-10-01 20:02:57 +02:00
|
|
|
BLI_assert(pf->data != NULL);
|
|
|
|
|
|
|
|
|
|
MEM_SAFE_FREE(pf->data);
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(pf);
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2019-07-08 00:06:52 +10:00
|
|
|
printf("%s: Trying to free a NULL pointer\n", __func__);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-08-21 10:39:02 +00:00
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
PackedFile *BKE_packedfile_duplicate(const PackedFile *pf_src)
|
2012-08-21 10:39:02 +00:00
|
|
|
{
|
2019-10-01 20:02:57 +02:00
|
|
|
BLI_assert(pf_src != NULL);
|
|
|
|
|
BLI_assert(pf_src->data != NULL);
|
|
|
|
|
|
2012-08-21 10:39:02 +00:00
|
|
|
PackedFile *pf_dst;
|
|
|
|
|
|
|
|
|
|
pf_dst = MEM_dupallocN(pf_src);
|
|
|
|
|
pf_dst->data = MEM_dupallocN(pf_src->data);
|
|
|
|
|
|
|
|
|
|
return pf_dst;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
PackedFile *BKE_packedfile_new_from_memory(void *mem, int memlen)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2019-10-01 20:02:57 +02:00
|
|
|
BLI_assert(mem != NULL);
|
|
|
|
|
|
2009-06-30 19:20:45 +00:00
|
|
|
PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");
|
2002-10-12 11:37:38 +00:00
|
|
|
pf->data = mem;
|
|
|
|
|
pf->size = memlen;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return pf;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
PackedFile *BKE_packedfile_new(ReportList *reports, const char *filename, const char *basepath)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2009-06-30 19:20:45 +00:00
|
|
|
PackedFile *pf = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
int file, filelen;
|
2011-11-26 04:07:38 +00:00
|
|
|
char name[FILE_MAX];
|
2009-06-30 19:20:45 +00:00
|
|
|
void *data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-10-15 08:39:47 +00:00
|
|
|
/* render result has no filename and can be ignored
|
|
|
|
|
* any other files with no name can be ignored too */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (filename[0] == '\0') {
|
2019-10-01 20:02:57 +02:00
|
|
|
return pf;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-01 11:09:22 +10:00
|
|
|
// XXX waitcursor(1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
/* convert relative filenames to absolute filenames */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-10-19 23:10:54 +00:00
|
|
|
BLI_strncpy(name, filename, sizeof(name));
|
2011-10-08 11:02:58 +00:00
|
|
|
BLI_path_abs(name, basepath);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
/* open the file
|
|
|
|
|
* and create a PackedFile structure */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-06 17:22:54 +00:00
|
|
|
file = BLI_open(name, O_BINARY | O_RDONLY, 0);
|
2014-04-22 16:40:17 +10:00
|
|
|
if (file == -1) {
|
2012-10-21 14:02:30 +00:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Unable to pack file, source path '%s' not found", name);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2011-10-22 15:35:49 +00:00
|
|
|
filelen = BLI_file_descriptor_size(file);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (filelen == 0) {
|
2012-07-07 22:51:57 +00:00
|
|
|
/* MEM_mallocN complains about MEM_mallocN(0, "bla");
|
|
|
|
|
* we don't care.... */
|
2002-10-12 11:37:38 +00:00
|
|
|
data = MEM_mallocN(1, "packFile");
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2002-10-12 11:37:38 +00:00
|
|
|
data = MEM_mallocN(filelen, "packFile");
|
|
|
|
|
}
|
|
|
|
|
if (read(file, data, filelen) == filelen) {
|
2019-07-07 23:57:35 +10:00
|
|
|
pf = BKE_packedfile_new_from_memory(data, filelen);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2013-09-18 18:55:12 +00:00
|
|
|
else {
|
|
|
|
|
MEM_freeN(data);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
close(file);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-01 11:09:22 +10:00
|
|
|
// XXX waitcursor(0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return pf;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2012-12-27 15:07:19 +00:00
|
|
|
/* no libraries for now */
|
2019-07-07 23:57:35 +10:00
|
|
|
void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
Image *ima;
|
2012-08-03 22:12:57 +00:00
|
|
|
VFont *vfont;
|
2009-08-09 21:16:39 +00:00
|
|
|
bSound *sound;
|
2020-03-17 14:41:48 +01:00
|
|
|
Volume *volume;
|
2013-01-27 14:28:45 +00:00
|
|
|
int tot = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
for (ima = bmain->images.first; ima; ima = ima->id.next) {
|
2017-11-06 17:17:10 +01:00
|
|
|
if (BKE_image_has_packedfile(ima) == false && !ID_IS_LINKED(ima)) {
|
2012-05-06 17:22:54 +00:00
|
|
|
if (ima->source == IMA_SRC_FILE) {
|
2015-04-06 10:40:12 -03:00
|
|
|
BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
|
2013-01-27 14:28:45 +00:00
|
|
|
tot++;
|
2010-10-10 21:39:24 +00:00
|
|
|
}
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 16:06:08 +01:00
|
|
|
else if (BKE_image_has_multiple_ibufs(ima) && verbose) {
|
2012-10-13 15:44:50 +00:00
|
|
|
BKE_reportf(reports,
|
|
|
|
|
RPT_WARNING,
|
Add support for tiled images and the UDIM naming scheme
This patch contains the work that I did during my week at the Code Quest - adding support for tiled images to Blender.
With this patch, images now contain a list of tiles. By default, this just contains one tile, but if the source type is set to Tiled, the user can add additional tiles. When acquiring an ImBuf, the tile to be loaded is specified in the ImageUser.
Therefore, code that is not yet aware of tiles will just access the default tile as usual.
The filenames of the additional tiles are derived from the original filename according to the UDIM naming scheme - the filename contains an index that is calculated as (1001 + 10*<y coordinate of the tile> + <x coordinate of the tile>), where the x coordinate never goes above 9.
Internally, the various tiles are stored in a cache just like sequences. When acquired for the first time, the code will try to load the corresponding file from disk. Alternatively, a new operator can be used to initialize the tile similar to the New Image operator.
The following features are supported so far:
- Automatic detection and loading of all tiles when opening the first tile (1001)
- Saving all tiles
- Adding and removing tiles
- Filling tiles with generated images
- Drawing all tiles in the Image Editor
- Viewing a tiled grid even if no image is selected
- Rendering tiled images in Eevee
- Rendering tiled images in Cycles (in SVM mode)
- Automatically skipping loading of unused tiles in Cycles
- 2D texture painting (also across tiles)
- 3D texture painting (also across tiles, only limitation: individual faces can not cross tile borders)
- Assigning custom labels to individual tiles (drawn in the Image Editor instead of the ID)
- Different resolutions between tiles
There still are some missing features that will be added later (see T72390):
- Workbench engine support
- Packing/Unpacking support
- Baking support
- Cycles OSL support
- many other Blender features that rely on images
Thanks to Brecht for the review and to all who tested the intermediate versions!
Differential Revision: https://developer.blender.org/D3509
2019-12-12 16:06:08 +01:00
|
|
|
"Image '%s' skipped, movies, image sequences and packed files not supported",
|
2012-10-13 15:44:50 +00:00
|
|
|
ima->id.name + 2);
|
2010-10-10 21:39:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
for (vfont = bmain->fonts.first; vfont; vfont = vfont->id.next) {
|
2017-11-06 17:17:10 +01:00
|
|
|
if (vfont->packedfile == NULL && !ID_IS_LINKED(vfont) &&
|
|
|
|
|
BKE_vfont_is_builtin(vfont) == false) {
|
2020-06-23 09:54:14 +10:00
|
|
|
vfont->packedfile = BKE_packedfile_new(
|
|
|
|
|
reports, vfont->filepath, BKE_main_blendfile_path(bmain));
|
2013-01-27 14:28:45 +00:00
|
|
|
tot++;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
for (sound = bmain->sounds.first; sound; sound = sound->id.next) {
|
2017-11-06 17:17:10 +01:00
|
|
|
if (sound->packedfile == NULL && !ID_IS_LINKED(sound)) {
|
2020-06-23 09:54:14 +10:00
|
|
|
sound->packedfile = BKE_packedfile_new(
|
|
|
|
|
reports, sound->filepath, BKE_main_blendfile_path(bmain));
|
2013-01-27 14:28:45 +00:00
|
|
|
tot++;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
|
|
|
|
|
if (volume->packedfile == NULL && !ID_IS_LINKED(volume)) {
|
|
|
|
|
volume->packedfile = BKE_packedfile_new(
|
|
|
|
|
reports, volume->filepath, BKE_main_blendfile_path(bmain));
|
|
|
|
|
tot++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (tot > 0) {
|
2019-10-02 12:52:58 +02:00
|
|
|
BKE_reportf(reports, RPT_INFO, "Packed %d file(s)", tot);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else if (verbose) {
|
2015-05-01 16:03:45 +02:00
|
|
|
BKE_report(reports, RPT_INFO, "No new files have been packed");
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
int BKE_packedfile_write_to_file(ReportList *reports,
|
|
|
|
|
const char *ref_file_name,
|
|
|
|
|
const char *filename,
|
|
|
|
|
PackedFile *pf,
|
|
|
|
|
const bool guimode)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2014-04-01 11:34:00 +11:00
|
|
|
int file, number;
|
2002-10-12 11:37:38 +00:00
|
|
|
int ret_value = RET_OK;
|
2014-04-01 11:34:00 +11:00
|
|
|
bool remove_tmp = false;
|
2011-11-26 04:07:38 +00:00
|
|
|
char name[FILE_MAX];
|
|
|
|
|
char tempname[FILE_MAX];
|
2012-05-06 17:22:54 +00:00
|
|
|
/* void *data; */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-04-24 10:08:07 +00:00
|
|
|
if (guimode) {
|
2019-05-01 11:09:22 +10:00
|
|
|
} // XXX waitcursor(1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-10-19 23:10:54 +00:00
|
|
|
BLI_strncpy(name, filename, sizeof(name));
|
2018-05-31 11:07:14 +02:00
|
|
|
BLI_path_abs(name, ref_file_name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (BLI_exists(name)) {
|
|
|
|
|
for (number = 1; number <= 999; number++) {
|
2011-10-19 23:10:54 +00:00
|
|
|
BLI_snprintf(tempname, sizeof(tempname), "%s.%03d_", name, number);
|
2012-05-06 17:22:54 +00:00
|
|
|
if (!BLI_exists(tempname)) {
|
2011-10-22 15:35:49 +00:00
|
|
|
if (BLI_copy(name, tempname) == RET_OK) {
|
2014-04-01 11:34:00 +11:00
|
|
|
remove_tmp = true;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
/* make sure the path to the file exists... */
|
Giant commit!
A full detailed description of this will be done later... is several days
of work. Here's a summary:
Render:
- Full cleanup of render code, removing *all* globals and bad level calls
all over blender. Render module is now not called abusive anymore
- API-fied calls to rendering
- Full recode of internal render pipeline. Is now rendering tiles by
default, prepared for much smarter 'bucket' render later.
- Each thread now can render a full part
- Renders were tested with 4 threads, goes fine, apart from some lookup
tables in softshadow and AO still
- Rendering is prepared to do multiple layers and passes
- No single 32 bits trick in render code anymore, all 100% floats now.
Writing images/movies
- moved writing images to blender kernel (bye bye 'schrijfplaatje'!)
- made a new Movie handle system, also in kernel. This will enable much
easier use of movies in Blender
PreviewRender:
- Using new render API, previewrender (in buttons) now uses regular render
code to generate images.
- new datafile 'preview.blend.c' has the preview scenes in it
- previews get rendered in exact displayed size (1 pixel = 1 pixel)
3D Preview render
- new; press Pkey in 3d window, for a panel that continuously renders
(pkey is for games, i know... but we dont do that in orange now!)
- this render works nearly identical to buttons-preview render, so it stops
rendering on any event (mouse, keyboard, etc)
- on moving/scaling the panel, the render code doesn't recreate all geometry
- same for shifting/panning view
- all other operations (now) regenerate the full render database still.
- this is WIP... but big fun, especially for simple scenes!
Compositor
- Using same node system as now in use for shaders, you can composit images
- works pretty straightforward... needs much more options/tools and integration
with rendering still
- is not threaded yet, nor is so smart to only recalculate changes... will be
done soon!
- the "Render Result" node will get all layers/passes as output sockets
- The "Output" node renders to a builtin image, which you can view in the Image
window. (yes, output nodes to render-result, and to files, is on the list!)
The Bad News
- "Unified Render" is removed. It might come back in some stage, but this
system should be built from scratch. I can't really understand this code...
I expect it is not much needed, especially with advanced layer/passes
control
- Panorama render, Field render, Motion blur, is not coded yet... (I had to
recode every single feature in render, so...!)
- Lens Flare is also not back... needs total revision, might become composit
effect though (using zbuffer for visibility)
- Part render is gone! (well, thats obvious, its default now).
- The render window is only restored with limited functionality... I am going
to check first the option to render to a Image window, so Blender can become
a true single-window application. :)
For example, the 'Spare render buffer' (jkey) doesnt work.
- Render with border, now default creates a smaller image
- No zbuffers are written yet... on the todo!
- Scons files and MSVC will need work to get compiling again
OK... thats what I can quickly recall. Now go compiling!
2006-01-23 22:05:47 +00:00
|
|
|
BLI_make_existing_file(name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-20 02:17:37 +00:00
|
|
|
file = BLI_open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
|
2014-04-22 16:40:17 +10:00
|
|
|
if (file == -1) {
|
2013-08-04 17:30:47 +00:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Error creating file '%s'", name);
|
|
|
|
|
ret_value = RET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2002-10-12 11:37:38 +00:00
|
|
|
if (write(file, pf->data, pf->size) != pf->size) {
|
2012-10-21 14:02:30 +00:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Error writing file '%s'", name);
|
2002-10-12 11:37:38 +00:00
|
|
|
ret_value = RET_ERROR;
|
|
|
|
|
}
|
2013-08-04 17:30:47 +00:00
|
|
|
else {
|
2013-01-27 14:28:45 +00:00
|
|
|
BKE_reportf(reports, RPT_INFO, "Saved packed file to: %s", name);
|
2013-08-04 17:30:47 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
close(file);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (remove_tmp) {
|
|
|
|
|
if (ret_value == RET_ERROR) {
|
2008-04-12 15:03:47 +00:00
|
|
|
if (BLI_rename(tempname, name) != 0) {
|
2012-10-21 14:02:30 +00:00
|
|
|
BKE_reportf(reports,
|
|
|
|
|
RPT_ERROR,
|
|
|
|
|
"Error restoring temp file (check files '%s' '%s')",
|
|
|
|
|
tempname,
|
|
|
|
|
name);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2013-03-05 03:53:22 +00:00
|
|
|
if (BLI_delete(tempname, false, false) != 0) {
|
2009-06-30 19:20:45 +00:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (guimode) {
|
2019-05-01 11:09:22 +10:00
|
|
|
} // XXX waitcursor(0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return ret_value;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-03-23 11:51:19 +01:00
|
|
|
|
|
|
|
|
/**
|
2012-03-03 20:19:11 +00:00
|
|
|
* This function compares a packed file to a 'real' file.
|
|
|
|
|
* It returns an integer indicating if:
|
|
|
|
|
*
|
2018-03-23 11:51:19 +01:00
|
|
|
* - PF_EQUAL: the packed file and original file are identical
|
|
|
|
|
* - PF_DIFFERENT: the packed file and original file differ
|
2018-09-24 17:27:41 +02:00
|
|
|
* - PF_NOFILE: the original file doesn't exist
|
2012-03-03 20:19:11 +00:00
|
|
|
*/
|
2019-07-08 00:40:56 +10:00
|
|
|
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
|
|
|
|
|
const char *filename,
|
|
|
|
|
PackedFile *pf)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2014-05-28 22:50:40 +06:00
|
|
|
BLI_stat_t st;
|
2019-07-08 00:40:56 +10:00
|
|
|
enum ePF_FileCompare ret_val;
|
2002-10-12 11:37:38 +00:00
|
|
|
char buf[4096];
|
2011-11-26 04:07:38 +00:00
|
|
|
char name[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-10-19 23:10:54 +00:00
|
|
|
BLI_strncpy(name, filename, sizeof(name));
|
2018-05-31 11:07:14 +02:00
|
|
|
BLI_path_abs(name, ref_file_name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-18 07:26:10 +11:00
|
|
|
if (BLI_stat(name, &st) == -1) {
|
2019-07-08 00:40:56 +10:00
|
|
|
ret_val = PF_CMP_NOFILE;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else if (st.st_size != pf->size) {
|
2019-07-08 00:40:56 +10:00
|
|
|
ret_val = PF_CMP_DIFFERS;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-07-07 22:51:57 +00:00
|
|
|
/* we'll have to compare the two... */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-08 00:40:56 +10:00
|
|
|
const int file = BLI_open(name, O_BINARY | O_RDONLY, 0);
|
2014-04-22 16:40:17 +10:00
|
|
|
if (file == -1) {
|
2019-07-08 00:40:56 +10:00
|
|
|
ret_val = PF_CMP_NOFILE;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2019-07-08 00:40:56 +10:00
|
|
|
ret_val = PF_CMP_EQUAL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-08 00:40:56 +10:00
|
|
|
for (int i = 0; i < pf->size; i += sizeof(buf)) {
|
|
|
|
|
int len = pf->size - i;
|
2002-10-12 11:37:38 +00:00
|
|
|
if (len > sizeof(buf)) {
|
|
|
|
|
len = sizeof(buf);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (read(file, buf, len) != len) {
|
2012-07-07 22:51:57 +00:00
|
|
|
/* read error ... */
|
2019-07-08 00:40:56 +10:00
|
|
|
ret_val = PF_CMP_DIFFERS;
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
2020-08-07 17:16:46 +02:00
|
|
|
if (memcmp(buf, ((char *)pf->data) + i, len) != 0) {
|
2020-08-07 12:30:43 +02:00
|
|
|
ret_val = PF_CMP_DIFFERS;
|
|
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-08-01 06:27:40 +00:00
|
|
|
close(file);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return ret_val;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-28 21:30:20 +10:00
|
|
|
/**
|
2019-07-07 23:57:35 +10:00
|
|
|
* #BKE_packedfile_unpack_to_file() looks at the existing files (abs_name, local_name)
|
|
|
|
|
* and a packed file.
|
2012-03-03 20:19:11 +00:00
|
|
|
*
|
|
|
|
|
* It returns a char *to the existing file name / new file name or NULL when
|
2012-04-25 06:06:40 +00:00
|
|
|
* there was an error or when the user decides to cancel the operation.
|
2015-07-28 21:30:20 +10:00
|
|
|
*
|
2019-04-27 12:07:07 +10:00
|
|
|
* \warning 'abs_name' may be relative still! (use a "//" prefix)
|
|
|
|
|
* be sure to run #BLI_path_abs on it first.
|
2012-03-03 20:19:11 +00:00
|
|
|
*/
|
2019-07-07 23:57:35 +10:00
|
|
|
char *BKE_packedfile_unpack_to_file(ReportList *reports,
|
|
|
|
|
const char *ref_file_name,
|
|
|
|
|
const char *abs_name,
|
|
|
|
|
const char *local_name,
|
|
|
|
|
PackedFile *pf,
|
2019-07-08 00:06:52 +10:00
|
|
|
enum ePF_FileStatus how)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2011-10-19 23:10:54 +00:00
|
|
|
char *newname = NULL;
|
|
|
|
|
const char *temp = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (pf != NULL) {
|
|
|
|
|
switch (how) {
|
|
|
|
|
case PF_KEEP:
|
|
|
|
|
break;
|
2006-12-20 17:57:56 +00:00
|
|
|
case PF_REMOVE:
|
2012-05-06 17:22:54 +00:00
|
|
|
temp = abs_name;
|
2006-12-20 17:57:56 +00:00
|
|
|
break;
|
2002-10-12 11:37:38 +00:00
|
|
|
case PF_USE_LOCAL: {
|
2015-07-28 21:30:20 +10:00
|
|
|
char temp_abs[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-28 21:30:20 +10:00
|
|
|
BLI_strncpy(temp_abs, local_name, sizeof(temp_abs));
|
2018-05-31 11:07:14 +02:00
|
|
|
BLI_path_abs(temp_abs, ref_file_name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
/* if file exists use it */
|
2015-07-28 21:30:20 +10:00
|
|
|
if (BLI_exists(temp_abs)) {
|
2002-10-12 11:37:38 +00:00
|
|
|
temp = local_name;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-07-21 08:16:37 +00:00
|
|
|
/* else create it */
|
2017-05-20 14:01:03 +10:00
|
|
|
ATTR_FALLTHROUGH;
|
2015-07-28 21:30:20 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
case PF_WRITE_LOCAL:
|
2019-07-07 23:57:35 +10:00
|
|
|
if (BKE_packedfile_write_to_file(reports, ref_file_name, local_name, pf, 1) == RET_OK) {
|
2002-10-12 11:37:38 +00:00
|
|
|
temp = local_name;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case PF_USE_ORIGINAL: {
|
2015-07-28 21:30:20 +10:00
|
|
|
char temp_abs[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-28 21:30:20 +10:00
|
|
|
BLI_strncpy(temp_abs, abs_name, sizeof(temp_abs));
|
2018-05-31 11:07:14 +02:00
|
|
|
BLI_path_abs(temp_abs, ref_file_name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
/* if file exists use it */
|
2015-07-28 21:30:20 +10:00
|
|
|
if (BLI_exists(temp_abs)) {
|
2013-01-27 14:28:45 +00:00
|
|
|
BKE_reportf(reports, RPT_INFO, "Use existing file (instead of packed): %s", abs_name);
|
2002-10-12 11:37:38 +00:00
|
|
|
temp = abs_name;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-07-21 08:16:37 +00:00
|
|
|
/* else create it */
|
2017-05-20 14:01:03 +10:00
|
|
|
ATTR_FALLTHROUGH;
|
2015-07-28 21:30:20 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
case PF_WRITE_ORIGINAL:
|
2019-07-07 23:57:35 +10:00
|
|
|
if (BKE_packedfile_write_to_file(reports, ref_file_name, abs_name, pf, 1) == RET_OK) {
|
2002-10-12 11:37:38 +00:00
|
|
|
temp = abs_name;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2019-07-08 00:06:52 +10:00
|
|
|
printf("%s: unknown return_value %u\n", __func__, how);
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (temp) {
|
2012-05-06 17:22:54 +00:00
|
|
|
newname = BLI_strdup(temp);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-10-19 23:10:54 +00:00
|
|
|
return newname;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2015-03-07 13:58:21 +01:00
|
|
|
static void unpack_generate_paths(const char *name,
|
2015-05-08 07:25:39 +10:00
|
|
|
ID *id,
|
|
|
|
|
char *r_abspath,
|
|
|
|
|
char *r_relpath,
|
|
|
|
|
size_t abspathlen,
|
|
|
|
|
size_t relpathlen)
|
2015-03-07 13:58:21 +01:00
|
|
|
{
|
2020-11-13 09:57:55 +11:00
|
|
|
const short id_type = GS(id->name);
|
2015-03-07 13:58:21 +01:00
|
|
|
char tempname[FILE_MAX];
|
|
|
|
|
char tempdir[FILE_MAXDIR];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-07 13:58:21 +01:00
|
|
|
BLI_split_dirfile(name, tempdir, tempname, sizeof(tempdir), sizeof(tempname));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-07 13:58:21 +01:00
|
|
|
if (tempname[0] == '\0') {
|
2020-11-13 09:57:55 +11:00
|
|
|
/* Note: we generally do not have any real way to re-create extension out of data. */
|
2015-03-07 13:58:21 +01:00
|
|
|
BLI_strncpy(tempname, id->name + 2, sizeof(tempname));
|
|
|
|
|
printf("%s\n", tempname);
|
2020-11-13 09:57:55 +11:00
|
|
|
|
|
|
|
|
/* For images we can add the file extension based on the file magic. */
|
|
|
|
|
if (id_type == ID_IM) {
|
|
|
|
|
ImagePackedFile *imapf = ((Image *)id)->packedfiles.last;
|
|
|
|
|
if (imapf != NULL && imapf->packedfile != NULL) {
|
|
|
|
|
const PackedFile *pf = imapf->packedfile;
|
2020-11-13 20:25:21 +11:00
|
|
|
enum eImbFileType ftype = IMB_ispic_type_from_memory((const uchar *)pf->data, pf->size);
|
|
|
|
|
if (ftype != IMB_FTYPE_NONE) {
|
2020-11-13 09:57:55 +11:00
|
|
|
const int imtype = BKE_image_ftype_to_imtype(ftype, NULL);
|
|
|
|
|
BKE_image_path_ensure_ext_from_imtype(tempname, imtype);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-07 13:58:21 +01:00
|
|
|
BLI_filename_make_safe(tempname);
|
|
|
|
|
printf("%s\n", tempname);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-07 13:58:21 +01:00
|
|
|
if (tempdir[0] == '\0') {
|
|
|
|
|
/* Fallback to relative dir. */
|
|
|
|
|
BLI_strncpy(tempdir, "//", sizeof(tempdir));
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-13 09:57:55 +11:00
|
|
|
switch (id_type) {
|
2015-03-07 13:58:21 +01:00
|
|
|
case ID_VF:
|
2015-05-08 07:25:39 +10:00
|
|
|
BLI_snprintf(r_relpath, relpathlen, "//fonts/%s", tempname);
|
2015-03-07 13:58:21 +01:00
|
|
|
break;
|
|
|
|
|
case ID_SO:
|
2015-05-08 07:25:39 +10:00
|
|
|
BLI_snprintf(r_relpath, relpathlen, "//sounds/%s", tempname);
|
2015-03-07 13:58:21 +01:00
|
|
|
break;
|
|
|
|
|
case ID_IM:
|
2015-05-08 07:25:39 +10:00
|
|
|
BLI_snprintf(r_relpath, relpathlen, "//textures/%s", tempname);
|
2015-03-07 13:58:21 +01:00
|
|
|
break;
|
2020-03-17 14:41:48 +01:00
|
|
|
case ID_VO:
|
|
|
|
|
BLI_snprintf(r_relpath, relpathlen, "//volumes/%s", tempname);
|
|
|
|
|
break;
|
2017-08-28 11:19:58 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
2015-03-07 13:58:21 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-07 13:58:21 +01:00
|
|
|
{
|
2015-05-08 07:25:39 +10:00
|
|
|
size_t len = BLI_strncpy_rlen(r_abspath, tempdir, abspathlen);
|
|
|
|
|
BLI_strncpy(r_abspath + len, tempname, abspathlen - len);
|
2015-03-07 13:58:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-07-08 00:06:52 +10:00
|
|
|
int BKE_packedfile_unpack_vfont(Main *bmain,
|
|
|
|
|
ReportList *reports,
|
|
|
|
|
VFont *vfont,
|
|
|
|
|
enum ePF_FileStatus how)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2015-03-07 13:58:21 +01:00
|
|
|
char localname[FILE_MAX], absname[FILE_MAX];
|
2009-06-30 19:20:45 +00:00
|
|
|
char *newname;
|
2002-10-12 11:37:38 +00:00
|
|
|
int ret_value = RET_ERROR;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (vfont != NULL) {
|
2015-03-07 13:58:21 +01:00
|
|
|
unpack_generate_paths(
|
2020-06-23 09:54:14 +10:00
|
|
|
vfont->filepath, (ID *)vfont, absname, localname, sizeof(absname), sizeof(localname));
|
2019-07-07 23:57:35 +10:00
|
|
|
newname = BKE_packedfile_unpack_to_file(
|
2018-06-05 15:10:33 +02:00
|
|
|
reports, BKE_main_blendfile_path(bmain), absname, localname, vfont->packedfile, how);
|
2002-10-12 11:37:38 +00:00
|
|
|
if (newname != NULL) {
|
|
|
|
|
ret_value = RET_OK;
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_free(vfont->packedfile);
|
2011-02-13 10:52:18 +00:00
|
|
|
vfont->packedfile = NULL;
|
2020-06-23 09:54:14 +10:00
|
|
|
BLI_strncpy(vfont->filepath, newname, sizeof(vfont->filepath));
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(newname);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return ret_value;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-08 00:06:52 +10:00
|
|
|
int BKE_packedfile_unpack_sound(Main *bmain,
|
|
|
|
|
ReportList *reports,
|
|
|
|
|
bSound *sound,
|
|
|
|
|
enum ePF_FileStatus how)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2015-03-07 13:58:21 +01:00
|
|
|
char localname[FILE_MAX], absname[FILE_MAX];
|
2009-06-30 19:20:45 +00:00
|
|
|
char *newname;
|
2002-10-12 11:37:38 +00:00
|
|
|
int ret_value = RET_ERROR;
|
2009-08-09 21:16:39 +00:00
|
|
|
|
|
|
|
|
if (sound != NULL) {
|
2015-03-07 13:58:21 +01:00
|
|
|
unpack_generate_paths(
|
2020-06-23 09:54:14 +10:00
|
|
|
sound->filepath, (ID *)sound, absname, localname, sizeof(absname), sizeof(localname));
|
2019-07-07 23:57:35 +10:00
|
|
|
newname = BKE_packedfile_unpack_to_file(
|
2018-06-05 15:10:33 +02:00
|
|
|
reports, BKE_main_blendfile_path(bmain), absname, localname, sound->packedfile, how);
|
2002-10-12 11:37:38 +00:00
|
|
|
if (newname != NULL) {
|
2020-06-23 09:54:14 +10:00
|
|
|
BLI_strncpy(sound->filepath, newname, sizeof(sound->filepath));
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(newname);
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_free(sound->packedfile);
|
2011-02-13 10:52:18 +00:00
|
|
|
sound->packedfile = NULL;
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_sound_load(bmain, sound);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
ret_value = RET_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return ret_value;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-08 00:06:52 +10:00
|
|
|
int BKE_packedfile_unpack_image(Main *bmain,
|
|
|
|
|
ReportList *reports,
|
|
|
|
|
Image *ima,
|
|
|
|
|
enum ePF_FileStatus how)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
int ret_value = RET_ERROR;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-21 03:07:40 +11:00
|
|
|
if (ima != NULL) {
|
2015-04-06 10:40:12 -03:00
|
|
|
while (ima->packedfiles.last) {
|
|
|
|
|
char localname[FILE_MAX], absname[FILE_MAX];
|
|
|
|
|
char *newname;
|
|
|
|
|
ImagePackedFile *imapf = ima->packedfiles.last;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
unpack_generate_paths(
|
|
|
|
|
imapf->filepath, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname));
|
2019-07-07 23:57:35 +10:00
|
|
|
newname = BKE_packedfile_unpack_to_file(
|
2018-06-05 15:10:33 +02:00
|
|
|
reports, BKE_main_blendfile_path(bmain), absname, localname, imapf->packedfile, how);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (newname != NULL) {
|
|
|
|
|
ImageView *iv;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
ret_value = ret_value == RET_ERROR ? RET_ERROR : RET_OK;
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_free(imapf->packedfile);
|
2015-04-06 10:40:12 -03:00
|
|
|
imapf->packedfile = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* update the new corresponding view filepath */
|
|
|
|
|
iv = BLI_findstring(&ima->views, imapf->filepath, offsetof(ImageView, filepath));
|
|
|
|
|
if (iv) {
|
|
|
|
|
BLI_strncpy(iv->filepath, newname, sizeof(imapf->filepath));
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* keep the new name in the image for non-pack specific reasons */
|
2015-10-21 03:07:40 +11:00
|
|
|
if (how != PF_REMOVE) {
|
2020-06-23 09:54:14 +10:00
|
|
|
BLI_strncpy(ima->filepath, newname, sizeof(imapf->filepath));
|
2015-10-21 03:07:40 +11:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
MEM_freeN(newname);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ret_value = RET_ERROR;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_remlink(&ima->packedfiles, imapf);
|
|
|
|
|
MEM_freeN(imapf);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (ret_value == RET_OK) {
|
2018-06-11 15:40:37 +02:00
|
|
|
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return ret_value;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
int BKE_packedfile_unpack_volume(Main *bmain,
|
|
|
|
|
ReportList *reports,
|
|
|
|
|
Volume *volume,
|
|
|
|
|
enum ePF_FileStatus how)
|
|
|
|
|
{
|
|
|
|
|
char localname[FILE_MAX], absname[FILE_MAX];
|
|
|
|
|
char *newfilepath;
|
|
|
|
|
int ret_value = RET_ERROR;
|
|
|
|
|
|
|
|
|
|
if (volume != NULL) {
|
|
|
|
|
unpack_generate_paths(
|
|
|
|
|
volume->filepath, (ID *)volume, absname, localname, sizeof(absname), sizeof(localname));
|
|
|
|
|
newfilepath = BKE_packedfile_unpack_to_file(
|
|
|
|
|
reports, BKE_main_blendfile_path(bmain), absname, localname, volume->packedfile, how);
|
|
|
|
|
if (newfilepath != NULL) {
|
|
|
|
|
BLI_strncpy(volume->filepath, newfilepath, sizeof(volume->filepath));
|
|
|
|
|
MEM_freeN(newfilepath);
|
|
|
|
|
|
|
|
|
|
BKE_packedfile_free(volume->packedfile);
|
|
|
|
|
volume->packedfile = NULL;
|
|
|
|
|
|
|
|
|
|
BKE_volume_unload(volume);
|
|
|
|
|
|
|
|
|
|
ret_value = RET_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return ret_value;
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
int BKE_packedfile_unpack_all_libraries(Main *bmain, ReportList *reports)
|
2012-12-27 15:07:19 +00:00
|
|
|
{
|
|
|
|
|
Library *lib;
|
|
|
|
|
char *newname;
|
|
|
|
|
int ret_value = RET_ERROR;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
for (lib = bmain->libraries.first; lib; lib = lib->id.next) {
|
2020-06-23 09:54:14 +10:00
|
|
|
if (lib->packedfile && lib->filepath[0]) {
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
newname = BKE_packedfile_unpack_to_file(reports,
|
|
|
|
|
BKE_main_blendfile_path(bmain),
|
2020-06-23 09:54:07 +10:00
|
|
|
lib->filepath_abs,
|
|
|
|
|
lib->filepath_abs,
|
2019-07-07 23:57:35 +10:00
|
|
|
lib->packedfile,
|
|
|
|
|
PF_WRITE_ORIGINAL);
|
2012-12-27 15:07:19 +00:00
|
|
|
if (newname != NULL) {
|
|
|
|
|
ret_value = RET_OK;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-01-12 11:59:22 +00:00
|
|
|
printf("Unpacked .blend library: %s\n", newname);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_free(lib->packedfile);
|
2012-12-27 15:07:19 +00:00
|
|
|
lib->packedfile = NULL;
|
|
|
|
|
|
|
|
|
|
MEM_freeN(newname);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2020-08-08 11:02:11 +10:00
|
|
|
return ret_value;
|
2012-12-27 15:07:19 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
void BKE_packedfile_pack_all_libraries(Main *bmain, ReportList *reports)
|
2012-12-27 15:07:19 +00:00
|
|
|
{
|
|
|
|
|
Library *lib;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-01-12 11:59:22 +00:00
|
|
|
/* test for relativenss */
|
2019-04-22 09:39:35 +10:00
|
|
|
for (lib = bmain->libraries.first; lib; lib = lib->id.next) {
|
2020-06-23 09:54:14 +10:00
|
|
|
if (!BLI_path_is_rel(lib->filepath)) {
|
2013-01-12 11:59:22 +00:00
|
|
|
break;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-01-12 11:59:22 +00:00
|
|
|
if (lib) {
|
2020-06-23 09:54:14 +10:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Cannot pack absolute file: '%s'", lib->filepath);
|
2013-01-12 11:59:22 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
for (lib = bmain->libraries.first; lib; lib = lib->id.next) {
|
|
|
|
|
if (lib->packedfile == NULL) {
|
2020-06-23 09:54:14 +10:00
|
|
|
lib->packedfile = BKE_packedfile_new(reports, lib->filepath, BKE_main_blendfile_path(bmain));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2012-12-27 15:07:19 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-08 00:06:52 +10:00
|
|
|
void BKE_packedfile_unpack_all(Main *bmain, ReportList *reports, enum ePF_FileStatus how)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
|
|
|
|
Image *ima;
|
|
|
|
|
VFont *vf;
|
2009-08-09 21:16:39 +00:00
|
|
|
bSound *sound;
|
2020-03-17 14:41:48 +01:00
|
|
|
Volume *volume;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
for (ima = bmain->images.first; ima; ima = ima->id.next) {
|
|
|
|
|
if (BKE_image_has_packedfile(ima)) {
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_unpack_image(bmain, reports, ima, how);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2009-06-30 19:20:45 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
for (vf = bmain->fonts.first; vf; vf = vf->id.next) {
|
|
|
|
|
if (vf->packedfile) {
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_unpack_vfont(bmain, reports, vf, how);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2009-06-30 19:20:45 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
for (sound = bmain->sounds.first; sound; sound = sound->id.next) {
|
|
|
|
|
if (sound->packedfile) {
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_unpack_sound(bmain, reports, sound, how);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
|
|
|
|
|
if (volume->packedfile) {
|
|
|
|
|
BKE_packedfile_unpack_volume(bmain, reports, volume, how);
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2009-06-30 19:20:45 +00:00
|
|
|
|
2013-01-27 14:28:45 +00:00
|
|
|
/* ID should be not NULL, return 1 if there's a packed file */
|
2019-07-07 23:57:35 +10:00
|
|
|
bool BKE_packedfile_id_check(ID *id)
|
2013-01-27 14:28:45 +00:00
|
|
|
{
|
2014-04-23 19:22:03 +10:00
|
|
|
switch (GS(id->name)) {
|
|
|
|
|
case ID_IM: {
|
|
|
|
|
Image *ima = (Image *)id;
|
2015-04-06 10:40:12 -03:00
|
|
|
return BKE_image_has_packedfile(ima);
|
2014-04-23 19:22:03 +10:00
|
|
|
}
|
|
|
|
|
case ID_VF: {
|
|
|
|
|
VFont *vf = (VFont *)id;
|
|
|
|
|
return vf->packedfile != NULL;
|
|
|
|
|
}
|
|
|
|
|
case ID_SO: {
|
|
|
|
|
bSound *snd = (bSound *)id;
|
|
|
|
|
return snd->packedfile != NULL;
|
|
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
case ID_VO: {
|
|
|
|
|
Volume *volume = (Volume *)id;
|
|
|
|
|
return volume->packedfile != NULL;
|
|
|
|
|
}
|
2014-04-23 19:22:03 +10:00
|
|
|
case ID_LI: {
|
|
|
|
|
Library *li = (Library *)id;
|
|
|
|
|
return li->packedfile != NULL;
|
|
|
|
|
}
|
2017-08-28 11:19:58 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
2013-01-27 14:28:45 +00:00
|
|
|
}
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2013-01-27 14:28:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ID should be not NULL */
|
2019-07-08 00:06:52 +10:00
|
|
|
void BKE_packedfile_id_unpack(Main *bmain, ID *id, ReportList *reports, enum ePF_FileStatus how)
|
2013-01-27 14:28:45 +00:00
|
|
|
{
|
2014-04-23 19:22:03 +10:00
|
|
|
switch (GS(id->name)) {
|
|
|
|
|
case ID_IM: {
|
|
|
|
|
Image *ima = (Image *)id;
|
2015-04-06 10:40:12 -03:00
|
|
|
if (BKE_image_has_packedfile(ima)) {
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_unpack_image(bmain, reports, ima, how);
|
2014-04-23 19:22:03 +10:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_VF: {
|
|
|
|
|
VFont *vf = (VFont *)id;
|
|
|
|
|
if (vf->packedfile) {
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_unpack_vfont(bmain, reports, vf, how);
|
2014-04-23 19:22:03 +10:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ID_SO: {
|
|
|
|
|
bSound *snd = (bSound *)id;
|
|
|
|
|
if (snd->packedfile) {
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_unpack_sound(bmain, reports, snd, how);
|
2014-04-23 19:22:03 +10:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
case ID_VO: {
|
|
|
|
|
Volume *volume = (Volume *)id;
|
|
|
|
|
if (volume->packedfile) {
|
|
|
|
|
BKE_packedfile_unpack_volume(bmain, reports, volume, how);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-04-23 19:22:03 +10:00
|
|
|
case ID_LI: {
|
|
|
|
|
Library *li = (Library *)id;
|
2020-06-23 09:54:14 +10:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Cannot unpack individual Library file, '%s'", li->filepath);
|
2014-04-23 19:22:03 +10:00
|
|
|
break;
|
|
|
|
|
}
|
2017-08-28 11:19:58 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
2013-01-27 14:28:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-10 14:35:09 +02:00
|
|
|
|
|
|
|
|
void BKE_packedfile_blend_write(BlendWriter *writer, PackedFile *pf)
|
|
|
|
|
{
|
|
|
|
|
if (pf == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
BLO_write_struct(writer, PackedFile, pf);
|
|
|
|
|
BLO_write_raw(writer, pf->size, pf->data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p)
|
|
|
|
|
{
|
|
|
|
|
BLO_read_packed_address(reader, pf_p);
|
|
|
|
|
PackedFile *pf = *pf_p;
|
|
|
|
|
if (pf == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLO_read_packed_address(reader, &pf->data);
|
|
|
|
|
if (pf->data == NULL) {
|
|
|
|
|
/* We cannot allow a PackedFile with a NULL data field,
|
|
|
|
|
* the whole code assumes this is not possible. See T70315. */
|
|
|
|
|
printf("%s: NULL packedfile data, cleaning up...\n", __func__);
|
|
|
|
|
MEM_SAFE_FREE(pf);
|
|
|
|
|
}
|
|
|
|
|
}
|