2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2011-02-27 20:40:57 +00:00
|
|
|
*/
|
|
|
|
|
|
2025-01-26 20:07:57 +01:00
|
|
|
#include <algorithm>
|
2023-07-22 11:27:25 +10:00
|
|
|
#include <cstdio>
|
2002-10-12 11:37:38 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
#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"
|
2023-07-22 11:27:25 +10:00
|
|
|
#include <cstring>
|
2002-10-12 11:37:38 +00:00
|
|
|
|
Fix: Broken "File -> External Data -> Pack Linked Libraries"
The operator refused to pack libraries with absolute paths (wasnt the
case in its original implementation 16411da41e40, but was added in
129fb516f431 -- for the reason of preventing "bad things happen on
unpacking" without an explanation of what these exactly are). It did so
by cancelling as soon as **one** library with ab absolute path was
found.
Now with the introduction of essential assets, we have those absolute
path linkages more or less "by default" as soon as e.g. a brush is
used, so the operator is more or less unusable now. NOTE: these absolute
essential asset library paths seem to be converted to relative on save?
Upon reload, these are then gone... (might be another hint for an
alternative fix, see below)
By "bad things happen on unpacking" I would assume the scenario of
folders being created in unwanted locations (e.g. when moving from one
OS to another), but the same thing is also true for packing **files**
instead of libraries (there, absolute paths are allowed, and unpacking
in original locations can equally fail or create folder structures that
are "unexpected"). NOTE: for files though we have the choice of
unpacking to a relative folder (which wouldnt really be possible since
libraries can be nested and we would have to correct paths all over the
place). NOTE: the chance of creating "unwanted" folder structures with
relative paths might be slimmer, but if you have a lot of "upwards"
parent folders, relative can easily "break" as well.
Possible ways to resolve this:
### [1] skip libraries identified as essentials assets (still cancel on all other absolute paths)
Can check a library path to be contained in `EssentialsAssetLibrary`
`essentials_directory_path`. This would be the safest imo since it is a no-behavior change.
### [2] lift the limitation of absolute paths alltogether
Like mentioned above, things could break with "relative" almost as
easily as with "absolute", there might even be scenarios where
"absolute" is wanted. It is a more behavior-changing fix that we might
explore more after 4.4 is out.
### [3] skip absolute libraries (but continue with non-absolute libraries)
This does change behavior as well (it does not cancel as soon as **one**
library with ab absolute path was found anymore, but the worst case
scenario is that you end up with an "incomplete" file if you really
mixed absolute and realtive lib linking).
This PR implements [1] for now, [2] or [3] can follow for 4.5.
Fixes #134665
Pull Request: https://projects.blender.org/blender/blender/pulls/134839
2025-02-28 17:14:14 +01:00
|
|
|
#include "AS_essentials_library.hh"
|
|
|
|
|
|
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"
|
2024-09-20 16:18:12 +02:00
|
|
|
#include "DNA_modifier_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
|
|
|
|
2025-02-11 16:59:42 +01:00
|
|
|
#include "BLI_listbase.h"
|
2025-01-28 15:27:34 +01:00
|
|
|
#include "BLI_path_utils.hh"
|
|
|
|
|
#include "BLI_string.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2024-09-20 16:18:12 +02:00
|
|
|
#include "BKE_bake_geometry_nodes_modifier.hh"
|
|
|
|
|
#include "BKE_bake_geometry_nodes_modifier_pack.hh"
|
2024-11-12 15:21:59 +01:00
|
|
|
#include "BKE_image.hh"
|
|
|
|
|
#include "BKE_image_format.hh"
|
2025-02-07 17:47:16 +01:00
|
|
|
#include "BKE_library.hh"
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh"
|
2024-08-08 15:13:14 +02:00
|
|
|
#include "BKE_packedFile.hh"
|
2024-02-10 18:34:29 +01:00
|
|
|
#include "BKE_report.hh"
|
2012-08-03 22:12:57 +00:00
|
|
|
#include "BKE_sound.h"
|
2023-11-28 16:05:12 -05:00
|
|
|
#include "BKE_vfont.hh"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_volume.hh"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2024-09-20 16:18:12 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
|
|
|
|
|
2024-01-18 22:50:23 +02:00
|
|
|
#include "IMB_imbuf.hh"
|
2024-09-20 16:18:12 +02:00
|
|
|
|
2023-08-28 15:01:05 +02:00
|
|
|
#include "BLO_read_write.hh"
|
2020-09-10 14:35:09 +02:00
|
|
|
|
2024-08-16 14:34:22 +02:00
|
|
|
#include "CLG_log.h"
|
|
|
|
|
|
|
|
|
|
static CLG_LogRef LOG = {"bke.packedfile"};
|
|
|
|
|
|
2024-08-16 15:03:14 +02:00
|
|
|
using namespace blender;
|
|
|
|
|
|
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
|
|
|
{
|
2023-07-17 10:46:26 +02:00
|
|
|
if ((pf != nullptr) && (size >= 0) && (data != nullptr)) {
|
2002-10-12 11:37:38 +00:00
|
|
|
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) {
|
2024-06-20 14:09:29 +02:00
|
|
|
memcpy(data, ((const 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
|
|
|
}
|
|
|
|
|
|
2024-09-20 16:18:12 +02:00
|
|
|
PackedFileCount 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;
|
2024-09-20 16:18:12 +02:00
|
|
|
|
|
|
|
|
PackedFileCount count;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
/* let's check if there are packed files... */
|
2023-07-17 10:46:26 +02:00
|
|
|
for (ima = static_cast<Image *>(bmain->images.first); ima;
|
|
|
|
|
ima = static_cast<Image *>(ima->id.next))
|
|
|
|
|
{
|
2024-05-22 14:50:25 +02:00
|
|
|
if (BKE_image_has_packedfile(ima) && !ID_IS_LINKED(ima)) {
|
2024-09-20 16:18:12 +02:00
|
|
|
count.individual_files++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (vf = static_cast<VFont *>(bmain->fonts.first); vf; vf = static_cast<VFont *>(vf->id.next)) {
|
2024-05-22 14:50:25 +02:00
|
|
|
if (vf->packedfile && !ID_IS_LINKED(vf)) {
|
2024-09-20 16:18:12 +02:00
|
|
|
count.individual_files++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (sound = static_cast<bSound *>(bmain->sounds.first); sound;
|
|
|
|
|
sound = static_cast<bSound *>(sound->id.next))
|
|
|
|
|
{
|
2024-05-22 14:50:25 +02:00
|
|
|
if (sound->packedfile && !ID_IS_LINKED(sound)) {
|
2024-09-20 16:18:12 +02:00
|
|
|
count.individual_files++;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (volume = static_cast<Volume *>(bmain->volumes.first); volume;
|
|
|
|
|
volume = static_cast<Volume *>(volume->id.next))
|
|
|
|
|
{
|
2024-05-22 14:50:25 +02:00
|
|
|
if (volume->packedfile && !ID_IS_LINKED(volume)) {
|
2024-09-20 16:18:12 +02:00
|
|
|
count.individual_files++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
|
|
|
|
|
if (ID_IS_LINKED(object)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
|
|
|
|
if (md->type == eModifierType_Nodes) {
|
|
|
|
|
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
|
|
|
|
for (const NodesModifierBake &bake : blender::Span{nmd->bakes, nmd->bakes_num}) {
|
|
|
|
|
if (bake.packed) {
|
|
|
|
|
count.bakes++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2023-07-17 10:46:26 +02:00
|
|
|
BLI_assert(pf->data != nullptr);
|
2024-06-20 14:09:29 +02:00
|
|
|
BLI_assert(pf->sharing_info != nullptr);
|
2019-10-01 20:02:57 +02:00
|
|
|
|
2024-06-20 14:09:29 +02:00
|
|
|
pf->sharing_info->remove_user_and_delete_if_last();
|
2002-10-12 11:37:38 +00:00
|
|
|
MEM_freeN(pf);
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2023-07-17 10:46:26 +02:00
|
|
|
printf("%s: Trying to free a nullptr 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
|
|
|
{
|
2023-07-17 10:46:26 +02:00
|
|
|
BLI_assert(pf_src != nullptr);
|
|
|
|
|
BLI_assert(pf_src->data != nullptr);
|
2019-10-01 20:02:57 +02:00
|
|
|
|
2012-08-21 10:39:02 +00:00
|
|
|
PackedFile *pf_dst;
|
|
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
pf_dst = static_cast<PackedFile *>(MEM_dupallocN(pf_src));
|
2024-06-20 14:09:29 +02:00
|
|
|
pf_dst->sharing_info->add_user();
|
2012-08-21 10:39:02 +00:00
|
|
|
|
|
|
|
|
return pf_dst;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 16:18:12 +02:00
|
|
|
PackedFile *BKE_packedfile_new_from_memory(const void *mem,
|
|
|
|
|
int memlen,
|
|
|
|
|
const blender::ImplicitSharingInfo *sharing_info)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2023-07-17 10:46:26 +02:00
|
|
|
BLI_assert(mem != nullptr);
|
2024-09-20 16:18:12 +02:00
|
|
|
if (!sharing_info) {
|
|
|
|
|
/* Assume we are the only owner of that memory currently. */
|
|
|
|
|
sharing_info = blender::implicit_sharing::info_for_mem_free(const_cast<void *>(mem));
|
|
|
|
|
}
|
2019-10-01 20:02:57 +02:00
|
|
|
|
2025-03-20 11:25:19 +01:00
|
|
|
PackedFile *pf = MEM_callocN<PackedFile>("PackedFile");
|
2002-10-12 11:37:38 +00:00
|
|
|
pf->data = mem;
|
|
|
|
|
pf->size = memlen;
|
2024-09-20 16:18:12 +02:00
|
|
|
pf->sharing_info = sharing_info;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return pf;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
PackedFile *BKE_packedfile_new(ReportList *reports, const char *filepath_rel, const char *basepath)
|
2002-10-12 11:37:38 +00:00
|
|
|
{
|
2023-05-03 14:13:27 +10:00
|
|
|
char filepath[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-03-24 16:33:32 +11:00
|
|
|
/* render result has no filepath and can be ignored
|
2009-10-15 08:39:47 +00:00
|
|
|
* any other files with no name can be ignored too */
|
2023-05-03 14:13:27 +10:00
|
|
|
if (filepath_rel[0] == '\0') {
|
2023-10-10 14:47:01 +11:00
|
|
|
return nullptr;
|
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
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(filepath, filepath_rel);
|
2023-05-03 14:13:27 +10:00
|
|
|
BLI_path_abs(filepath, 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
|
|
|
|
2023-10-10 14:47:01 +11:00
|
|
|
const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
|
2014-04-22 16:40:17 +10:00
|
|
|
if (file == -1) {
|
2023-05-03 14:13:27 +10:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Unable to pack file, source path '%s' not found", filepath);
|
2023-10-10 14:47:01 +11:00
|
|
|
return nullptr;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-10-10 14:47:01 +11:00
|
|
|
PackedFile *pf = nullptr;
|
|
|
|
|
const size_t file_size = BLI_file_descriptor_size(file);
|
|
|
|
|
if (file_size == size_t(-1)) {
|
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Unable to access the size of, source path '%s'", filepath);
|
|
|
|
|
}
|
|
|
|
|
else if (file_size > INT_MAX) {
|
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Unable to pack files over 2gb, source path '%s'", filepath);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* #MEM_mallocN complains about `MEM_mallocN(0, "...")`,
|
|
|
|
|
* a single allocation is harmless and doesn't cause any complications. */
|
|
|
|
|
void *data = MEM_mallocN(std::max(file_size, size_t(1)), "packFile");
|
2023-10-10 22:47:35 +11:00
|
|
|
if (BLI_read(file, data, file_size) == file_size) {
|
2023-10-10 14:47:01 +11:00
|
|
|
pf = BKE_packedfile_new_from_memory(data, file_size);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2013-09-18 18:55:12 +00:00
|
|
|
else {
|
|
|
|
|
MEM_freeN(data);
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-10-10 14:47:01 +11:00
|
|
|
close(file);
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (ima = static_cast<Image *>(bmain->images.first); ima;
|
|
|
|
|
ima = static_cast<Image *>(ima->id.next))
|
|
|
|
|
{
|
2024-05-16 14:53:09 +02:00
|
|
|
if (BKE_image_has_packedfile(ima) == false && ID_IS_EDITABLE(ima)) {
|
2022-05-11 20:11:44 -07:00
|
|
|
if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_TILED)) {
|
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
|
|
|
}
|
2022-05-11 20:11:44 -07:00
|
|
|
else if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) && verbose) {
|
2012-10-13 15:44:50 +00:00
|
|
|
BKE_reportf(reports,
|
|
|
|
|
RPT_WARNING,
|
2022-05-11 20:11:44 -07:00
|
|
|
"Image '%s' skipped, packing movies or image sequences 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
|
|
|
}
|
|
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (vfont = static_cast<VFont *>(bmain->fonts.first); vfont;
|
|
|
|
|
vfont = static_cast<VFont *>(vfont->id.next))
|
|
|
|
|
{
|
2024-05-16 14:53:09 +02:00
|
|
|
if (vfont->packedfile == nullptr && ID_IS_EDITABLE(vfont) &&
|
2024-01-02 18:12:54 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (sound = static_cast<bSound *>(bmain->sounds.first); sound;
|
|
|
|
|
sound = static_cast<bSound *>(sound->id.next))
|
|
|
|
|
{
|
2024-05-16 14:53:09 +02:00
|
|
|
if (sound->packedfile == nullptr && ID_IS_EDITABLE(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
|
|
|
}
|
|
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (volume = static_cast<Volume *>(bmain->volumes.first); volume;
|
|
|
|
|
volume = static_cast<Volume *>(volume->id.next))
|
|
|
|
|
{
|
2024-05-16 14:53:09 +02:00
|
|
|
if (volume->packedfile == nullptr && ID_IS_EDITABLE(volume)) {
|
2020-03-17 14:41:48 +01:00
|
|
|
volume->packedfile = BKE_packedfile_new(
|
|
|
|
|
reports, volume->filepath, BKE_main_blendfile_path(bmain));
|
|
|
|
|
tot++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 16:18:12 +02:00
|
|
|
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
|
|
|
|
|
if (ID_IS_LINKED(object)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
|
|
|
|
if (md->type == eModifierType_Nodes) {
|
|
|
|
|
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
|
|
|
|
for (NodesModifierBake &bake : blender::MutableSpan{nmd->bakes, nmd->bakes_num}) {
|
|
|
|
|
blender::bke::bake::pack_geometry_nodes_bake(*bmain, reports, *object, *nmd, bake);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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,
|
2023-05-03 14:13:27 +10:00
|
|
|
const char *filepath_rel,
|
2023-05-23 11:53:05 +10:00
|
|
|
PackedFile *pf)
|
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;
|
2023-05-03 14:13:27 +10:00
|
|
|
char filepath[FILE_MAX];
|
|
|
|
|
char filepath_temp[FILE_MAX];
|
2023-09-25 16:56:17 +10:00
|
|
|
// void *data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(filepath, filepath_rel);
|
2023-05-03 14:13:27 +10:00
|
|
|
BLI_path_abs(filepath, ref_file_name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
if (BLI_exists(filepath)) {
|
2002-10-12 11:37:38 +00:00
|
|
|
for (number = 1; number <= 999; number++) {
|
2023-05-09 12:50:37 +10:00
|
|
|
SNPRINTF(filepath_temp, "%s.%03d_", filepath, number);
|
2023-05-03 14:13:27 +10:00
|
|
|
if (!BLI_exists(filepath_temp)) {
|
|
|
|
|
if (BLI_copy(filepath, filepath_temp) == 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
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
BLI_file_ensure_parent_dir_exists(filepath);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
file = BLI_open(filepath, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
|
2014-04-22 16:40:17 +10:00
|
|
|
if (file == -1) {
|
2023-05-03 14:13:27 +10:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Error creating file '%s'", filepath);
|
2013-08-04 17:30:47 +00:00
|
|
|
ret_value = RET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2002-10-12 11:37:38 +00:00
|
|
|
if (write(file, pf->data, pf->size) != pf->size) {
|
2023-05-03 14:13:27 +10:00
|
|
|
BKE_reportf(reports, RPT_ERROR, "Error writing file '%s'", filepath);
|
2002-10-12 11:37:38 +00:00
|
|
|
ret_value = RET_ERROR;
|
|
|
|
|
}
|
2013-08-04 17:30:47 +00:00
|
|
|
else {
|
2023-05-03 14:13:27 +10:00
|
|
|
BKE_reportf(reports, RPT_INFO, "Saved packed file to: %s", filepath);
|
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) {
|
2023-05-16 13:13:05 +10:00
|
|
|
if (BLI_rename_overwrite(filepath_temp, filepath) != 0) {
|
2012-10-21 14:02:30 +00:00
|
|
|
BKE_reportf(reports,
|
|
|
|
|
RPT_ERROR,
|
|
|
|
|
"Error restoring temp file (check files '%s' '%s')",
|
2023-05-03 14:13:27 +10:00
|
|
|
filepath_temp,
|
|
|
|
|
filepath);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2023-05-03 14:13:27 +10:00
|
|
|
if (BLI_delete(filepath_temp, false, false) != 0) {
|
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", filepath_temp);
|
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_value;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-03-23 11:51:19 +01:00
|
|
|
|
2019-07-08 00:40:56 +10:00
|
|
|
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
|
2023-05-03 14:13:27 +10:00
|
|
|
const char *filepath_rel,
|
2024-04-03 10:22:05 +11:00
|
|
|
const 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];
|
2023-05-03 14:13:27 +10:00
|
|
|
char filepath[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(filepath, filepath_rel);
|
2023-05-03 14:13:27 +10:00
|
|
|
BLI_path_abs(filepath, ref_file_name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
if (BLI_stat(filepath, &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
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
const int file = BLI_open(filepath, 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;
|
2025-02-13 13:29:41 +11:00
|
|
|
len = std::min<ulong>(len, sizeof(buf));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-10-10 22:47:35 +11:00
|
|
|
if (BLI_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
|
|
|
|
2023-10-10 22:47:35 +11:00
|
|
|
if (memcmp(buf, ((const 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
|
|
|
}
|
|
|
|
|
|
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
|
|
|
{
|
2023-07-17 10:46:26 +02:00
|
|
|
char *newname = nullptr;
|
|
|
|
|
const char *temp = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
if (pf != nullptr) {
|
2002-10-12 11:37:38 +00:00
|
|
|
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
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(temp_abs, local_name);
|
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:
|
2023-05-23 11:53:05 +10:00
|
|
|
if (BKE_packedfile_write_to_file(reports, ref_file_name, local_name, pf) == 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
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(temp_abs, abs_name);
|
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:
|
2023-05-23 11:53:05 +10:00
|
|
|
if (BKE_packedfile_write_to_file(reports, ref_file_name, abs_name, pf) == RET_OK) {
|
2002-10-12 11:37:38 +00:00
|
|
|
temp = abs_name;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2023-07-17 10:46:26 +02:00
|
|
|
printf("%s: unknown return_value %d\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
|
|
|
}
|
|
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
static void unpack_generate_paths(const char *filepath,
|
2015-05-08 07:25:39 +10:00
|
|
|
ID *id,
|
|
|
|
|
char *r_abspath,
|
2023-05-13 17:34:23 +10:00
|
|
|
size_t abspath_maxncpy,
|
2015-05-08 07:25:39 +10:00
|
|
|
char *r_relpath,
|
2023-05-13 17:34:23 +10:00
|
|
|
size_t relpath_maxncpy)
|
2015-03-07 13:58:21 +01:00
|
|
|
{
|
2020-11-13 09:57:55 +11:00
|
|
|
const short id_type = GS(id->name);
|
2023-05-03 14:13:27 +10:00
|
|
|
char temp_filename[FILE_MAX];
|
|
|
|
|
char temp_dirname[FILE_MAXDIR];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
BLI_path_split_dir_file(
|
|
|
|
|
filepath, temp_dirname, sizeof(temp_dirname), temp_filename, sizeof(temp_filename));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
if (temp_filename[0] == '\0') {
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: we generally do not have any real way to re-create extension out of data. */
|
2023-05-09 12:50:37 +10:00
|
|
|
const size_t len = STRNCPY_RLEN(temp_filename, id->name + 2);
|
2023-05-03 14:13:27 +10:00
|
|
|
printf("%s\n", temp_filename);
|
2020-11-13 09:57:55 +11:00
|
|
|
|
2022-05-11 20:11:44 -07:00
|
|
|
/* For images ensure that the temporary filename contains tile number information as well as
|
|
|
|
|
* a file extension based on the file magic. */
|
2020-11-13 09:57:55 +11:00
|
|
|
if (id_type == ID_IM) {
|
2022-05-11 20:11:44 -07:00
|
|
|
Image *ima = (Image *)id;
|
2023-07-17 10:46:26 +02:00
|
|
|
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(ima->packedfiles.last);
|
|
|
|
|
if (imapf != nullptr && imapf->packedfile != nullptr) {
|
2020-11-13 09:57:55 +11:00
|
|
|
const PackedFile *pf = imapf->packedfile;
|
2023-07-17 10:46:26 +02:00
|
|
|
enum eImbFileType ftype = eImbFileType(
|
2025-03-27 13:12:54 +01:00
|
|
|
IMB_test_image_type_from_memory((const uchar *)pf->data, pf->size));
|
2022-05-11 20:11:44 -07:00
|
|
|
if (ima->source == IMA_SRC_TILED) {
|
|
|
|
|
char tile_number[6];
|
2023-05-09 12:50:37 +10:00
|
|
|
SNPRINTF(tile_number, ".%d", imapf->tile_number);
|
2023-05-03 14:13:27 +10:00
|
|
|
BLI_strncpy(temp_filename + len, tile_number, sizeof(temp_filename) - len);
|
2022-05-11 20:11:44 -07:00
|
|
|
}
|
2020-11-13 20:25:21 +11:00
|
|
|
if (ftype != IMB_FTYPE_NONE) {
|
2023-07-17 10:46:26 +02:00
|
|
|
const int imtype = BKE_ftype_to_imtype(ftype, nullptr);
|
2023-05-05 12:40:27 +10:00
|
|
|
BKE_image_path_ext_from_imtype_ensure(temp_filename, sizeof(temp_filename), imtype);
|
2020-11-13 09:57:55 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
BLI_path_make_safe_filename(temp_filename);
|
|
|
|
|
printf("%s\n", temp_filename);
|
2015-03-07 13:58:21 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-03 14:13:27 +10:00
|
|
|
if (temp_dirname[0] == '\0') {
|
2015-03-07 13:58:21 +01:00
|
|
|
/* Fallback to relative dir. */
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(temp_dirname, "//");
|
2015-03-07 13:58:21 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-12 10:10:54 +10:00
|
|
|
{
|
2023-07-17 10:46:26 +02:00
|
|
|
const char *dir_name = nullptr;
|
2022-09-12 10:10:54 +10:00
|
|
|
switch (id_type) {
|
|
|
|
|
case ID_VF:
|
|
|
|
|
dir_name = "fonts";
|
|
|
|
|
break;
|
|
|
|
|
case ID_SO:
|
|
|
|
|
dir_name = "sounds";
|
|
|
|
|
break;
|
|
|
|
|
case ID_IM:
|
|
|
|
|
dir_name = "textures";
|
|
|
|
|
break;
|
|
|
|
|
case ID_VO:
|
|
|
|
|
dir_name = "volumes";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (dir_name) {
|
2023-05-13 17:34:23 +10:00
|
|
|
BLI_path_join(r_relpath, relpath_maxncpy, "//", dir_name, temp_filename);
|
2022-09-12 10:10:54 +10:00
|
|
|
}
|
2015-03-07 13:58:21 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-03-07 13:58:21 +01:00
|
|
|
{
|
2023-05-13 17:34:23 +10:00
|
|
|
size_t len = BLI_strncpy_rlen(r_abspath, temp_dirname, abspath_maxncpy);
|
|
|
|
|
BLI_strncpy(r_abspath + len, temp_filename, abspath_maxncpy - len);
|
2015-03-07 13:58:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2021-09-13 14:13:58 +02:00
|
|
|
char *BKE_packedfile_unpack(Main *bmain,
|
|
|
|
|
ReportList *reports,
|
|
|
|
|
ID *id,
|
|
|
|
|
const char *orig_file_path,
|
|
|
|
|
PackedFile *pf,
|
|
|
|
|
enum ePF_FileStatus how)
|
|
|
|
|
{
|
|
|
|
|
char localname[FILE_MAX], absname[FILE_MAX];
|
2023-07-17 10:46:26 +02:00
|
|
|
char *new_name = nullptr;
|
2021-09-13 14:13:58 +02:00
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
if (id != nullptr) {
|
2021-09-13 14:13:58 +02:00
|
|
|
unpack_generate_paths(
|
2023-05-13 17:34:23 +10:00
|
|
|
orig_file_path, id, absname, sizeof(absname), localname, sizeof(localname));
|
2021-09-13 14:13:58 +02:00
|
|
|
new_name = BKE_packedfile_unpack_to_file(
|
|
|
|
|
reports, BKE_main_blendfile_path(bmain), absname, localname, pf, how);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new_name;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
{
|
|
|
|
|
int ret_value = RET_ERROR;
|
2021-09-13 14:13:58 +02:00
|
|
|
if (vfont) {
|
|
|
|
|
char *new_file_path = BKE_packedfile_unpack(
|
|
|
|
|
bmain, reports, (ID *)vfont, vfont->filepath, vfont->packedfile, how);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
if (new_file_path != nullptr) {
|
2002-10-12 11:37:38 +00:00
|
|
|
ret_value = RET_OK;
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_free(vfont->packedfile);
|
2023-07-17 10:46:26 +02:00
|
|
|
vfont->packedfile = nullptr;
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(vfont->filepath, new_file_path);
|
2021-09-13 14:13:58 +02:00
|
|
|
MEM_freeN(new_file_path);
|
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_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
|
|
|
{
|
|
|
|
|
int ret_value = RET_ERROR;
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
if (sound != nullptr) {
|
2021-09-13 14:13:58 +02:00
|
|
|
char *new_file_path = BKE_packedfile_unpack(
|
|
|
|
|
bmain, reports, (ID *)sound, sound->filepath, sound->packedfile, how);
|
2023-07-17 10:46:26 +02:00
|
|
|
if (new_file_path != nullptr) {
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(sound->filepath, new_file_path);
|
2021-09-13 14:13:58 +02:00
|
|
|
MEM_freeN(new_file_path);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-07-07 23:57:35 +10:00
|
|
|
BKE_packedfile_free(sound->packedfile);
|
2023-07-17 10:46:26 +02:00
|
|
|
sound->packedfile = nullptr;
|
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
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
if (ima != nullptr) {
|
2015-04-06 10:40:12 -03:00
|
|
|
while (ima->packedfiles.last) {
|
2023-07-17 10:46:26 +02:00
|
|
|
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(ima->packedfiles.last);
|
2021-09-13 14:13:58 +02:00
|
|
|
char *new_file_path = BKE_packedfile_unpack(
|
|
|
|
|
bmain, reports, (ID *)ima, imapf->filepath, imapf->packedfile, how);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
if (new_file_path != nullptr) {
|
2015-04-06 10:40:12 -03:00
|
|
|
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);
|
2023-07-17 10:46:26 +02:00
|
|
|
imapf->packedfile = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* update the new corresponding view filepath */
|
2023-07-17 10:46:26 +02:00
|
|
|
iv = static_cast<ImageView *>(
|
|
|
|
|
BLI_findstring(&ima->views, imapf->filepath, offsetof(ImageView, filepath)));
|
2015-04-06 10:40:12 -03:00
|
|
|
if (iv) {
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(iv->filepath, new_file_path);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
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) {
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(ima->filepath, new_file_path);
|
2022-05-11 20:11:44 -07:00
|
|
|
if (ima->source == IMA_SRC_TILED) {
|
|
|
|
|
/* Ensure that the Image filepath is kept in a tokenized format. */
|
2023-04-28 21:38:20 +10:00
|
|
|
BKE_image_ensure_tile_token(ima->filepath, sizeof(ima->filepath));
|
2022-05-11 20:11:44 -07:00
|
|
|
}
|
2015-10-21 03:07:40 +11:00
|
|
|
}
|
2021-09-13 14:13:58 +02:00
|
|
|
MEM_freeN(new_file_path);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
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) {
|
2023-07-17 10:46:26 +02:00
|
|
|
BKE_image_signal(bmain, ima, nullptr, 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)
|
|
|
|
|
{
|
|
|
|
|
int ret_value = RET_ERROR;
|
|
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
if (volume != nullptr) {
|
2021-09-13 14:13:58 +02:00
|
|
|
char *new_file_path = BKE_packedfile_unpack(
|
|
|
|
|
bmain, reports, (ID *)volume, volume->filepath, volume->packedfile, how);
|
2023-07-17 10:46:26 +02:00
|
|
|
if (new_file_path != nullptr) {
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(volume->filepath, new_file_path);
|
2021-09-13 14:13:58 +02:00
|
|
|
MEM_freeN(new_file_path);
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
BKE_packedfile_free(volume->packedfile);
|
2023-07-17 10:46:26 +02:00
|
|
|
volume->packedfile = nullptr;
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
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
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (lib = static_cast<Library *>(bmain->libraries.first); lib;
|
|
|
|
|
lib = static_cast<Library *>(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),
|
2025-02-07 17:47:16 +01:00
|
|
|
lib->runtime->filepath_abs,
|
|
|
|
|
lib->runtime->filepath_abs,
|
2019-07-07 23:57:35 +10:00
|
|
|
lib->packedfile,
|
|
|
|
|
PF_WRITE_ORIGINAL);
|
2023-07-17 10:46:26 +02:00
|
|
|
if (newname != nullptr) {
|
2012-12-27 15:07:19 +00:00
|
|
|
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);
|
2023-07-17 10:46:26 +02:00
|
|
|
lib->packedfile = nullptr;
|
2012-12-27 15:07:19 +00:00
|
|
|
|
|
|
|
|
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
|
|
|
|
Fix: Broken "File -> External Data -> Pack Linked Libraries"
The operator refused to pack libraries with absolute paths (wasnt the
case in its original implementation 16411da41e40, but was added in
129fb516f431 -- for the reason of preventing "bad things happen on
unpacking" without an explanation of what these exactly are). It did so
by cancelling as soon as **one** library with ab absolute path was
found.
Now with the introduction of essential assets, we have those absolute
path linkages more or less "by default" as soon as e.g. a brush is
used, so the operator is more or less unusable now. NOTE: these absolute
essential asset library paths seem to be converted to relative on save?
Upon reload, these are then gone... (might be another hint for an
alternative fix, see below)
By "bad things happen on unpacking" I would assume the scenario of
folders being created in unwanted locations (e.g. when moving from one
OS to another), but the same thing is also true for packing **files**
instead of libraries (there, absolute paths are allowed, and unpacking
in original locations can equally fail or create folder structures that
are "unexpected"). NOTE: for files though we have the choice of
unpacking to a relative folder (which wouldnt really be possible since
libraries can be nested and we would have to correct paths all over the
place). NOTE: the chance of creating "unwanted" folder structures with
relative paths might be slimmer, but if you have a lot of "upwards"
parent folders, relative can easily "break" as well.
Possible ways to resolve this:
### [1] skip libraries identified as essentials assets (still cancel on all other absolute paths)
Can check a library path to be contained in `EssentialsAssetLibrary`
`essentials_directory_path`. This would be the safest imo since it is a no-behavior change.
### [2] lift the limitation of absolute paths alltogether
Like mentioned above, things could break with "relative" almost as
easily as with "absolute", there might even be scenarios where
"absolute" is wanted. It is a more behavior-changing fix that we might
explore more after 4.4 is out.
### [3] skip absolute libraries (but continue with non-absolute libraries)
This does change behavior as well (it does not cancel as soon as **one**
library with ab absolute path was found anymore, but the worst case
scenario is that you end up with an "incomplete" file if you really
mixed absolute and realtive lib linking).
This PR implements [1] for now, [2] or [3] can follow for 4.5.
Fixes #134665
Pull Request: https://projects.blender.org/blender/blender/pulls/134839
2025-02-28 17:14:14 +01:00
|
|
|
/* Only allow libraries with relative paths (to avoid issues when unpacking, a limitation that we
|
|
|
|
|
* might want to lift since the "relativeness" does not really ensure sanity significantly more).
|
|
|
|
|
*/
|
2023-07-17 10:46:26 +02:00
|
|
|
for (lib = static_cast<Library *>(bmain->libraries.first); lib;
|
|
|
|
|
lib = static_cast<Library *>(lib->id.next))
|
|
|
|
|
{
|
Fix: Broken "File -> External Data -> Pack Linked Libraries"
The operator refused to pack libraries with absolute paths (wasnt the
case in its original implementation 16411da41e40, but was added in
129fb516f431 -- for the reason of preventing "bad things happen on
unpacking" without an explanation of what these exactly are). It did so
by cancelling as soon as **one** library with ab absolute path was
found.
Now with the introduction of essential assets, we have those absolute
path linkages more or less "by default" as soon as e.g. a brush is
used, so the operator is more or less unusable now. NOTE: these absolute
essential asset library paths seem to be converted to relative on save?
Upon reload, these are then gone... (might be another hint for an
alternative fix, see below)
By "bad things happen on unpacking" I would assume the scenario of
folders being created in unwanted locations (e.g. when moving from one
OS to another), but the same thing is also true for packing **files**
instead of libraries (there, absolute paths are allowed, and unpacking
in original locations can equally fail or create folder structures that
are "unexpected"). NOTE: for files though we have the choice of
unpacking to a relative folder (which wouldnt really be possible since
libraries can be nested and we would have to correct paths all over the
place). NOTE: the chance of creating "unwanted" folder structures with
relative paths might be slimmer, but if you have a lot of "upwards"
parent folders, relative can easily "break" as well.
Possible ways to resolve this:
### [1] skip libraries identified as essentials assets (still cancel on all other absolute paths)
Can check a library path to be contained in `EssentialsAssetLibrary`
`essentials_directory_path`. This would be the safest imo since it is a no-behavior change.
### [2] lift the limitation of absolute paths alltogether
Like mentioned above, things could break with "relative" almost as
easily as with "absolute", there might even be scenarios where
"absolute" is wanted. It is a more behavior-changing fix that we might
explore more after 4.4 is out.
### [3] skip absolute libraries (but continue with non-absolute libraries)
This does change behavior as well (it does not cancel as soon as **one**
library with ab absolute path was found anymore, but the worst case
scenario is that you end up with an "incomplete" file if you really
mixed absolute and realtive lib linking).
This PR implements [1] for now, [2] or [3] can follow for 4.5.
Fixes #134665
Pull Request: https://projects.blender.org/blender/blender/pulls/134839
2025-02-28 17:14:14 +01:00
|
|
|
/* Exception to the above: essential assets have an absolute path and should not prevent to
|
|
|
|
|
* operator from continuing. */
|
|
|
|
|
if (BLI_path_contains(blender::asset_system::essentials_directory_path().c_str(),
|
|
|
|
|
lib->filepath))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (lib = static_cast<Library *>(bmain->libraries.first); lib;
|
|
|
|
|
lib = static_cast<Library *>(lib->id.next))
|
|
|
|
|
{
|
Fix: Broken "File -> External Data -> Pack Linked Libraries"
The operator refused to pack libraries with absolute paths (wasnt the
case in its original implementation 16411da41e40, but was added in
129fb516f431 -- for the reason of preventing "bad things happen on
unpacking" without an explanation of what these exactly are). It did so
by cancelling as soon as **one** library with ab absolute path was
found.
Now with the introduction of essential assets, we have those absolute
path linkages more or less "by default" as soon as e.g. a brush is
used, so the operator is more or less unusable now. NOTE: these absolute
essential asset library paths seem to be converted to relative on save?
Upon reload, these are then gone... (might be another hint for an
alternative fix, see below)
By "bad things happen on unpacking" I would assume the scenario of
folders being created in unwanted locations (e.g. when moving from one
OS to another), but the same thing is also true for packing **files**
instead of libraries (there, absolute paths are allowed, and unpacking
in original locations can equally fail or create folder structures that
are "unexpected"). NOTE: for files though we have the choice of
unpacking to a relative folder (which wouldnt really be possible since
libraries can be nested and we would have to correct paths all over the
place). NOTE: the chance of creating "unwanted" folder structures with
relative paths might be slimmer, but if you have a lot of "upwards"
parent folders, relative can easily "break" as well.
Possible ways to resolve this:
### [1] skip libraries identified as essentials assets (still cancel on all other absolute paths)
Can check a library path to be contained in `EssentialsAssetLibrary`
`essentials_directory_path`. This would be the safest imo since it is a no-behavior change.
### [2] lift the limitation of absolute paths alltogether
Like mentioned above, things could break with "relative" almost as
easily as with "absolute", there might even be scenarios where
"absolute" is wanted. It is a more behavior-changing fix that we might
explore more after 4.4 is out.
### [3] skip absolute libraries (but continue with non-absolute libraries)
This does change behavior as well (it does not cancel as soon as **one**
library with ab absolute path was found anymore, but the worst case
scenario is that you end up with an "incomplete" file if you really
mixed absolute and realtive lib linking).
This PR implements [1] for now, [2] or [3] can follow for 4.5.
Fixes #134665
Pull Request: https://projects.blender.org/blender/blender/pulls/134839
2025-02-28 17:14:14 +01:00
|
|
|
/* Do not really pack essential assets though (see above). */
|
|
|
|
|
if (BLI_path_contains(blender::asset_system::essentials_directory_path().c_str(),
|
|
|
|
|
lib->filepath))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2023-07-17 10:46:26 +02:00
|
|
|
if (lib->packedfile == nullptr) {
|
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
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (ima = static_cast<Image *>(bmain->images.first); ima;
|
|
|
|
|
ima = static_cast<Image *>(ima->id.next))
|
|
|
|
|
{
|
2024-05-22 14:50:25 +02:00
|
|
|
if (BKE_image_has_packedfile(ima) && !ID_IS_LINKED(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
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (vf = static_cast<VFont *>(bmain->fonts.first); vf; vf = static_cast<VFont *>(vf->id.next)) {
|
2024-05-22 14:50:25 +02:00
|
|
|
if (vf->packedfile && !ID_IS_LINKED(vf)) {
|
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
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (sound = static_cast<bSound *>(bmain->sounds.first); sound;
|
|
|
|
|
sound = static_cast<bSound *>(sound->id.next))
|
|
|
|
|
{
|
2024-05-22 14:50:25 +02:00
|
|
|
if (sound->packedfile && !ID_IS_LINKED(sound)) {
|
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
|
|
|
|
2023-07-17 10:46:26 +02:00
|
|
|
for (volume = static_cast<Volume *>(bmain->volumes.first); volume;
|
|
|
|
|
volume = static_cast<Volume *>(volume->id.next))
|
|
|
|
|
{
|
2024-05-22 14:50:25 +02:00
|
|
|
if (volume->packedfile && !ID_IS_LINKED(volume)) {
|
2020-03-17 14:41:48 +01:00
|
|
|
BKE_packedfile_unpack_volume(bmain, reports, volume, how);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-20 16:18:12 +02:00
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
|
|
|
|
|
if (ID_IS_LINKED(object)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
|
|
|
|
|
if (md->type == eModifierType_Nodes) {
|
|
|
|
|
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
|
|
|
|
|
for (NodesModifierBake &bake : blender::MutableSpan{nmd->bakes, nmd->bakes_num}) {
|
|
|
|
|
blender::bke::bake::unpack_geometry_nodes_bake(
|
|
|
|
|
*bmain, reports, *object, *nmd, bake, how);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2009-06-30 19:20:45 +00:00
|
|
|
|
2021-10-11 09:40:22 +02:00
|
|
|
bool BKE_packedfile_id_check(const 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: {
|
2021-10-11 09:40:22 +02:00
|
|
|
const Image *ima = (const 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: {
|
2021-10-11 09:40:22 +02:00
|
|
|
const VFont *vf = (const VFont *)id;
|
2023-07-17 10:46:26 +02:00
|
|
|
return vf->packedfile != nullptr;
|
2014-04-23 19:22:03 +10:00
|
|
|
}
|
|
|
|
|
case ID_SO: {
|
2021-10-11 09:40:22 +02:00
|
|
|
const bSound *snd = (const bSound *)id;
|
2023-07-17 10:46:26 +02:00
|
|
|
return snd->packedfile != nullptr;
|
2014-04-23 19:22:03 +10:00
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
case ID_VO: {
|
2021-10-11 09:40:22 +02:00
|
|
|
const Volume *volume = (const Volume *)id;
|
2023-07-17 10:46:26 +02:00
|
|
|
return volume->packedfile != nullptr;
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
2014-04-23 19:22:03 +10:00
|
|
|
case ID_LI: {
|
2021-10-11 09:40:22 +02:00
|
|
|
const Library *li = (const Library *)id;
|
2023-07-17 10:46:26 +02:00
|
|
|
return li->packedfile != nullptr;
|
2014-04-23 19:22:03 +10:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
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
|
|
|
{
|
2024-05-22 15:02:37 +02:00
|
|
|
/* Only unpack when datablock is editable. */
|
|
|
|
|
if (!ID_IS_EDITABLE(id)) {
|
2024-05-22 14:50:25 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2024-04-03 10:22:05 +11:00
|
|
|
void BKE_packedfile_blend_write(BlendWriter *writer, const PackedFile *pf)
|
2020-09-10 14:35:09 +02:00
|
|
|
{
|
2023-07-17 10:46:26 +02:00
|
|
|
if (pf == nullptr) {
|
2020-09-10 14:35:09 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
BLO_write_struct(writer, PackedFile, pf);
|
2024-06-20 14:09:29 +02:00
|
|
|
BLO_write_shared(writer, pf->data, pf->size, pf->sharing_info, [&]() {
|
|
|
|
|
BLO_write_raw(writer, pf->size, pf->data);
|
|
|
|
|
});
|
2020-09-10 14:35:09 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-16 15:03:14 +02:00
|
|
|
void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p, StringRefNull filepath)
|
2020-09-10 14:35:09 +02:00
|
|
|
{
|
2024-06-20 13:51:48 +02:00
|
|
|
BLO_read_struct(reader, PackedFile, pf_p);
|
2020-09-10 14:35:09 +02:00
|
|
|
PackedFile *pf = *pf_p;
|
2023-07-17 10:46:26 +02:00
|
|
|
if (pf == nullptr) {
|
2020-09-10 14:35:09 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2024-07-31 18:30:50 +02:00
|
|
|
/* NOTE: there is no way to handle endianness switch here. */
|
2024-06-20 14:09:29 +02:00
|
|
|
pf->sharing_info = BLO_read_shared(reader, &pf->data, [&]() {
|
|
|
|
|
BLO_read_data_address(reader, &pf->data);
|
2024-08-20 14:25:52 +10:00
|
|
|
/* Do not create an implicit sharing if read data pointer is `nullptr`. */
|
2024-08-16 14:34:22 +02:00
|
|
|
return pf->data ? blender::implicit_sharing::info_for_mem_free(const_cast<void *>(pf->data)) :
|
|
|
|
|
nullptr;
|
2024-06-20 14:09:29 +02:00
|
|
|
});
|
2023-07-17 10:46:26 +02:00
|
|
|
if (pf->data == nullptr) {
|
2024-08-23 10:02:36 +10:00
|
|
|
/* We cannot allow a #PackedFile with a nullptr data field,
|
2023-02-12 14:37:16 +11:00
|
|
|
* the whole code assumes this is not possible. See #70315. */
|
2024-08-16 15:03:14 +02:00
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
|
"%s: nullptr packedfile data (source: '%s'), cleaning up...",
|
|
|
|
|
__func__,
|
|
|
|
|
filepath.c_str());
|
2024-08-16 14:34:22 +02:00
|
|
|
BLI_assert(pf->sharing_info == nullptr);
|
|
|
|
|
MEM_SAFE_FREE(*pf_p);
|
2020-09-10 14:35:09 +02:00
|
|
|
}
|
|
|
|
|
}
|