Beispiel #1
0
/* 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;
}
Beispiel #2
0
/**
 * 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 */
	}
}
Beispiel #3
0
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);

}
Beispiel #4
0
/* op can be NULL */
int WM_read_homefile(bContext *C, ReportList *UNUSED(reports), short from_memory)
{
	ListBase wmbase;
	char tstr[FILE_MAX];
	int success = 0;
	
	free_ttfont(); /* still weird... what does it here? */
		
	G.relbase_valid = 0;
	if (!from_memory) {
		char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
		if (cfgdir) {
			BLI_make_file_string(G.main->name, tstr, cfgdir, BLENDER_STARTUP_FILE);
		}
		else {
			tstr[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 && BLI_exists(tstr)) {
		success = (BKE_read_file(C, tstr, NULL) != BKE_READ_FILE_FAIL);
		
		if (U.themes.first == NULL) {
			printf("\nError: No valid "STRINGIFY (BLENDER_STARTUP_FILE)", fall back to built-in default.\n\n");
			success = 0;
		}
	}
	if (success == 0) {
		success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL);
		if (wmbase.first == NULL) wm_clear_default_size(C);

#ifdef WITH_PYTHON_SECURITY /* not default */
		/* 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
	}
	
	/* 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);
	
	/* 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... */
//	mainwindow_set_filename_to_title("");	// empty string re-initializes title to "Blender"
	
//	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_driver_reset();
		BPY_app_handlers_reset(FALSE);
		BPY_modules_load_user(C);
	}
#endif

	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;
}
Beispiel #5
0
static int view3d_layers_exec(bContext *C, wmOperator *op)
{
	Scene *scene= CTX_data_scene(C);
	ScrArea *sa= CTX_wm_area(C);
	View3D *v3d= sa->spacedata.first;
	int nr= RNA_int_get(op->ptr, "nr");
	int toggle= RNA_boolean_get(op->ptr, "toggle");
	
	if(nr < 0)
		return OPERATOR_CANCELLED;

	if(nr == 0) {
		/* all layers */
		if(!v3d->layact)
			v3d->layact= 1;

		if (toggle && v3d->lay == ((1<<20)-1)) {
			/* return to active layer only */
			v3d->lay = v3d->layact;

			view3d_layers_editmode_ensure(scene, v3d);
		}
		else {
			v3d->lay |= (1<<20)-1;
		}		
	}
	else {
		int bit;
		nr--;

		if(RNA_boolean_get(op->ptr, "extend")) {
			if(toggle && v3d->lay & (1<<nr) && (v3d->lay & ~(1<<nr)))
				v3d->lay &= ~(1<<nr);
			else
				v3d->lay |= (1<<nr);
		} else {
			v3d->lay = (1<<nr);
		}

		view3d_layers_editmode_ensure(scene, v3d);

		/* set active layer, ensure to always have one */
		if(v3d->lay & (1<<nr))
		   v3d->layact= 1<<nr;
		else if((v3d->lay & v3d->layact)==0) {
			for(bit=0; bit<32; bit++) {
				if(v3d->lay & (1<<bit)) {
					v3d->layact= 1<<bit;
					break;
				}
			}
		}
	}
	
	if(v3d->scenelock) handle_view3d_lock(C);
	
	DAG_on_visible_update(CTX_data_main(C), FALSE);

	ED_area_tag_redraw(sa);
	
	return OPERATOR_FINISHED;
}
Beispiel #6
0
static void render_endjob(void *rjv)
{
	RenderJob *rj = rjv;

	/* this render may be used again by the sequencer without the active 'Render' where the callbacks
	 * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
	RE_InitRenderCB(rj->re);

	if (rj->main != G.main)
		BKE_main_free(rj->main);

	/* else the frame will not update for the original value */
	if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
		/* possible this fails of loading new file while rendering */
		if (G.main->wm.first) {
			ED_update_for_newframe(G.main, rj->scene, 1);
		}
	}
	
	/* XXX above function sets all tags in nodes */
	ntreeCompositClearTags(rj->scene->nodetree);
	
	/* potentially set by caller */
	rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
	
	if (rj->srl) {
		nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
		WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
	}

	if (rj->sa) {
		render_image_restore_layer(rj);
	}

	/* XXX render stability hack */
	G.is_rendering = false;
	WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL);

	/* Partial render result will always update display buffer
	 * for first render layer only. This is nice because you'll
	 * see render progress during rendering, but it ends up in
	 * wrong display buffer shown after rendering.
	 *
	 * The code below will mark display buffer as invalid after
	 * rendering in case multiple layers were rendered, which
	 * ensures display buffer matches render layer after
	 * rendering.
	 *
	 * Perhaps proper way would be to toggle active render
	 * layer in image editor and job, so we always display
	 * layer being currently rendered. But this is not so much
	 * trivial at this moment, especially because of external
	 * engine API, so lets use simple and robust way for now
	 *                                          - sergey -
	 */
	if (rj->scene->r.layers.first != rj->scene->r.layers.last ||
	    rj->image_outdated)
	{
		void *lock;
		Image *ima = rj->image;
		ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);

		if (ibuf)
			ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;

		BKE_image_release_ibuf(ima, ibuf, lock);
	}

	/* Finally unlock the user interface (if it was locked). */
	if (rj->interface_locked) {
		Scene *scene;

		/* Interface was locked, so window manager couldn't have been changed
		 * and using one from Global will unlock exactly the same manager as
		 * was locked before running the job.
		 */
		WM_set_locked_interface(G.main->wm.first, false);

		/* We've freed all the derived caches before rendering, which is
		 * effectively the same as if we re-loaded the file.
		 *
		 * So let's not try being smart here and just reset all updated
		 * scene layers and use generic DAG_on_visible_update.
		 */
		for (scene = G.main->scene.first; scene; scene = scene->id.next) {
			scene->lay_updated = 0;
		}

		DAG_on_visible_update(G.main, false);
	}
}
Beispiel #7
0
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;

		BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);

		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);
			Main *bmain = CTX_data_main(C);

			/* special case, 2.4x files */
			if (wm == NULL && BLI_listbase_is_empty(&bmain->wm)) {
				extern void wm_add_default(bContext *C);

				/* wm_add_default() needs the screen to be set. */
				CTX_wm_screen_set(C, bmain->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 */

			/* WM_file_read would call normally */
			ED_editors_init(C);
			DAG_on_visible_update(bmain, true);
			BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
		}
		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

		BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);

		/* 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;
}