/** * Logic shared between #WM_file_read & #wm_homefile_read, * updates to make after reading a file. */ static void wm_file_read_post(bContext *C, bool is_startup_file) { bool addons_loaded = false; wmWindowManager *wm = CTX_wm_manager(C); if (!G.background) { /* remove windows which failed to be added via WM_check */ wm_window_ghostwindows_remove_invalid(C, wm); } CTX_wm_window_set(C, wm->windows.first); ED_editors_init(C); DAG_on_visible_update(CTX_data_main(C), true); #ifdef WITH_PYTHON if (is_startup_file) { /* possible python hasn't been initialized */ if (CTX_py_init_get(C)) { /* sync addons, these may have changed from the defaults */ BPY_execute_string(C, "__import__('addon_utils').reset_all()"); BPY_python_reset(C); addons_loaded = true; } } else { /* run any texts that were loaded in and flagged as modules */ BPY_python_reset(C); addons_loaded = true; } #else UNUSED_VARS(is_startup_file); #endif /* WITH_PYTHON */ WM_operatortype_last_properties_clear_all(); /* important to do before NULL'ing the context */ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); /* would otherwise be handled by event loop */ if (G.background) { Main *bmain = CTX_data_main(C); BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C)); } WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); /* report any errors. * currently disabled if addons aren't yet loaded */ if (addons_loaded) { wm_file_read_report(C); } if (!G.background) { /* in background mode this makes it hard to load * a blend file and do anything since the screen * won't be set to a valid value again */ CTX_wm_window_set(C, NULL); /* exits queues */ } if (!G.background) { // undo_editmode_clear(); BKE_undo_reset(); BKE_undo_write(C, "original"); /* save current state */ } }
static int load_file(int UNUSED(argc), const char **argv, void *data) { bContext *C = data; /* Make the path absolute because its needed for relative linked blends to be found */ char filename[FILE_MAX]; /* note, we could skip these, but so far we always tried to load these files */ if (argv[0][0] == '-') { fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]); } BLI_strncpy(filename, argv[0], sizeof(filename)); BLI_path_cwd(filename); if (G.background) { int retval = BKE_read_file(C, filename, NULL); /* we successfully loaded a blend file, get sure that * pointcache works */ if (retval != BKE_READ_FILE_FAIL) { wmWindowManager *wm = CTX_wm_manager(C); /* special case, 2.4x files */ if (wm == NULL && CTX_data_main(C)->wm.first == NULL) { extern void wm_add_default(bContext *C); /* wm_add_default() needs the screen to be set. */ CTX_wm_screen_set(C, CTX_data_main(C)->screen.first); wm_add_default(C); } CTX_wm_manager_set(C, NULL); /* remove wm to force check */ WM_check(C); G.relbase_valid = 1; if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */ DAG_on_visible_update(CTX_data_main(C), TRUE); } else { /* failed to load file, stop processing arguments */ return -1; } /* WM_file_read() runs normally but since we're in background mode do here */ #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ BPY_python_reset(C); #endif /* happens for the UI on file reading too (huh? (ton))*/ // XXX BKE_reset_undo(); // BKE_write_undo("original"); /* save current state */ } else { /* we are not running in background mode here, but start blender in UI mode with * a file - this should do everything a 'load file' does */ ReportList reports; BKE_reports_init(&reports, RPT_PRINT); WM_file_autoexec_init(filename); WM_file_read(C, filename, &reports); BKE_reports_clear(&reports); } G.file_loaded = 1; return 0; }
/* only called once, for startup */ void WM_init(bContext *C, int argc, const char **argv) { if (!G.background) { wm_ghost_init(C); /* note: it assigns C to ghost! */ wm_init_cursor_data(); } GHOST_CreateSystemPaths(); BKE_addon_pref_type_init(); wm_operatortype_init(); wm_operatortypes_register(); WM_menutype_init(); WM_uilisttype_init(); ED_undosys_type_init(); BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */ BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */ BKE_library_callback_remap_editor_id_reference_set(WM_main_remap_editor_id_reference); /* library.c */ BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */ BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap); /* screen.c */ DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update, ED_render_scene_update_pre); /* depsgraph.c */ ED_spacetypes_init(); /* editors/space_api/spacetype.c */ ED_file_init(); /* for fsmenu */ ED_node_init_butfuncs(); BLF_init(); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */ BLT_lang_init(); /* Must call first before doing any .blend file reading, since versionning code may create new IDs... See T57066. */ BLT_lang_set(NULL); /* reports cant be initialized before the wm, * but keep before file reading, since that may report errors */ wm_init_reports(C); /* get the default database, plus a wm */ wm_homefile_read(C, NULL, G.factory_startup, false, true, NULL, WM_init_state_app_template_get()); /* Call again to set from userpreferences... */ BLT_lang_set(NULL); if (!G.background) { #ifdef WITH_INPUT_NDOF /* sets 3D mouse deadzone */ WM_ndof_deadzone_set(U.ndof_deadzone); #endif GPU_init(); GPU_set_mipmap(G_MAIN, !(U.gameflags & USER_DISABLE_MIPMAP)); GPU_set_linear_mipmap(true); GPU_set_anisotropic(G_MAIN, U.anisotropic_filter); GPU_set_gpu_mipmapping(G_MAIN, U.use_gpu_mipmap); #ifdef WITH_OPENSUBDIV BKE_subsurf_osd_init(); #endif UI_init(); } else { /* Note: Currently only inits icons, which we now want in background mode too * (scripts could use those in background processing...). * In case we do more later, we may need to pass a 'background' flag. * Called from 'UI_init' above */ BKE_icons_init(1); } ED_spacemacros_init(); /* note: there is a bug where python needs initializing before loading the * startup.blend because it may contain PyDrivers. It also needs to be after * initializing space types and other internal data. * * However cant redo this at the moment. Solution is to load python * before wm_homefile_read() or make py-drivers check if python is running. * Will try fix when the crash can be repeated. - campbell. */ #ifdef WITH_PYTHON BPY_context_set(C); /* necessary evil */ BPY_python_start(argc, argv); BPY_python_reset(C); #else (void)argc; /* unused */ (void)argv; /* unused */ #endif if (!G.background && !wm_start_with_console) GHOST_toggleConsole(3); clear_matcopybuf(); ED_render_clear_mtex_copybuf(); // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); wm_history_file_read(); /* allow a path of "", this is what happens when making a new file */ #if 0 if (BKE_main_blendfile_path_from_global()[0] == '\0') BLI_make_file_string("/", G_MAIN->name, BKE_appdir_folder_default(), "untitled.blend"); #endif BLI_strncpy(G.lib, BKE_main_blendfile_path_from_global(), sizeof(G.lib)); #ifdef WITH_COMPOSITOR if (1) { extern void *COM_linker_hack; COM_linker_hack = COM_execute; } #endif /* load last session, uses regular file reading so it has to be in end (after init py etc) */ if (U.uiflag2 & USER_KEEP_SESSION) { /* calling WM_recover_last_session(C, NULL) has been moved to creator.c */ /* that prevents loading both the kept session, and the file on the command line */ } else { Main *bmain = CTX_data_main(C); /* note, logic here is from wm_file_read_post, * call functions that depend on Python being initialized. */ /* normally 'wm_homefile_read' will do this, * however python is not initialized when called from this function. * * unlikely any handlers are set but its possible, * note that recovering the last session does its own callbacks. */ CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); wm_file_read_report(C, bmain); if (!G.background) { CTX_wm_window_set(C, NULL); } } }
/* custom_file can be NULL */ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file) { ListBase wmbase; char startstr[FILE_MAX]; char prefstr[FILE_MAX]; int success = 0; /* Indicates whether user prefereneces were really load from memory. * * This is used for versioning code, and for this we can not rely on from_memory * passed via argument. This is because there might be configuration folder * exists but it might not have userpref.blend and in this case we fallback to * reading home file from memory. * * And in this case versioning code is to be run. */ bool read_userdef_from_memory = true; /* options exclude eachother */ BLI_assert((from_memory && custom_file) == 0); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); G.relbase_valid = 0; if (!from_memory) { const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); if (custom_file) { BLI_strncpy(startstr, custom_file, FILE_MAX); if (cfgdir) { BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); } else { prefstr[0] = '\0'; } } else if (cfgdir) { BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE); BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); } else { startstr[0] = '\0'; prefstr[0] = '\0'; from_memory = 1; } } /* prevent loading no UI */ G.fileflags &= ~G_FILE_NO_UI; /* put aside screens to match with persistent windows later */ wm_window_match_init(C, &wmbase); if (!from_memory) { if (BLI_access(startstr, R_OK) == 0) { success = (BKE_read_file(C, startstr, NULL) != BKE_READ_FILE_FAIL); } if (U.themes.first == NULL) { if (G.debug & G_DEBUG) printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr); success = 0; } } if (success == 0 && custom_file && reports) { BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", custom_file); /*We can not return from here because wm is already reset*/ } if (success == 0) { success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true); if (wmbase.first == NULL) wm_clear_default_size(C); BLI_init_temporary_dir(U.tempdir); #ifdef WITH_PYTHON_SECURITY /* use alternative setting for security nuts * otherwise we'd need to patch the binary blob - startup.blend.c */ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; #endif } /* check new prefs only after startup.blend was finished */ if (!from_memory && BLI_exists(prefstr)) { int done = BKE_read_file_userdef(prefstr, NULL); if (done) { read_userdef_from_memory = false; printf("Read new prefs: %s\n", prefstr); } } /* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise * can remove this eventually, only in a 2.53 and older, now its not written */ G.fileflags &= ~G_FILE_RELATIVE_REMAP; /* check userdef before open window, keymaps etc */ wm_init_userdef(C, read_userdef_from_memory); /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); WM_check(C); /* opens window(s), checks keymaps */ G.main->name[0] = '\0'; /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ if (!G.background) GPU_default_lights(); /* XXX */ G.save_over = 0; // start with save preference untitled.blend G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */ // refresh_interface_font(); // undo_editmode_clear(); BKE_reset_undo(); BKE_write_undo(C, "original"); /* save current state */ ED_editors_init(C); DAG_on_visible_update(CTX_data_main(C), TRUE); #ifdef WITH_PYTHON if (CTX_py_init_get(C)) { /* sync addons, these may have changed from the defaults */ BPY_string_exec(C, "__import__('addon_utils').reset_all()"); BPY_python_reset(C); } #endif /* important to do before NULL'ing the context */ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); /* in background mode the scene will stay NULL */ if (!G.background) { CTX_wm_window_set(C, NULL); /* exits queues */ } return TRUE; }
void WM_file_read(bContext *C, const char *filepath, ReportList *reports) { int retval; /* so we can get the error message */ errno = 0; WM_cursor_wait(1); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); /* first try to append data from exotic file formats... */ /* it throws error box when file doesn't exist and returns -1 */ /* note; it should set some error message somewhere... (ton) */ retval = wm_read_exotic(CTX_data_scene(C), filepath); /* we didn't succeed, now try to read Blender file */ if (retval == BKE_READ_EXOTIC_OK_BLEND) { int G_f = G.f; ListBase wmbase; /* assume automated tasks with background, don't write recent file list */ const int do_history = (G.background == FALSE) && (CTX_wm_manager(C)->op_undo_depth == 0); /* put aside screens to match with persistent windows later */ /* also exit screens and editors */ wm_window_match_init(C, &wmbase); /* confusing this global... */ G.relbase_valid = 1; retval = BKE_read_file(C, filepath, reports); /* when loading startup.blend's, we can be left with a blank path */ if (G.main->name[0]) { G.save_over = 1; } else { G.save_over = 0; G.relbase_valid = 0; } /* this flag is initialized by the operator but overwritten on read. * need to re-enable it here else drivers + registered scripts wont work. */ if (G.f != G_f) { const int flags_keep = (G_SCRIPT_AUTOEXEC | G_SCRIPT_OVERRIDE_PREF); G.f = (G.f & ~flags_keep) | (G_f & flags_keep); } /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); WM_check(C); /* opens window(s), checks keymaps */ if (retval == BKE_READ_FILE_OK_USERPREFS) { /* in case a userdef is read from regular .blend */ wm_init_userdef(C, false); } if (retval != BKE_READ_FILE_FAIL) { if (do_history) { write_history(); } } WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); // refresh_interface_font(); CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); ED_editors_init(C); DAG_on_visible_update(CTX_data_main(C), TRUE); #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ BPY_python_reset(C); #endif /* important to do before NULL'ing the context */ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); if (!G.background) { /* in background mode this makes it hard to load * a blend file and do anything since the screen * won't be set to a valid value again */ CTX_wm_window_set(C, NULL); /* exits queues */ } #if 0 /* gives popups on windows but not linux, bug in report API * but disable for now to stop users getting annoyed */ /* TODO, make this show in header info window */ { Scene *sce; for (sce = G.main->scene.first; sce; sce = sce->id.next) { if (sce->r.engine[0] && BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL) { BKE_reportf(reports, RPT_ERROR, "Engine '%s' not available for scene '%s' " "(an addon may need to be installed or enabled)", sce->r.engine, sce->id.name + 2); } } } #endif BKE_reset_undo(); BKE_write_undo(C, "original"); /* save current state */ } else if (retval == BKE_READ_EXOTIC_OK_OTHER) BKE_write_undo(C, "Import file"); else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) { BKE_reportf(reports, RPT_ERROR, "Cannot read file '%s': %s", filepath, errno ? strerror(errno) : TIP_("unable to open the file")); } else if (retval == BKE_READ_EXOTIC_FAIL_FORMAT) { BKE_reportf(reports, RPT_ERROR, "File format is not supported in file '%s'", filepath); } else if (retval == BKE_READ_EXOTIC_FAIL_PATH) { BKE_reportf(reports, RPT_ERROR, "File path '%s' invalid", filepath); } else { BKE_reportf(reports, RPT_ERROR, "Unknown error loading '%s'", filepath); BLI_assert(!"invalid 'retval'"); } WM_cursor_wait(0); }
/* only called once, for startup */ void WM_init(bContext *C, int argc, const char **argv) { if (!G.background) { wm_ghost_init(C); /* note: it assigns C to ghost! */ wm_init_cursor_data(); } GHOST_CreateSystemPaths(); BKE_addon_pref_type_init(); wm_operatortype_init(); WM_menutype_init(); WM_uilisttype_init(); set_free_windowmanager_cb(wm_close_and_free); /* library.c */ set_free_notifier_reference_cb(WM_main_remove_notifier_reference); /* library.c */ set_blender_test_break_cb(wm_window_testbreak); /* blender.c */ DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */ ED_spacetypes_init(); /* editors/space_api/spacetype.c */ ED_file_init(); /* for fsmenu */ ED_node_init_butfuncs(); BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */ BLF_lang_init(); /* get the default database, plus a wm */ wm_homefile_read(C, NULL, G.factory_startup); BLF_lang_set(NULL); /* note: there is a bug where python needs initializing before loading the * startup.blend because it may contain PyDrivers. It also needs to be after * initializing space types and other internal data. * * However cant redo this at the moment. Solution is to load python * before wm_homefile_read() or make py-drivers check if python is running. * Will try fix when the crash can be repeated. - campbell. */ #ifdef WITH_PYTHON BPY_context_set(C); /* necessary evil */ BPY_python_start(argc, argv); BPY_python_reset(C); #else (void)argc; /* unused */ (void)argv; /* unused */ #endif if (!G.background && !wm_start_with_console) GHOST_toggleConsole(3); wm_init_reports(C); /* reports cant be initialized before the wm */ if (!G.background) { GPU_extensions_init(); GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); GPU_set_anisotropic(U.anisotropic_filter); GPU_set_gpu_mipmapping(U.use_gpu_mipmap); UI_init(); } clear_matcopybuf(); ED_render_clear_mtex_copybuf(); // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ED_preview_init_dbase(); wm_read_history(); /* allow a path of "", this is what happens when making a new file */ #if 0 if (G.main->name[0] == 0) BLI_make_file_string("/", G.main->name, BLI_getDefaultDocumentFolder(), "untitled.blend"); #endif BLI_strncpy(G.lib, G.main->name, FILE_MAX); #ifdef WITH_COMPOSITOR if (1) { extern void *COM_linker_hack; COM_linker_hack = COM_execute; } #endif /* load last session, uses regular file reading so it has to be in end (after init py etc) */ if (U.uiflag2 & USER_KEEP_SESSION) { /* calling WM_recover_last_session(C, NULL) has been moved to creator.c */ /* that prevents loading both the kept session, and the file on the command line */ } else { /* normally 'wm_homefile_read' will do this, * however python is not initialized when called from this function. * * unlikely any handlers are set but its possible, * note that recovering the last session does its own callbacks. */ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); } }