Example #1
0
bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name) {

	String assembly_file = p_assembly_name + ".dll";
	String assembly_src = p_src_dir.plus_file(assembly_file);
	String assembly_dst = p_dst_dir.plus_file(assembly_file);

	if (!FileAccess::exists(assembly_dst) || FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst)) {
		DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);

		String xml_file = p_assembly_name + ".xml";
		if (da->copy(p_src_dir.plus_file(xml_file), p_dst_dir.plus_file(xml_file)) != OK)
			WARN_PRINTS("Failed to copy " + xml_file);

		String pdb_file = p_assembly_name + ".pdb";
		if (da->copy(p_src_dir.plus_file(pdb_file), p_dst_dir.plus_file(pdb_file)) != OK)
			WARN_PRINTS("Failed to copy " + pdb_file);

		Error err = da->copy(assembly_src, assembly_dst);

		memdelete(da);

		if (err != OK) {
			show_build_error_dialog("Failed to copy " API_ASSEMBLY_NAME ".dll");
			return false;
		}
	}

	return true;
}
Example #2
0
	bool _test_path() {

		error->set_text("");
		get_ok()->set_disabled(true);
		DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
		if (project_path->get_text() != "" && d->change_dir(project_path->get_text())!=OK) {
			error->set_text(TTR("Invalid project path, the path must exist!"));
			memdelete(d);
			return false;
		}

		if (mode!=MODE_IMPORT) {

			if (d->file_exists("engine.cfg")) {

				error->set_text(TTR("Invalid project path, engine.cfg must not exist."));
				memdelete(d);
				return false;
			}

		} else {

			if (project_path->get_text() != "" && !d->file_exists("engine.cfg")) {

				error->set_text(TTR("Invalid project path, engine.cfg must exist."));
				memdelete(d);
				return false;
			}
		}

		memdelete(d);
		get_ok()->set_disabled(false);
		return true;

	}
Example #3
0
EditorFileSystem::EditorFileSystem() {

	reimport_on_missing_imported_files = GLOBAL_DEF("editor/reimport_missing_imported_files", true);

	singleton = this;
	filesystem = memnew(EditorFileSystemDirectory); //like, empty
	filesystem->parent = NULL;

	thread = NULL;
	scanning = false;
	importing = false;
	use_threads = true;
	thread_sources = NULL;
	new_filesystem = NULL;

	abort_scan = false;
	scanning_changes = false;
	scanning_changes_done = false;
	ResourceSaver::set_save_callback(_resource_saved);

	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
	if (da->change_dir("res://.import") != OK) {
		da->make_dir("res://.import");
	}
	memdelete(da);

	scan_total = 0;
}
Example #4
0
	NewProjectDialog() {


		VBoxContainer *vb = memnew( VBoxContainer );
		add_child(vb);
		set_child_rect(vb);

		Label* l = memnew(Label);
		l->set_text("Project Path:");
		vb->add_child(l);
		pp=l;

		project_path = memnew( LineEdit );
		MarginContainer *mc = memnew( MarginContainer );
		vb->add_child(mc);
		HBoxContainer *pphb = memnew( HBoxContainer );
		mc->add_child(pphb);
		pphb->add_child(project_path);
		project_path->set_h_size_flags(SIZE_EXPAND_FILL);

		Button* browse = memnew( Button );
		pphb->add_child(browse);
		browse->set_text("Browse");
		browse->connect("pressed", this,"_browse_path");

		l = memnew(Label);
		l->set_text("Project Name:");
		l->set_pos(Point2(5,50));
		vb->add_child(l);
		pn=l;

		project_name = memnew( LineEdit );
		mc = memnew( MarginContainer );
		vb->add_child(mc);
		mc->add_child(project_name);
		project_name->set_text("New Game Project");


		l = memnew(Label);
		l->set_text("That's a BINGO!");
		vb->add_child(l);
		error=l;
		l->add_color_override("font_color",Color(1,0.4,0.3,0.8));
		l->set_align(Label::ALIGN_CENTER);

		get_ok()->set_text("Create");
		DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
		project_path->set_text(d->get_current_dir());
		memdelete(d);

		fdialog = memnew( FileDialog );
		add_child(fdialog);
		fdialog->set_access(FileDialog::ACCESS_FILESYSTEM);
		project_name->connect("text_changed", this,"_text_changed");
		project_path->connect("text_changed", this,"_path_text_changed");
		fdialog->connect("dir_selected", this,"_path_selected");
		fdialog->connect("file_selected", this,"_file_selected");
		set_hide_on_ok(false);
		import_mode=false;
	}
void EditorAssetLibraryItemDownload::_close() {

	DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	da->remove(download->get_download_file()); //clean up removed file
	memdelete(da);
	queue_delete();
}
Example #6
0
void RotatedFileLogger::rotate_file() {
	close_file();

	if (FileAccess::exists(base_path)) {
		if (max_files > 1) {
			char timestamp[21];
			OS::Date date = OS::get_singleton()->get_date();
			OS::Time time = OS::get_singleton()->get_time();
			sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day, time.hour, time.min, time.sec);

			String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension();

			DirAccess *da = DirAccess::open(base_path.get_base_dir());
			if (da) {
				da->copy(base_path, backup_name);
				memdelete(da);
			}
			clear_old_backups();
		}
	} else {
		DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA);
		if (da) {
			da->make_dir_recursive(base_path.get_base_dir());
			memdelete(da);
		}
	}

	file = FileAccess::open(base_path, FileAccess::WRITE);
}
Example #7
0
bool DirAccess::exists(String p_dir) {

	DirAccess *da = DirAccess::create_for_path(p_dir);
	bool valid = da->change_dir(p_dir) == OK;
	memdelete(da);
	return valid;
}
Example #8
0
	bool _test_path() {

		error->set_text("");
		get_ok()->set_disabled(true);
		DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
		if (d->change_dir(project_path->get_text())!=OK) {
			error->set_text("Invalid Path for Project, Path Must Exist!");
			memdelete(d);
			return false;
		}

		if (!import_mode) {

			if (d->file_exists("engine.cfg")) {

				error->set_text("Invalid Project Path (engine.cfg must not exist).");
				memdelete(d);
				return false;
			}

		} else {

			if (!d->file_exists("engine.cfg")) {

				error->set_text("Invalid Project Path (engine.cfg must exist).");
				memdelete(d);
				return false;
			}
		}

		memdelete(d);
		get_ok()->set_disabled(false);
		return true;

	}
void ExportTemplateManager::_uninstall_template_confirm() {

	DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	Error err = d->change_dir(EditorSettings::get_singleton()->get_templates_dir());

	ERR_FAIL_COND(err != OK);

	err = d->change_dir(to_remove);

	ERR_FAIL_COND(err != OK);

	Vector<String> files;

	d->list_dir_begin();

	bool isdir;
	String c = d->get_next(&isdir);
	while (c != String()) {
		if (!isdir) {
			files.push_back(c);
		}
		c = d->get_next(&isdir);
	}

	d->list_dir_end();

	for (int i = 0; i < files.size(); i++) {
		d->remove(files[i]);
	}

	d->change_dir("..");
	d->remove(to_remove);

	_update_template_list();
}
Example #10
0
void FindInFiles::_scan_dir(String path, PoolStringArray &out_folders) {

	DirAccess *dir = DirAccess::open(path);
	if (dir == NULL) {
		print_line("Cannot open directory! " + path);
		return;
	}

	dir->list_dir_begin();

	for (int i = 0; i < 1000; ++i) {
		String file = dir->get_next();

		if (file == "")
			break;

		// Ignore special dirs and hidden dirs (such as .git and .import)
		if (file == "." || file == ".." || file.begins_with("."))
			continue;

		if (dir->current_is_dir())
			out_folders.append(file);

		else {
			String file_ext = file.get_extension();
			if (_extension_filter.has(file_ext)) {
				_files_to_scan.push_back(path.plus_file(file));
			}
		}
	}
}
Example #11
0
void OSIPhone::set_data_dir(String p_dir) {

	DirAccess *da = DirAccess::open(p_dir);

	data_dir = da->get_current_dir();
	printf("setting data dir to %ls from %ls\n", data_dir.c_str(), p_dir.c_str());
	memdelete(da);
};
Example #12
0
void OSIPhone::set_data_dir(String p_dir) {

	DirAccess* da = DirAccess::open(p_dir);

	data_dir = da->get_current_dir();

	memdelete(da);
};
Example #13
0
// scan localpath, add or update child nodes, call recursively for folder nodes
// localpath must be prefixed with Sync
bool Sync::scan(string* localpath, FileAccess* fa)
{
	if (localpath->size() < localdebris.size()
		|| memcmp(localpath->data(), localdebris.data(), localdebris.size())
		|| (localpath->size() != localdebris.size()
			&& memcmp(localpath->data() + localdebris.size(),
					  client->fsaccess->localseparator.data(),
					  client->fsaccess->localseparator.size())))
	{
		DirAccess* da;
		string localname, name;
		bool success;

		da = client->fsaccess->newdiraccess();

		// scan the dir, mark all items with a unique identifier
		if ((success = da->dopen(localpath, fa, false)))
		{
			size_t t = localpath->size();

			while (da->dnext(&localname))
			{
				name = localname;
				client->fsaccess->local2name(&name);

				// check if this record is to be ignored
				if (client->app->sync_syncable(name.c_str(), localpath, &localname))
				{
					if (t)
					{
						localpath->append(client->fsaccess->localseparator);
					}

					localpath->append(localname);

					// skip the sync's debris folder
					if ((localpath->size() < localdebris.size())
						|| memcmp(localpath->data(), localdebris.data(), localdebris.size())
						|| ((localpath->size() != localdebris.size())
							&& memcmp(localpath->data() + localdebris.size(),
									  client->fsaccess->localseparator.data(),
									  client->fsaccess->localseparator.size())))
					{
						// new or existing record: place scan result in notification queue
						dirnotify->notify(DirNotify::DIREVENTS, NULL, localpath->data(), localpath->size(), true);
					}

					localpath->resize(t);
				}
			}
		}

		delete da;

		return success;
	}
	else return false;
}
Example #14
0
void PluginConfigDialog::_on_confirmed() {

	String path = "res://addons/" + subfolder_edit->get_text();

	if (!_edit_mode) {
		DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
		if (!d || d->make_dir_recursive(path) != OK)
			return;
	}

	Ref<ConfigFile> cf = memnew(ConfigFile);
	cf->set_value("plugin", "name", name_edit->get_text());
	cf->set_value("plugin", "description", desc_edit->get_text());
	cf->set_value("plugin", "author", author_edit->get_text());
	cf->set_value("plugin", "version", version_edit->get_text());
	cf->set_value("plugin", "script", script_edit->get_text());

	cf->save(path.plus_file("plugin.cfg"));

	if (!_edit_mode) {
		int lang_idx = script_option_edit->get_selected();
		String lang_name = ScriptServer::get_language(lang_idx)->get_name();

		Ref<Script> script;

		// TODO Use script templates. Right now, this code won't add the 'tool' annotation to other languages.
		// TODO Better support script languages with named classes (has_named_classes).

		if (lang_name == GDScriptLanguage::get_singleton()->get_name()) {
			// Hard-coded GDScript template to keep usability until we use script templates.
			Ref<GDScript> gdscript = memnew(GDScript);
			gdscript->set_source_code(
					"tool\n"
					"extends EditorPlugin\n"
					"\n"
					"func _enter_tree():\n"
					"\tpass\n"
					"\n"
					"func _exit_tree():\n"
					"\tpass\n");
			String script_path = path.plus_file(script_edit->get_text());
			gdscript->set_path(script_path);
			ResourceSaver::save(script_path, gdscript);
			script = gdscript;
		} else {
			String script_path = path.plus_file(script_edit->get_text());
			String class_name = script_path.get_file().get_basename();
			script = ScriptServer::get_language(lang_idx)->get_template(class_name, "EditorPlugin");
			script->set_path(script_path);
			ResourceSaver::save(script_path, script);
		}

		emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? subfolder_edit->get_text() : "");
	} else {
		EditorNode::get_singleton()->get_project_settings()->update_plugins();
	}
	_clear_fields();
}
Example #15
0
String DirAccess::get_full_path(const String &p_path, AccessType p_access) {

	DirAccess *d = DirAccess::create(p_access);
	if (!d)
		return p_path;

	d->change_dir(p_path);
	String full = d->get_current_dir();
	memdelete(d);
	return full;
}
void OrphanResourcesDialog::_delete_confirm() {

	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
	for (List<String>::Element *E=paths.front();E;E=E->next()) {

		da->remove(E->get());
		EditorFileSystem::get_singleton()->update_file(E->get());
	}
	memdelete(da);
	refresh();
}
Example #17
0
void EditorFileSystem::_delete_internal_files(String p_file) {
	if (FileAccess::exists(p_file + ".import")) {
		List<String> paths;
		ResourceFormatImporter::get_singleton()->get_internal_resource_path_list(p_file, &paths);
		DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
		for (List<String>::Element *E = paths.front(); E; E = E->next()) {
			da->remove(E->get());
		}
		da->remove(p_file + ".import");
		memdelete(da);
	}
}
Example #18
0
void ScenesDock::_go_to_dir(const String& p_dir){

	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
	if (da->change_dir(p_dir)==OK) {
		path=da->get_current_dir();
		_update_files(false);
	}
	current_path->set_text(path);
	memdelete(da);


}
void DependencyRemoveDialog::ok_pressed() {


	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
	for (Map<String,TreeItem*>::Element *E=files.front();E;E=E->next()) {

		da->remove(E->key());
		EditorFileSystem::get_singleton()->update_file(E->key());
	}
	memdelete(da);

}
Example #20
0
String ProjectSettings::localize_path(const String &p_path) const {

	if (resource_path == "")
		return p_path; //not initialized yet

	if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
			(p_path.is_abs_path() && !p_path.begins_with(resource_path)))
		return p_path.simplify_path();

	DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);

	String path = p_path.replace("\\", "/").simplify_path();

	if (dir->change_dir(path) == OK) {

		String cwd = dir->get_current_dir();
		cwd = cwd.replace("\\", "/");

		memdelete(dir);

		// Ensure that we end with a '/'.
		// This is important to ensure that we do not wrongly localize the resource path
		// in an absolute path that just happens to contain this string but points to a
		// different folder (e.g. "/my/project" as resource_path would be contained in
		// "/my/project_data", even though the latter is not part of res://.
		// `plus_file("")` is an easy way to ensure we have a trailing '/'.
		const String res_path = resource_path.plus_file("");

		if (!cwd.begins_with(res_path)) {
			return p_path;
		};

		return cwd.replace_first(res_path, "res://");
	} else {

		memdelete(dir);

		int sep = path.find_last("/");
		if (sep == -1) {
			return "res://" + path;
		};

		String parent = path.substr(0, sep);

		String plocal = localize_path(parent);
		if (plocal == "") {
			return "";
		};
		return plocal + path.substr(sep, path.size() - sep);
	};
}
Example #21
0
DirAccess *DirAccess::open(const String &p_path, Error *r_error) {

	DirAccess *da = create_for_path(p_path);

	ERR_FAIL_COND_V(!da, NULL);
	Error err = da->change_dir(p_path);
	if (r_error)
		*r_error = err;
	if (err != OK) {
		memdelete(da);
		return NULL;
	}

	return da;
}
Example #22
0
String Globals::localize_path(const String& p_path) const {

	if (resource_path=="")
		return p_path; //not initialied yet

	if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
		(p_path.is_abs_path() && !p_path.begins_with(resource_path)))
		return p_path.simplify_path();


	DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);

	String path = p_path.replace("\\","/").simplify_path();

	if (dir->change_dir(path)==OK) {

		String cwd = dir->get_current_dir();
		cwd = cwd.replace("\\","/");

		memdelete(dir);

		if (!cwd.begins_with(resource_path)) {
			return p_path;
		};

		return cwd.replace_first(resource_path, "res:/");
	} else {

		memdelete(dir);

		int sep = path.find_last("/");
		if (sep == -1) {
			return "res://"+path;
		};


		String parent = path.substr(0, sep);

		String plocal = localize_path(parent);
		if (plocal == "") {
			return "";
		};
		return plocal + path.substr(sep, path.size() - sep);
	};

}
Example #23
0
void RotatedFileLogger::clear_old_backups() {
	int max_backups = max_files - 1; // -1 for the current file

	String basename = base_path.get_file().get_basename();
	String extension = "." + base_path.get_extension();

	DirAccess *da = DirAccess::open(base_path.get_base_dir());
	if (!da) {
		return;
	}

	da->list_dir_begin();
	String f = da->get_next();
	Set<String> backups;
	while (f != String()) {
		if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path.get_file()) {
			backups.insert(f);
		}
		f = da->get_next();
	}
	da->list_dir_end();

	if (backups.size() > max_backups) {
		// since backups are appended with timestamp and Set iterates them in sorted order,
		// first backups are the oldest
		int to_delete = backups.size() - max_backups;
		for (Set<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) {
			da->remove(E->get());
		}
	}

	memdelete(da);
}
Example #24
0
bool PowerX11::GetPowerInfo_Linux_proc_acpi() {
	String node;
	DirAccess *dirp = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	bool have_battery = false;
	bool have_ac = false;
	bool charging = false;

	this->nsecs_left = -1;
	this->percent_left = -1;
	this->power_state = OS::POWERSTATE_UNKNOWN;

	dirp->change_dir(proc_acpi_battery_path);
	Error err = dirp->list_dir_begin();

	if (err != OK) {
		return false; /* can't use this interface. */
	} else {
		node = dirp->get_next();
		while (node != "") {
			check_proc_acpi_battery(node.utf8().get_data(), &have_battery, &charging /*, seconds, percent*/);
			node = dirp->get_next();
		}
		memdelete(dirp);
	}

	dirp->change_dir(proc_acpi_ac_adapter_path);
	err = dirp->list_dir_begin();
	if (err != OK) {
		return false; /* can't use this interface. */
	} else {
		node = dirp->get_next();
		while (node != "") {
			check_proc_acpi_ac_adapter(node.utf8().get_data(), &have_ac);
			node = dirp->get_next();
		}
		memdelete(dirp);
	}

	if (!have_battery) {
		this->power_state = OS::POWERSTATE_NO_BATTERY;
	} else if (charging) {
		this->power_state = OS::POWERSTATE_CHARGING;
	} else if (have_ac) {
		this->power_state = OS::POWERSTATE_CHARGED;
	} else {
		this->power_state = OS::POWERSTATE_ON_BATTERY;
	}

	return true; /* definitive answer. */
}
Example #25
0
void ProjectManager::_scan_begin(const String& p_base) {

	print_line("SCAN PROJECTS AT: "+p_base);
	List<String> projects;
	DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	da->change_dir(p_base);
	_scan_dir(da,0,1,&projects);
	memdelete(da);
	print_line("found: "+itos(projects.size())+" projects.");

	for(List<String>::Element *E=projects.front();E;E=E->next()) {
		String proj=E->get().replace("/","::");
		EditorSettings::get_singleton()->set("projects/"+proj,E->get());

	}
	EditorSettings::get_singleton()->save();
	_load_recent_projects();

}
Example #26
0
void DependencyRemoveDialog::ok_pressed() {

	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
	for (Map<String, TreeItem *>::Element *E = files.front(); E; E = E->next()) {
		if (da->dir_exists(E->key())) {
			String path = OS::get_singleton()->get_resource_dir() + E->key().replace_first("res://", "/");
			OS::get_singleton()->move_path_to_trash(path);
			EditorFileSystem::get_singleton()->scan();
		} else {
			if (ResourceCache::has(E->key())) {
				Resource *res = ResourceCache::get(E->key());
				res->set_path(""); //clear reference to path
			}
			da->remove(E->key());
			EditorFileSystem::get_singleton()->update_file(E->key());
		}
	}
	memdelete(da);
}
Example #27
0
	String _test_path() {

		error->set_text("");
		get_ok()->set_disabled(true);
		DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
		String valid_path;
		if (d->change_dir(project_path->get_text())==OK){
			valid_path=project_path->get_text();
		} else if (d->change_dir(project_path->get_text().strip_edges())==OK) {
			valid_path=project_path->get_text().strip_edges();
		}

		if (valid_path == "") {
			error->set_text(TTR("Invalid project path, the path must exist!"));
			memdelete(d);
			return "";
		}

		if (mode!=MODE_IMPORT) {

			if (d->file_exists("godot.cfg")) {

				error->set_text(TTR("Invalid project path, godot.cfg must not exist."));
				memdelete(d);
				return "";
			}

		} else {

			if (valid_path != "" && !d->file_exists("godot.cfg")) {

				error->set_text(TTR("Invalid project path, godot.cfg must exist."));
				memdelete(d);
				return "";
			}
		}

		memdelete(d);
		get_ok()->set_disabled(false);
		return valid_path;

	}
Example #28
0
void ProjectManager::_files_dropped(StringArray p_files, int p_screen) {
	Set<String> folders_set;
	DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	for (int i = 0; i < p_files.size(); i++) {
		String file = p_files[i];
		folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir());
	}
	memdelete(da);
	if (folders_set.size()>0) {
		StringArray folders;
		for (Set<String>::Element *E=folders_set.front();E;E=E->next()) {
			folders.append(E->get());
		}

		bool confirm = true;
		if (folders.size()==1) {
			DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
			if (dir->change_dir(folders[0])==OK) {
				dir->list_dir_begin();
				String file = dir->get_next();
				while(confirm && file!=String()) {
					if (!da->current_is_dir() && file.ends_with("engine.cfg")) {
						confirm = false;
					}
					file = dir->get_next();
				}
				dir->list_dir_end();
			}
			memdelete(dir);
		}
		if (confirm) {
			multi_scan_ask->get_ok()->disconnect("pressed", this, "_scan_multiple_folders");
			multi_scan_ask->get_ok()->connect("pressed", this, "_scan_multiple_folders", varray(folders));
			multi_scan_ask->set_text(vformat(TTR("You are about the scan %s folders for existing Godot projects. Do you confirm?"), folders.size()));
			multi_scan_ask->popup_centered_minsize();
		} else {
			_scan_multiple_folders(folders);
		}
	}
}
Example #29
0
MainLoop *test() {

	print_line("this is test io");
	DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	da->change_dir(".");
	print_line("Opening current dir " + da->get_current_dir());
	String entry;
	da->list_dir_begin();
	while ((entry = da->get_next()) != "") {

		print_line("entry " + entry + " is dir: " + Variant(da->current_is_dir()));
	};
	da->list_dir_end();

	RES texture = ResourceLoader::load("test_data/rock.png");
	ERR_FAIL_COND_V(texture.is_null(), NULL);

	ResourceSaver::save("test_data/rock.xml", texture);

	print_line("localize paths");
	print_line(ProjectSettings::get_singleton()->localize_path("algo.xml"));
	print_line(ProjectSettings::get_singleton()->localize_path("c:\\windows\\algo.xml"));
	print_line(ProjectSettings::get_singleton()->localize_path(ProjectSettings::get_singleton()->get_resource_path() + "/something/something.xml"));
	print_line(ProjectSettings::get_singleton()->localize_path("somedir/algo.xml"));

	{

		FileAccess *z = FileAccess::open("test_data/archive.zip", FileAccess::READ);
		int len = z->get_len();
		Vector<uint8_t> zip;
		zip.resize(len);
		z->get_buffer(&zip[0], len);
		z->close();
		memdelete(z);

		FileAccessMemory::register_file("a_package", zip);
		FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_RESOURCES);
		FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_FILESYSTEM);
		FileAccess::make_default<FileAccessMemory>(FileAccess::ACCESS_USERDATA);

		print_line("archive test");
	};

	print_line("test done");

	return memnew(TestMainLoop);
}
void ExportTemplateManager::_update_template_list() {

	while (current_hb->get_child_count()) {
		memdelete(current_hb->get_child(0));
	}

	while (installed_vb->get_child_count()) {
		memdelete(installed_vb->get_child(0));
	}

	DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	Error err = d->change_dir(EditorSettings::get_singleton()->get_templates_dir());

	d->list_dir_begin();
	Set<String> templates;

	if (err == OK) {

		bool isdir;
		String c = d->get_next(&isdir);
		while (c != String()) {
			if (isdir && !c.begins_with(".")) {
				templates.insert(c);
			}
			c = d->get_next(&isdir);
		}
	}
	d->list_dir_end();

	memdelete(d);

	String current_version = VERSION_FULL_CONFIG;

	Label *current = memnew(Label);
	current->set_h_size_flags(SIZE_EXPAND_FILL);
	current_hb->add_child(current);

	if (templates.has(current_version)) {
		current->add_color_override("font_color", get_color("success_color", "Editor"));
		Button *redownload = memnew(Button);
		redownload->set_text(TTR("Re-Download"));
		current_hb->add_child(redownload);
		redownload->connect("pressed", this, "_download_template", varray(current_version));

		Button *uninstall = memnew(Button);
		uninstall->set_text(TTR("Uninstall"));
		current_hb->add_child(uninstall);
		current->set_text(current_version + " " + TTR("(Installed)"));
		uninstall->connect("pressed", this, "_uninstall_template", varray(current_version));

	} else {
		current->add_color_override("font_color", get_color("error_color", "Editor"));
		Button *redownload = memnew(Button);
		redownload->set_text(TTR("Download"));
		redownload->connect("pressed", this, "_download_template", varray(current_version));
		current_hb->add_child(redownload);
		current->set_text(current_version + " " + TTR("(Missing)"));
	}

	for (Set<String>::Element *E = templates.back(); E; E = E->prev()) {

		HBoxContainer *hbc = memnew(HBoxContainer);
		Label *version = memnew(Label);
		version->set_modulate(get_color("disabled_font_color", "Editor"));
		String text = E->get();
		if (text == current_version) {
			text += " " + TTR("(Current)");
		}
		version->set_text(text);
		version->set_h_size_flags(SIZE_EXPAND_FILL);
		hbc->add_child(version);

		Button *uninstall = memnew(Button);

		uninstall->set_text(TTR("Uninstall"));
		hbc->add_child(uninstall);
		uninstall->connect("pressed", this, "_uninstall_template", varray(E->get()));

		installed_vb->add_child(hbc);
	}
}