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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager/intern/wm_files.c')
-rw-r--r--source/blender/windowmanager/intern/wm_files.c264
1 files changed, 167 insertions, 97 deletions
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 06aaf95f232..f83511e76f0 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -28,11 +28,10 @@
* winsock stuff.
*/
#include <errno.h>
+#include <fcntl.h> /* for open flags (O_BINARY, O_RDONLY). */
#include <stddef.h>
#include <string.h>
-#include "zlib.h" /* wm_read_exotic() */
-
#ifdef WIN32
/* Need to include windows.h so _WIN32_IE is defined. */
# include <windows.h>
@@ -51,6 +50,7 @@
#include "BLI_blenlib.h"
#include "BLI_fileops_types.h"
+#include "BLI_filereader.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_system.h"
@@ -481,53 +481,64 @@ static void wm_init_userdef(Main *bmain)
/* intended to check for non-blender formats but for now it only reads blends */
static int wm_read_exotic(const char *name)
{
- int len;
- gzFile gzfile;
+ /* make sure we're not trying to read a directory.... */
+
+ int namelen = strlen(name);
+ if (namelen > 0 && ELEM(name[namelen - 1], '/', '\\')) {
+ return BKE_READ_EXOTIC_FAIL_PATH;
+ }
+
+ /* open the file. */
+ const int filedes = BLI_open(name, O_BINARY | O_RDONLY, 0);
+ if (filedes == -1) {
+ return BKE_READ_EXOTIC_FAIL_OPEN;
+ }
+
+ FileReader *rawfile = BLI_filereader_new_file(filedes);
+ if (rawfile == NULL) {
+ return BKE_READ_EXOTIC_FAIL_OPEN;
+ }
+
+ /* read the header (7 bytes are enough to identify all known types). */
char header[7];
- int retval;
+ if (rawfile->read(rawfile, header, sizeof(header)) != sizeof(header)) {
+ rawfile->close(rawfile);
+ return BKE_READ_EXOTIC_FAIL_FORMAT;
+ }
+ rawfile->seek(rawfile, 0, SEEK_SET);
- /* make sure we're not trying to read a directory.... */
+ /* check for uncompressed .blend */
+ if (STREQLEN(header, "BLENDER", 7)) {
+ rawfile->close(rawfile);
+ return BKE_READ_EXOTIC_OK_BLEND;
+ }
- len = strlen(name);
- if (len > 0 && ELEM(name[len - 1], '/', '\\')) {
- retval = BKE_READ_EXOTIC_FAIL_PATH;
+ /* check for compressed .blend */
+ FileReader *compressed_file = NULL;
+ if (BLI_file_magic_is_gzip(header)) {
+ /* In earlier versions of Blender (before 3.0), compressed files used Gzip instead of Zstd.
+ * While these files will no longer be written, there still needs to be reading support. */
+ compressed_file = BLI_filereader_new_gzip(rawfile);
+ }
+ else if (BLI_file_magic_is_zstd(header)) {
+ compressed_file = BLI_filereader_new_zstd(rawfile);
}
- else {
- gzfile = BLI_gzopen(name, "rb");
- if (gzfile == NULL) {
- retval = BKE_READ_EXOTIC_FAIL_OPEN;
- }
- else {
- len = gzread(gzfile, header, sizeof(header));
- gzclose(gzfile);
- if (len == sizeof(header) && STREQLEN(header, "BLENDER", 7)) {
- retval = BKE_READ_EXOTIC_OK_BLEND;
- }
- else {
- /* We may want to support loading other file formats
- * from their header bytes or file extension.
- * This used to be supported in the code below and may be added
- * back at some point. */
-#if 0
- WM_cursor_wait(true);
- if (is_foo_format(name)) {
- read_foo(name);
- retval = BKE_READ_EXOTIC_OK_OTHER;
- }
- else
-#endif
- {
- retval = BKE_READ_EXOTIC_FAIL_FORMAT;
- }
-#if 0
- WM_cursor_wait(false);
-#endif
- }
+ /* If a compression signature matches, try decompressing the start and check if it's a .blend */
+ if (compressed_file != NULL) {
+ size_t len = compressed_file->read(compressed_file, header, sizeof(header));
+ compressed_file->close(compressed_file);
+ if (len == sizeof(header) && STREQLEN(header, "BLENDER", 7)) {
+ return BKE_READ_EXOTIC_OK_BLEND;
}
}
+ else {
+ rawfile->close(rawfile);
+ }
- return retval;
+ /* Add check for future file formats here. */
+
+ return BKE_READ_EXOTIC_FAIL_FORMAT;
}
/** \} */
@@ -596,19 +607,33 @@ static void wm_file_read_pre(bContext *C, bool use_data, bool UNUSED(use_userdef
}
/**
+ * Parameters for #wm_file_read_post, also used for deferred initialization.
+ */
+struct wmFileReadPost_Params {
+ uint use_data : 1;
+ uint use_userdef : 1;
+
+ uint is_startup_file : 1;
+ uint is_factory_startup : 1;
+ uint reset_app_template : 1;
+};
+
+/**
* Logic shared between #WM_file_read & #wm_homefile_read,
* updates to make after reading a file.
*/
-static void wm_file_read_post(bContext *C,
- const bool is_startup_file,
- const bool is_factory_startup,
- const bool use_data,
- const bool use_userdef,
- const bool reset_app_template)
+static void wm_file_read_post(bContext *C, const struct wmFileReadPost_Params *params)
{
- bool addons_loaded = false;
wmWindowManager *wm = CTX_wm_manager(C);
+ const bool use_data = params->use_data;
+ const bool use_userdef = params->use_userdef;
+ const bool is_startup_file = params->is_startup_file;
+ const bool is_factory_startup = params->is_factory_startup;
+ const bool reset_app_template = params->reset_app_template;
+
+ bool addons_loaded = false;
+
if (use_data) {
if (!G.background) {
/* remove windows which failed to be added via WM_check */
@@ -797,22 +822,31 @@ static void file_read_reports_finalize(BlendFileReadReport *bf_reports)
bf_reports->count.resynced_lib_overrides,
duration_lib_override_recursive_resync_minutes,
duration_lib_override_recursive_resync_seconds);
+
if (bf_reports->resynced_lib_overrides_libraries_count != 0) {
for (LinkNode *node_lib = bf_reports->resynced_lib_overrides_libraries; node_lib != NULL;
node_lib = node_lib->next) {
Library *library = node_lib->link;
BKE_reportf(
- bf_reports->reports, RPT_INFO, "Library %s needs overrides resync.", library->filepath);
+ bf_reports->reports, RPT_INFO, "Library %s needs overrides resync", library->filepath);
}
}
+
if (bf_reports->count.missing_libraries != 0 || bf_reports->count.missing_linked_id != 0) {
BKE_reportf(bf_reports->reports,
RPT_WARNING,
- "%d libraries and %d linked data-blocks are missing, please check the "
- "Info and Outliner editors for details",
+ "%d libraries and %d linked data-blocks are missing (including %d ObjectData and "
+ "%d Proxies), please check the Info and Outliner editors for details",
bf_reports->count.missing_libraries,
- bf_reports->count.missing_linked_id);
+ bf_reports->count.missing_linked_id,
+ bf_reports->count.missing_obdata,
+ bf_reports->count.missing_obproxies);
}
+ else {
+ BLI_assert(bf_reports->count.missing_obdata == 0);
+ BLI_assert(bf_reports->count.missing_obproxies == 0);
+ }
+
if (bf_reports->resynced_lib_overrides_libraries_count != 0) {
BKE_reportf(bf_reports->reports,
RPT_WARNING,
@@ -901,7 +935,14 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
wm_history_file_update();
}
- wm_file_read_post(C, false, false, use_data, use_userdef, false);
+ wm_file_read_post(C,
+ &(const struct wmFileReadPost_Params){
+ .use_data = use_data,
+ .use_userdef = use_userdef,
+ .is_startup_file = false,
+ .is_factory_startup = false,
+ .reset_app_template = false,
+ });
bf_reports.duration.whole = PIL_check_seconds_timer() - bf_reports.duration.whole;
file_read_reports_finalize(&bf_reports);
@@ -984,31 +1025,18 @@ const char *WM_init_state_app_template_get(void)
/**
* Called on startup, (context entirely filled with NULLs)
- * or called for 'New File' both startup.blend and userpref.blend are checked.
- *
- * \param use_factory_settings:
- * Ignore on-disk startup file, use bundled `datatoc_startup_blend` instead.
- * Used for "Restore Factory Settings".
+ * or called for 'New File' both `startup.blend` and `userpref.blend` are checked.
*
- * \param use_userdef: Load factory settings as well as startup file.
- * Disabled for "File New" we don't want to reload preferences.
- *
- * \param filepath_startup_override:
- * Optional path pointing to an alternative blend file (may be NULL).
- *
- * \param app_template_override:
- * Template to use instead of the template defined in user-preferences.
- * When not-null, this is written into the user preferences.
+ * \param r_params_file_read_post: Support postponed initialization,
+ * needed for initial startup when only some sub-systems have been initialized.
+ * When non-null, #wm_file_read_post doesn't run, instead it's arguments are stored
+ * in this return argument.
+ * The caller is responsible for calling #wm_homefile_read_post with this return argument.
*/
-void wm_homefile_read(bContext *C,
- ReportList *reports,
- bool use_factory_settings,
- bool use_empty_data,
- bool use_data,
- bool use_userdef,
- const char *filepath_startup_override,
- const char *app_template_override,
- bool *r_is_factory_startup)
+void wm_homefile_read_ex(bContext *C,
+ const struct wmHomeFileRead_Params *params_homefile,
+ ReportList *reports,
+ struct wmFileReadPost_Params **r_params_file_read_post)
{
#if 0 /* UNUSED, keep as this may be needed later & the comment below isn't self evident. */
/* Context does not always have valid main pointer here. */
@@ -1017,6 +1045,14 @@ void wm_homefile_read(bContext *C,
ListBase wmbase;
bool success = false;
+ /* May be enabled, when the user configuration doesn't exist. */
+ const bool use_data = params_homefile->use_data;
+ const bool use_userdef = params_homefile->use_userdef;
+ bool use_factory_settings = params_homefile->use_factory_settings;
+ const bool use_empty_data = params_homefile->use_empty_data;
+ const char *filepath_startup_override = params_homefile->filepath_startup_override;
+ const char *app_template_override = params_homefile->app_template_override;
+
bool filepath_startup_is_factory = true;
char filepath_startup[FILE_MAX];
char filepath_userdef[FILE_MAX];
@@ -1304,13 +1340,45 @@ void wm_homefile_read(bContext *C,
G.save_over = 0;
}
- wm_file_read_post(C, true, is_factory_startup, use_data, use_userdef, reset_app_template);
+ {
+ const struct wmFileReadPost_Params params_file_read_post = {
+ .use_data = use_data,
+ .use_userdef = use_userdef,
+ .is_startup_file = true,
+ .is_factory_startup = is_factory_startup,
+ .reset_app_template = reset_app_template,
+ };
+ if (r_params_file_read_post == NULL) {
+ wm_file_read_post(C, &params_file_read_post);
+ }
+ else {
+ *r_params_file_read_post = MEM_mallocN(sizeof(struct wmFileReadPost_Params), __func__);
+ **r_params_file_read_post = params_file_read_post;
- if (r_is_factory_startup) {
- *r_is_factory_startup = is_factory_startup;
+ /* Match #wm_file_read_post which leaves the window cleared too. */
+ CTX_wm_window_set(C, NULL);
+ }
}
}
+void wm_homefile_read(bContext *C,
+ const struct wmHomeFileRead_Params *params_homefile,
+ ReportList *reports)
+{
+ wm_homefile_read_ex(C, params_homefile, reports, NULL);
+}
+
+/**
+ * Special case, support deferred execution of #wm_file_read_post,
+ * Needed when loading for the first time to workaround order of initialization bug, see T89046.
+ */
+void wm_homefile_read_post(struct bContext *C,
+ const struct wmFileReadPost_Params *params_file_read_post)
+{
+ wm_file_read_post(C, params_file_read_post);
+ MEM_freeN((void *)params_file_read_post);
+}
+
/* -------------------------------------------------------------------- */
/** \name Blend-File History API
* \{ */
@@ -2078,14 +2146,15 @@ static int wm_userpref_read_exec(bContext *C, wmOperator *op)
UserDef U_backup = U;
wm_homefile_read(C,
- op->reports,
- use_factory_settings,
- false,
- use_data,
- use_userdef,
- NULL,
- WM_init_state_app_template_get(),
- NULL);
+ &(const struct wmHomeFileRead_Params){
+ .use_data = use_data,
+ .use_userdef = use_userdef,
+ .use_factory_settings = use_factory_settings,
+ .use_empty_data = false,
+ .filepath_startup_override = NULL,
+ .app_template_override = WM_init_state_app_template_get(),
+ },
+ op->reports);
wm_userpref_read_exceptions(&U, &U_backup);
SET_FLAG_FROM_TEST(G.f, use_factory_settings, G_FLAG_USERPREF_NO_SAVE_ON_EXIT);
@@ -2224,16 +2293,17 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
app_template = WM_init_state_app_template_get();
}
- bool use_data = true;
wm_homefile_read(C,
- op->reports,
- use_factory_settings,
- use_empty_data,
- use_data,
- use_userdef,
- filepath,
- app_template,
- NULL);
+ &(const struct wmHomeFileRead_Params){
+ .use_data = true,
+ .use_userdef = use_userdef,
+ .use_factory_settings = use_factory_settings,
+ .use_empty_data = use_empty_data,
+ .filepath_startup_override = filepath,
+ .app_template_override = app_template,
+ },
+ op->reports);
+
if (use_splash) {
WM_init_splash(C);
}
@@ -3434,7 +3504,7 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C,
BLI_split_file_part(blendfile_pathpath, filename, sizeof(filename));
}
else {
- STRNCPY(filename, IFACE_("untitled.blend"));
+ STRNCPY(filename, "untitled.blend");
}
uiItemL(layout, filename, ICON_NONE);