Selaa lähdekoodia

Merge pull request #12988 from akien-mga/xdg-home-paths

Add support for XDG Base Directory spec
Rémi Verschelde 8 vuotta sitten
vanhempi
commit
ecf80fbbba
49 muutettua tiedostoa jossa 493 lisäystä ja 257 poistoa
  1. 3 3
      core/bind/core_bind.cpp
  2. 1 1
      core/bind/core_bind.h
  3. 2 2
      core/os/dir_access.cpp
  4. 1 1
      core/os/file_access.cpp
  5. 45 13
      core/os/os.cpp
  6. 10 5
      core/os/os.h
  7. 1 1
      core/project_settings.cpp
  8. 2 2
      doc/classes/EditorSettings.xml
  9. 2 2
      doc/classes/OS.xml
  10. 0 10
      drivers/unix/SCsub
  11. 8 19
      drivers/unix/os_unix.cpp
  12. 1 6
      drivers/unix/os_unix.h
  13. 4 4
      editor/create_dialog.cpp
  14. 8 23
      editor/editor_export.cpp
  15. 4 4
      editor/editor_file_system.cpp
  16. 11 11
      editor/editor_node.cpp
  17. 1 1
      editor/editor_resource_preview.cpp
  18. 147 70
      editor/editor_settings.cpp
  19. 12 4
      editor/editor_settings.h
  20. 5 4
      editor/export_template_manager.cpp
  21. 4 4
      editor/plugins/asset_library_editor_plugin.cpp
  22. 1 1
      editor/plugins/editor_preview_plugins.cpp
  23. 1 1
      editor/plugins/script_editor_plugin.cpp
  24. 3 3
      editor/pvrtc_compress.cpp
  25. 1 1
      editor/script_create_dialog.cpp
  26. 1 1
      modules/enet/networked_multiplayer_enet.cpp
  27. 3 9
      modules/mono/godotsharp_dirs.cpp
  28. 2 2
      platform/android/export/export.cpp
  29. 2 2
      platform/android/java_glue.cpp
  30. 5 6
      platform/android/os_android.cpp
  31. 4 4
      platform/android/os_android.h
  32. 33 0
      platform/haiku/os_haiku.cpp
  33. 4 0
      platform/haiku/os_haiku.h
  34. 3 3
      platform/iphone/os_iphone.cpp
  35. 1 1
      platform/iphone/os_iphone.h
  36. 1 1
      platform/javascript/export/export.cpp
  37. 5 5
      platform/javascript/os_javascript.cpp
  38. 4 4
      platform/javascript/os_javascript.h
  39. 3 3
      platform/osx/export/export.cpp
  40. 5 0
      platform/osx/os_osx.h
  41. 39 1
      platform/osx/os_osx.mm
  42. 1 1
      platform/server/os_server.cpp
  43. 3 3
      platform/uwp/export/export.cpp
  44. 3 2
      platform/uwp/os_uwp.cpp
  45. 1 1
      platform/uwp/os_uwp.h
  46. 47 10
      platform/windows/os_windows.cpp
  47. 7 1
      platform/windows/os_windows.h
  48. 34 1
      platform/x11/os_x11.cpp
  49. 4 0
      platform/x11/os_x11.h

+ 3 - 3
core/bind/core_bind.cpp

@@ -888,9 +888,9 @@ void _OS::dump_resources_to_file(const String &p_file) {
 	OS::get_singleton()->dump_resources_to_file(p_file.utf8().get_data());
 }
 
-String _OS::get_data_dir() const {
+String _OS::get_user_data_dir() const {
 
-	return OS::get_singleton()->get_data_dir();
+	return OS::get_singleton()->get_user_data_dir();
 };
 
 Error _OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) {
@@ -1088,7 +1088,7 @@ void _OS::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &_OS::get_static_memory_peak_usage);
 	ClassDB::bind_method(D_METHOD("get_dynamic_memory_usage"), &_OS::get_dynamic_memory_usage);
 
-	ClassDB::bind_method(D_METHOD("get_data_dir"), &_OS::get_data_dir);
+	ClassDB::bind_method(D_METHOD("get_user_data_dir"), &_OS::get_user_data_dir);
 	ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir);
 	ClassDB::bind_method(D_METHOD("get_unique_id"), &_OS::get_unique_id);
 

+ 1 - 1
core/bind/core_bind.h

@@ -297,7 +297,7 @@ public:
 
 	String get_system_dir(SystemDir p_dir) const;
 
-	String get_data_dir() const;
+	String get_user_data_dir() const;
 
 	void alert(const String &p_alert, const String &p_title = "ALERT!");
 

+ 2 - 2
core/os/dir_access.cpp

@@ -38,7 +38,7 @@ String DirAccess::_get_root_path() const {
 	switch (_access_type) {
 
 		case ACCESS_RESOURCES: return ProjectSettings::get_singleton()->get_resource_path();
-		case ACCESS_USERDATA: return OS::get_singleton()->get_data_dir();
+		case ACCESS_USERDATA: return OS::get_singleton()->get_user_data_dir();
 		default: return "";
 	}
 
@@ -217,7 +217,7 @@ String DirAccess::fix_path(String p_path) const {
 
 			if (p_path.begins_with("user://")) {
 
-				String data_dir = OS::get_singleton()->get_data_dir();
+				String data_dir = OS::get_singleton()->get_user_data_dir();
 				if (data_dir != "") {
 
 					return p_path.replace_first("user:/", data_dir);

+ 1 - 1
core/os/file_access.cpp

@@ -152,7 +152,7 @@ String FileAccess::fix_path(const String &p_path) const {
 
 			if (r_path.begins_with("user://")) {
 
-				String data_dir = OS::get_singleton()->get_data_dir();
+				String data_dir = OS::get_singleton()->get_user_data_dir();
 				if (data_dir != "") {
 
 					return r_path.replace("user:/", data_dir);

+ 45 - 13
core/os/os.cpp

@@ -33,6 +33,7 @@
 #include "input.h"
 #include "os/file_access.h"
 #include "project_settings.h"
+#include "version_generated.gen.h"
 
 #include <stdarg.h>
 
@@ -262,16 +263,7 @@ String OS::get_locale() const {
 	return "en";
 }
 
-String OS::get_resource_dir() const {
-
-	return ProjectSettings::get_singleton()->get_resource_path();
-}
-
-String OS::get_system_dir(SystemDir p_dir) const {
-
-	return ".";
-}
-
+// Helper function used by OS_Unix and OS_Windows
 String OS::get_safe_application_name() const {
 	String an = ProjectSettings::get_singleton()->get("application/config/name");
 	Vector<String> invalid_char = String("\\ / : * ? \" < > |").split(" ");
@@ -281,11 +273,51 @@ String OS::get_safe_application_name() const {
 	return an;
 }
 
-String OS::get_data_dir() const {
+// Path to data, config, cache, etc. OS-specific folders
+
+// Get properly capitalized engine name for system paths
+String OS::get_godot_dir_name() const {
+
+	// Default to lowercase, so only override when different case is needed
+	return String(_MKSTR(VERSION_SHORT_NAME)).to_lower();
+}
+
+// OS equivalent of XDG_DATA_HOME
+String OS::get_data_path() const {
+
+	return ".";
+}
+
+// OS equivalent of XDG_CONFIG_HOME
+String OS::get_config_path() const {
+
+	return ".";
+}
+
+// OS equivalent of XDG_CACHE_HOME
+String OS::get_cache_path() const {
+
+	return ".";
+}
+
+// OS specific path for user://
+String OS::get_user_data_dir() const {
 
 	return ".";
 };
 
+// Absolute path to res://
+String OS::get_resource_dir() const {
+
+	return ProjectSettings::get_singleton()->get_resource_path();
+}
+
+// Access system-specific dirs like Documents, Downloads, etc.
+String OS::get_system_dir(SystemDir p_dir) const {
+
+	return ".";
+}
+
 Error OS::shell_open(String p_uri) {
 	return ERR_UNAVAILABLE;
 };
@@ -374,9 +406,9 @@ OS::ScreenOrientation OS::get_screen_orientation() const {
 	return (OS::ScreenOrientation)_orientation;
 }
 
-void OS::_ensure_data_dir() {
+void OS::_ensure_user_data_dir() {
 
-	String dd = get_data_dir();
+	String dd = get_user_data_dir();
 	DirAccess *da = DirAccess::open(dd);
 	if (da) {
 		memdelete(da);

+ 10 - 5
core/os/os.h

@@ -124,7 +124,7 @@ protected:
 
 	virtual void set_cmdline(const char *p_execpath, const List<String> &p_args);
 
-	void _ensure_data_dir();
+	void _ensure_user_data_dir();
 	virtual bool _check_internal_feature_support(const String &p_feature) = 0;
 
 public:
@@ -200,7 +200,6 @@ public:
 	virtual void set_low_processor_usage_mode(bool p_enabled);
 	virtual bool is_in_low_processor_usage_mode() const;
 
-	virtual String get_installed_templates_path() const { return ""; }
 	virtual String get_executable_path() const;
 	virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false) = 0;
 	virtual Error kill(const ProcessID &p_pid) = 0;
@@ -334,10 +333,14 @@ public:
 	virtual String get_locale() const;
 
 	String get_safe_application_name() const;
-	virtual String get_data_dir() const;
-	virtual String get_resource_dir() const;
+	virtual String get_godot_dir_name() const;
 
-	virtual Error move_to_trash(const String &p_path) { return FAILED; }
+	virtual String get_data_path() const;
+	virtual String get_config_path() const;
+	virtual String get_cache_path() const;
+
+	virtual String get_user_data_dir() const;
+	virtual String get_resource_dir() const;
 
 	enum SystemDir {
 		SYSTEM_DIR_DESKTOP,
@@ -352,6 +355,8 @@ public:
 
 	virtual String get_system_dir(SystemDir p_dir) const;
 
+	virtual Error move_to_trash(const String &p_path) { return FAILED; }
+
 	virtual void set_no_window_mode(bool p_enable);
 	virtual bool is_no_window_mode_enabled() const;
 

+ 1 - 1
core/project_settings.cpp

@@ -116,7 +116,7 @@ String ProjectSettings::globalize_path(const String &p_path) const {
 		return p_path.replace("res://", "");
 	} else if (p_path.begins_with("user://")) {
 
-		String data_dir = OS::get_singleton()->get_data_dir();
+		String data_dir = OS::get_singleton()->get_user_data_dir();
 		if (data_dir != "") {
 
 			return p_path.replace("user:/", data_dir);

+ 2 - 2
doc/classes/EditorSettings.xml

@@ -55,7 +55,7 @@
 				Get the list of favorite directories for this project.
 			</description>
 		</method>
-		<method name="get_project_settings_path" qualifiers="const">
+		<method name="get_project_settings_dir" qualifiers="const">
 			<return type="String">
 			</return>
 			<description>
@@ -77,7 +77,7 @@
 			<description>
 			</description>
 		</method>
-		<method name="get_settings_path" qualifiers="const">
+		<method name="get_settings_dir" qualifiers="const">
 			<return type="String">
 			</return>
 			<description>

+ 2 - 2
doc/classes/OS.xml

@@ -127,11 +127,11 @@
 				Returns the current screen index (0 padded).
 			</description>
 		</method>
-		<method name="get_data_dir" qualifiers="const">
+		<method name="get_user_data_dir" qualifiers="const">
 			<return type="String">
 			</return>
 			<description>
-				Returns the absolute directory path of user data path([user://]).
+				Returns the absolute directory path where user data is written ([code]user://[/code]).
 			</description>
 		</method>
 		<method name="get_date" qualifiers="const">

+ 0 - 10
drivers/unix/SCsub

@@ -2,16 +2,6 @@
 
 Import('env')
 
-g_set_p = '#ifdef UNIX_ENABLED\n'
-g_set_p += '#include "os_unix.h"\n'
-g_set_p += 'String OS_Unix::get_global_settings_path() const {\n'
-g_set_p += '\treturn "' + env["unix_global_settings_path"] + '";\n'
-g_set_p += '}\n'
-g_set_p += '#endif'
-f = open("os_unix_global_settings_path.gen.cpp", "w")
-f.write(g_set_p)
-f.close()
-
 env.add_source_files(env.drivers_sources, "*.cpp")
 
 env["check_c_headers"] = [ [ "mntent.h", "HAVE_MNTENT" ] ]

+ 8 - 19
drivers/unix/os_unix.cpp

@@ -454,32 +454,21 @@ int OS_Unix::get_processor_count() const {
 	return sysconf(_SC_NPROCESSORS_CONF);
 }
 
-String OS_Unix::get_data_dir() const {
+String OS_Unix::get_user_data_dir() const {
 
-	String an = get_safe_application_name();
-	if (an != "") {
-
-		if (has_environment("HOME")) {
-
-			bool use_godot = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir");
-			if (use_godot)
-				return get_environment("HOME") + "/.godot/app_userdata/" + an;
-			else
-				return get_environment("HOME") + "/." + an;
+	String appname = get_safe_application_name();
+	if (appname != "") {
+		bool use_godot_dir = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir");
+		if (use_godot_dir) {
+			return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname);
+		} else {
+			return get_data_path().plus_file(appname);
 		}
 	}
 
 	return ProjectSettings::get_singleton()->get_resource_path();
 }
 
-String OS_Unix::get_installed_templates_path() const {
-	String p = get_global_settings_path();
-	if (p != "")
-		return p + "/templates/";
-	else
-		return "";
-}
-
 String OS_Unix::get_executable_path() const {
 
 #ifdef __linux__

+ 1 - 6
drivers/unix/os_unix.h

@@ -62,8 +62,6 @@ protected:
 
 	String stdin_buf;
 
-	String get_global_settings_path() const;
-
 public:
 	virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
 	virtual String get_stdin_string(bool p_block);
@@ -108,11 +106,8 @@ public:
 
 	virtual void debug_break();
 
-	virtual String get_installed_templates_path() const;
 	virtual String get_executable_path() const;
-	virtual String get_data_dir() const;
-
-	//virtual void run( MainLoop * p_main_loop );
+	virtual String get_user_data_dir() const;
 };
 
 class UnixTerminalLogger : public StdLogger {

+ 4 - 4
editor/create_dialog.cpp

@@ -41,7 +41,7 @@ void CreateDialog::popup_create(bool p_dontclear) {
 
 	recent->clear();
 
-	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent." + base_type), FileAccess::READ);
+	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ);
 
 	if (f) {
 
@@ -63,7 +63,7 @@ void CreateDialog::popup_create(bool p_dontclear) {
 
 	favorites->clear();
 
-	f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites." + base_type), FileAccess::READ);
+	f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::READ);
 
 	favorite_list.clear();
 
@@ -316,7 +316,7 @@ void CreateDialog::_confirmed() {
 	if (!ti)
 		return;
 
-	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent." + base_type), FileAccess::WRITE);
+	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
 
 	if (f) {
 		f->store_line(get_selected_type());
@@ -476,7 +476,7 @@ void CreateDialog::_favorite_toggled() {
 
 void CreateDialog::_save_favorite_list() {
 
-	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites." + base_type), FileAccess::WRITE);
+	FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
 
 	if (f) {
 

+ 8 - 23
editor/editor_export.cpp

@@ -336,33 +336,18 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat
 
 String EditorExportPlatform::find_export_template(String template_file_name, String *err) const {
 
-	String base_name = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + _MKSTR(VERSION_STATUS) + "/" + template_file_name;
-	String user_file = EditorSettings::get_singleton()->get_settings_path() + "/templates/" + base_name;
-	String system_file = OS::get_singleton()->get_installed_templates_path();
-	bool has_system_path = (system_file != "");
-	system_file = system_file.plus_file(base_name);
-
-	// Prefer user file
-	if (FileAccess::exists(user_file)) {
-		return user_file;
-	}
+	String current_version = itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "-" + _MKSTR(VERSION_STATUS) + VERSION_MODULE_CONFIG;
+	String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(current_version).plus_file(template_file_name);
 
-	// Now check system file
-	if (has_system_path) {
-		if (FileAccess::exists(system_file)) {
-			return system_file;
-		}
+	if (FileAccess::exists(template_path)) {
+		return template_path;
 	}
 
 	// Not found
 	if (err) {
-		*err += "No export template found at \"" + user_file + "\"";
-		if (has_system_path)
-			*err += "\n or \"" + system_file + "\".";
-		else
-			*err += ".";
+		*err += "No export template found at \"" + template_path + "\".";
 	}
-	return String(); // not found
+	return String();
 }
 
 bool EditorExportPlatform::exists_export_template(String template_file_name, String *err) const {
@@ -692,7 +677,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
 	}
 
 	String config_file = "project.binary";
-	String engine_cfb = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmp" + config_file;
+	String engine_cfb = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp" + config_file);
 	ProjectSettings::get_singleton()->save_custom(engine_cfb, custom_map, custom_list);
 	Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
 
@@ -705,7 +690,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
 
 	EditorProgress ep("savepack", TTR("Packing"), 102);
 
-	String tmppath = EditorSettings::get_singleton()->get_settings_path() + "/tmp/packtmp";
+	String tmppath = EditorSettings::get_singleton()->get_cache_dir().plus_file("packtmp");
 	FileAccess *ftmp = FileAccess::open(tmppath, FileAccess::WRITE);
 	ERR_FAIL_COND_V(!ftmp, ERR_CANT_CREATE)
 

+ 4 - 4
editor/editor_file_system.cpp

@@ -188,7 +188,7 @@ void EditorFileSystem::_scan_filesystem() {
 
 	String project = ProjectSettings::get_singleton()->get_resource_path();
 
-	String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache3");
+	String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_cache3");
 	FileAccess *f = FileAccess::open(fscache, FileAccess::READ);
 
 	if (f) {
@@ -238,7 +238,7 @@ void EditorFileSystem::_scan_filesystem() {
 		memdelete(f);
 	}
 
-	String update_cache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_update3");
+	String update_cache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update3");
 
 	if (FileAccess::exists(update_cache)) {
 		{
@@ -282,7 +282,7 @@ void EditorFileSystem::_scan_filesystem() {
 }
 
 void EditorFileSystem::_save_filesystem_cache() {
-	String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache3");
+	String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_cache3");
 
 	FileAccess *f = FileAccess::open(fscache, FileAccess::WRITE);
 	_save_filesystem_cache(filesystem, f);
@@ -1180,7 +1180,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem_path(const String &p
 
 void EditorFileSystem::_save_late_updated_files() {
 	//files that already existed, and were modified, need re-scanning for dependencies upon project restart. This is done via saving this special file
-	String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_update3");
+	String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update3");
 	FileAccessRef f = FileAccess::open(fscache, FileAccess::WRITE);
 	for (Set<String>::Element *E = late_update_files.front(); E; E = E->next()) {
 		f->store_line(E->get());

+ 11 - 11
editor/editor_node.cpp

@@ -705,7 +705,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) {
 	if (!scene)
 		return;
 
-	String path = EditorSettings::get_singleton()->get_project_settings_path().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
+	String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
 
 	Ref<ConfigFile> cf;
 	cf.instance();
@@ -739,7 +739,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) {
 	scene->set_meta("__editor_run_settings__", Variant()); //clear it (no point in keeping it)
 	scene->set_meta("__editor_plugin_states__", Variant());
 
-	String path = EditorSettings::get_singleton()->get_project_settings_path().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
+	String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
 
 	Ref<ConfigFile> cf;
 	cf.instance();
@@ -932,7 +932,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
 		img->flip_y();
 
 		//save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5
-		String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+		String temp_path = EditorSettings::get_singleton()->get_cache_dir();
 		String cache_base = ProjectSettings::get_singleton()->globalize_path(p_file).md5_text();
 		cache_base = temp_path.plus_file("resthumb-" + cache_base);
 
@@ -1204,7 +1204,7 @@ void EditorNode::_dialog_action(String p_file) {
 
 			Ref<ConfigFile> config;
 			config.instance();
-			Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+			Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
 
 			if (err == ERR_CANT_OPEN) {
 				config.instance(); // new config
@@ -1215,7 +1215,7 @@ void EditorNode::_dialog_action(String p_file) {
 
 			_save_docks_to_config(config, p_file);
 
-			config->save(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+			config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
 
 			layout_dialog->hide();
 			_update_layouts_menu();
@@ -1232,7 +1232,7 @@ void EditorNode::_dialog_action(String p_file) {
 
 			Ref<ConfigFile> config;
 			config.instance();
-			Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+			Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
 
 			if (err != OK || !config->has_section(p_file)) {
 				show_warning(TTR("Layout name not found!"));
@@ -1246,7 +1246,7 @@ void EditorNode::_dialog_action(String p_file) {
 				config->set_value(p_file, E->get(), Variant());
 			}
 
-			config->save(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+			config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
 
 			layout_dialog->hide();
 			_update_layouts_menu();
@@ -3587,7 +3587,7 @@ void EditorNode::_save_docks() {
 	_save_docks_to_config(config, "docks");
 	editor_data.get_plugin_window_layout(config);
 
-	config->save(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
+	config->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
 }
 
 void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) {
@@ -3649,7 +3649,7 @@ void EditorNode::_load_docks() {
 
 	Ref<ConfigFile> config;
 	config.instance();
-	Error err = config->load(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
+	Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
 	if (err != OK) {
 		//no config
 		if (overridden_default_layout >= 0) {
@@ -3818,7 +3818,7 @@ void EditorNode::_update_layouts_menu() {
 
 	Ref<ConfigFile> config;
 	config.instance();
-	Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+	Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
 	if (err != OK) {
 		return; //no config
 	}
@@ -3866,7 +3866,7 @@ void EditorNode::_layout_menu_option(int p_id) {
 
 			Ref<ConfigFile> config;
 			config.instance();
-			Error err = config->load(EditorSettings::get_singleton()->get_settings_path().plus_file("editor_layouts-3.cfg"));
+			Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
 			if (err != OK) {
 				return; //no config
 			}

+ 1 - 1
editor/editor_resource_preview.cpp

@@ -198,7 +198,7 @@ void EditorResourcePreview::_thread() {
 
 				} else {
 
-					String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+					String temp_path = EditorSettings::get_singleton()->get_cache_dir();
 					String cache_base = ProjectSettings::get_singleton()->globalize_path(item.path).md5_text();
 					cache_base = temp_path.plus_file("resthumb-" + cache_base);
 

+ 147 - 70
editor/editor_settings.cpp

@@ -640,10 +640,14 @@ void EditorSettings::create() {
 		return; //pointless
 
 	DirAccess *dir = NULL;
-	Variant meta;
 
+	String data_path;
+	String data_dir;
 	String config_path;
 	String config_dir;
+	String cache_path;
+	String cache_dir;
+
 	Ref<ConfigFile> extra_config = memnew(ConfigFile);
 
 	String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
@@ -660,38 +664,50 @@ void EditorSettings::create() {
 	memdelete(d);
 
 	if (self_contained) {
-		// editor is self contained
+
+		// editor is self contained, all in same folder
+		data_path = exe_path;
+		data_dir = data_path.plus_file("editor_data");
 		config_path = exe_path;
-		config_dir = "editor_data";
+		config_dir = data_dir;
+		cache_path = exe_path;
+		cache_dir = data_dir.plus_file("cache");
 	} else {
 
-		if (OS::get_singleton()->has_environment("APPDATA")) {
-			// Most likely under windows, save here
-			config_path = OS::get_singleton()->get_environment("APPDATA");
-			config_dir = String(_MKSTR(VERSION_SHORT_NAME)).capitalize();
-		} else if (OS::get_singleton()->has_environment("HOME")) {
-
-			config_path = OS::get_singleton()->get_environment("HOME");
-			config_dir = "." + String(_MKSTR(VERSION_SHORT_NAME)).to_lower();
+		// Typically XDG_DATA_HOME or %APPDATA%
+		data_path = OS::get_singleton()->get_data_path();
+		data_dir = data_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+		// Can be different from data_path e.g. on Linux or macOS
+		config_path = OS::get_singleton()->get_config_path();
+		config_dir = config_path.plus_file(OS::get_singleton()->get_godot_dir_name());
+		// Can be different from above paths, otherwise a subfolder of data_dir
+		cache_path = OS::get_singleton()->get_cache_path();
+		if (cache_path == data_path) {
+			cache_dir = data_dir.plus_file("cache");
+		} else {
+			cache_dir = cache_path.plus_file(OS::get_singleton()->get_godot_dir_name());
 		}
-	};
+	}
 
 	ClassDB::register_class<EditorSettings>(); //otherwise it can't be unserialized
+
 	String config_file_path;
 
-	if (config_path != "") {
+	if (data_path != "" && config_path != "" && cache_path != "") {
+
+		// Validate/create data dir and subdirectories
 
 		dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-		if (dir->change_dir(config_path) != OK) {
-			ERR_PRINT("Cannot find path for config directory!");
+		if (dir->change_dir(data_path) != OK) {
+			ERR_PRINT("Cannot find path for data directory!");
 			memdelete(dir);
 			goto fail;
 		}
 
-		if (dir->change_dir(config_dir) != OK) {
-			dir->make_dir(config_dir);
-			if (dir->change_dir(config_dir) != OK) {
-				ERR_PRINT("Cannot create config directory!");
+		if (dir->change_dir(data_dir) != OK) {
+			dir->make_dir(data_dir);
+			if (dir->change_dir(data_dir) != OK) {
+				ERR_PRINT("Cannot create data directory!");
 				memdelete(dir);
 				goto fail;
 			}
@@ -700,10 +716,43 @@ void EditorSettings::create() {
 		if (dir->change_dir("templates") != OK) {
 			dir->make_dir("templates");
 		} else {
-
 			dir->change_dir("..");
 		}
 
+		// Validate/create cache dir
+
+		if (dir->change_dir(cache_path) != OK) {
+			ERR_PRINT("Cannot find path for cache directory!");
+			memdelete(dir);
+			goto fail;
+		}
+
+		if (dir->change_dir(cache_dir) != OK) {
+			dir->make_dir(cache_dir);
+			if (dir->change_dir(cache_dir) != OK) {
+				ERR_PRINT("Cannot create cache directory!");
+				memdelete(dir);
+				goto fail;
+			}
+		}
+
+		// Validate/create config dir and subdirectories
+
+		if (dir->change_dir(config_path) != OK) {
+			ERR_PRINT("Cannot find path for config directory!");
+			memdelete(dir);
+			goto fail;
+		}
+
+		if (dir->change_dir(config_dir) != OK) {
+			dir->make_dir(config_dir);
+			if (dir->change_dir(config_dir) != OK) {
+				ERR_PRINT("Cannot create config directory!");
+				memdelete(dir);
+				goto fail;
+			}
+		}
+
 		if (dir->change_dir("text_editor_themes") != OK) {
 			dir->make_dir("text_editor_themes");
 		} else {
@@ -715,52 +764,40 @@ void EditorSettings::create() {
 		} else {
 			dir->change_dir("..");
 		}
-		_create_script_templates(dir->get_current_dir() + "/script_templates");
-
-		if (dir->change_dir("tmp") != OK) {
-			dir->make_dir("tmp");
-		} else {
-
-			dir->change_dir("..");
-		}
+		_create_script_templates(dir->get_current_dir().plus_file("script_templates"));
 
-		if (dir->change_dir("config") != OK) {
-			dir->make_dir("config");
+		if (dir->change_dir("projects") != OK) {
+			dir->make_dir("projects");
 		} else {
-
 			dir->change_dir("..");
 		}
 
-		dir->change_dir("config");
+		// Validate/create project-specific config dir
 
-		String pcp = ProjectSettings::get_singleton()->get_resource_path();
-		if (pcp.ends_with("/"))
-			pcp = config_path.substr(0, pcp.size() - 1);
-		pcp = pcp.get_file() + "-" + pcp.md5_text();
+		dir->change_dir("projects");
+		String project_config_dir = ProjectSettings::get_singleton()->get_resource_path();
+		if (project_config_dir.ends_with("/"))
+			project_config_dir = config_path.substr(0, project_config_dir.size() - 1);
+		project_config_dir = project_config_dir.get_file() + "-" + project_config_dir.md5_text();
 
-		if (dir->change_dir(pcp)) {
-			dir->make_dir(pcp);
+		if (dir->change_dir(project_config_dir) != OK) {
+			dir->make_dir(project_config_dir);
 		} else {
 			dir->change_dir("..");
 		}
-
 		dir->change_dir("..");
 
-		// path at least is validated, so validate config file
-
-		String config_file_name = "editor_settings-" + String(_MKSTR(VERSION_MAJOR)) + ".tres";
-		config_file_path = config_path + "/" + config_dir + "/" + config_file_name;
-
-		String open_path = config_file_path;
+		// Validate editor config file
 
+		String config_file_name = "editor_settings.tres";
+		config_file_path = config_dir.plus_file(config_file_name);
 		if (!dir->file_exists(config_file_name)) {
-
 			goto fail;
 		}
 
 		memdelete(dir);
 
-		singleton = ResourceLoader::load(open_path, "EditorSettings");
+		singleton = ResourceLoader::load(config_file_path, "EditorSettings");
 
 		if (singleton.is_null()) {
 			WARN_PRINT("Could not open config file.");
@@ -769,8 +806,10 @@ void EditorSettings::create() {
 
 		singleton->save_changed_setting = true;
 		singleton->config_file_path = config_file_path;
-		singleton->project_config_path = pcp;
-		singleton->settings_path = config_path + "/" + config_dir;
+		singleton->project_config_dir = project_config_dir;
+		singleton->settings_dir = config_dir;
+		singleton->data_dir = data_dir;
+		singleton->cache_dir = cache_dir;
 
 		if (OS::get_singleton()->is_stdout_verbose()) {
 
@@ -800,7 +839,9 @@ fail:
 	singleton = Ref<EditorSettings>(memnew(EditorSettings));
 	singleton->save_changed_setting = true;
 	singleton->config_file_path = config_file_path;
-	singleton->settings_path = config_path + "/" + config_dir;
+	singleton->settings_dir = config_dir;
+	singleton->data_dir = data_dir;
+	singleton->cache_dir = cache_dir;
 	singleton->_load_defaults(extra_config);
 	singleton->setup_language();
 	singleton->setup_network();
@@ -971,21 +1012,52 @@ void EditorSettings::add_property_hint(const PropertyInfo &p_hint) {
 	hints[p_hint.name] = p_hint;
 }
 
-// Settings paths and saved metadata
+// Data directories
+
+String EditorSettings::get_data_dir() const {
+
+	return data_dir;
+}
+
+String EditorSettings::get_templates_dir() const {
+
+	return get_data_dir().plus_file("templates");
+}
+
+// Config directories
+
+String EditorSettings::get_settings_dir() const {
+
+	return settings_dir;
+}
+
+String EditorSettings::get_project_settings_dir() const {
+
+	return get_settings_dir().plus_file("projects").plus_file(project_config_dir);
+}
+
+String EditorSettings::get_text_editor_themes_dir() const {
 
-String EditorSettings::get_settings_path() const {
+	return get_settings_dir().plus_file("text_editor_themes");
+}
 
-	return settings_path;
+String EditorSettings::get_script_templates_dir() const {
+
+	return get_settings_dir().plus_file("script_templates");
 }
 
-String EditorSettings::get_project_settings_path() const {
+// Cache directory
+
+String EditorSettings::get_cache_dir() const {
 
-	return get_settings_path().plus_file("config").plus_file(project_config_path);
+	return cache_dir;
 }
 
+// Metadata
+
 void EditorSettings::set_project_metadata(const String &p_section, const String &p_key, Variant p_data) {
 	Ref<ConfigFile> cf = memnew(ConfigFile);
-	String path = get_project_settings_path().plus_file("project_metadata.cfg");
+	String path = get_project_settings_dir().plus_file("project_metadata.cfg");
 	cf->load(path);
 	cf->set_value(p_section, p_key, p_data);
 	cf->save(path);
@@ -993,7 +1065,7 @@ void EditorSettings::set_project_metadata(const String &p_section, const String
 
 Variant EditorSettings::get_project_metadata(const String &p_section, const String &p_key, Variant p_default) {
 	Ref<ConfigFile> cf = memnew(ConfigFile);
-	String path = get_project_settings_path().plus_file("project_metadata.cfg");
+	String path = get_project_settings_dir().plus_file("project_metadata.cfg");
 	Error err = cf->load(path);
 	if (err != OK) {
 		return p_default;
@@ -1004,7 +1076,7 @@ Variant EditorSettings::get_project_metadata(const String &p_section, const Stri
 void EditorSettings::set_favorite_dirs(const Vector<String> &p_favorites_dirs) {
 
 	favorite_dirs = p_favorites_dirs;
-	FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"), FileAccess::WRITE);
+	FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorite_dirs"), FileAccess::WRITE);
 	if (f) {
 		for (int i = 0; i < favorite_dirs.size(); i++)
 			f->store_line(favorite_dirs[i]);
@@ -1020,7 +1092,7 @@ Vector<String> EditorSettings::get_favorite_dirs() const {
 void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) {
 
 	recent_dirs = p_recent_dirs;
-	FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"), FileAccess::WRITE);
+	FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("recent_dirs"), FileAccess::WRITE);
 	if (f) {
 		for (int i = 0; i < recent_dirs.size(); i++)
 			f->store_line(recent_dirs[i]);
@@ -1035,7 +1107,7 @@ Vector<String> EditorSettings::get_recent_dirs() const {
 
 void EditorSettings::load_favorites() {
 
-	FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"), FileAccess::READ);
+	FileAccess *f = FileAccess::open(get_project_settings_dir().plus_file("favorite_dirs"), FileAccess::READ);
 	if (f) {
 		String line = f->get_line().strip_edges();
 		while (line != "") {
@@ -1045,7 +1117,7 @@ void EditorSettings::load_favorites() {
 		memdelete(f);
 	}
 
-	f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"), FileAccess::READ);
+	f = FileAccess::open(get_project_settings_dir().plus_file("recent_dirs"), FileAccess::READ);
 	if (f) {
 		String line = f->get_line().strip_edges();
 		while (line != "") {
@@ -1058,7 +1130,7 @@ void EditorSettings::load_favorites() {
 
 void EditorSettings::list_text_editor_themes() {
 	String themes = "Adaptive,Default";
-	DirAccess *d = DirAccess::open(get_settings_path().plus_file("text_editor_themes"));
+	DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
 	if (d) {
 		d->list_dir_begin();
 		String file = d->get_next();
@@ -1080,7 +1152,7 @@ void EditorSettings::load_text_editor_theme() {
 		return;
 	}
 
-	String theme_path = get_settings_path().plus_file("text_editor_themes").plus_file((String)get("text_editor/theme/color_theme") + ".tet");
+	String theme_path = get_text_editor_themes_dir().plus_file((String)get("text_editor/theme/color_theme") + ".tet");
 
 	Ref<ConfigFile> cf = memnew(ConfigFile);
 	Error err = cf->load(theme_path);
@@ -1118,9 +1190,9 @@ bool EditorSettings::import_text_editor_theme(String p_file) {
 			return false;
 		}
 
-		DirAccess *d = DirAccess::open(get_settings_path().plus_file("text_editor_themes"));
+		DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
 		if (d) {
-			d->copy(p_file, get_settings_path().plus_file("text_editor_themes").plus_file(p_file.get_file()));
+			d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file()));
 			memdelete(d);
 			return true;
 		}
@@ -1135,7 +1207,7 @@ bool EditorSettings::save_text_editor_theme() {
 	if (p_file.get_file().to_lower() == "default" || p_file.get_file().to_lower() == "adaptive") {
 		return false;
 	}
-	String theme_path = get_settings_path().plus_file("text_editor_themes").plus_file(p_file + ".tet");
+	String theme_path = get_text_editor_themes_dir().plus_file(p_file + ".tet");
 	return _save_text_editor_theme(theme_path);
 }
 
@@ -1153,7 +1225,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) {
 		list_text_editor_themes();
 		String theme_name = p_file.substr(0, p_file.length() - 4).get_file();
 
-		if (p_file.get_base_dir() == get_settings_path().plus_file("text_editor_themes")) {
+		if (p_file.get_base_dir() == get_text_editor_themes_dir()) {
 			_initial_set("text_editor/theme/color_theme", theme_name);
 			load_text_editor_theme();
 		}
@@ -1165,7 +1237,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) {
 Vector<String> EditorSettings::get_script_templates(const String &p_extension) {
 
 	Vector<String> templates;
-	DirAccess *d = DirAccess::open(get_settings_path().plus_file("script_templates"));
+	DirAccess *d = DirAccess::open(get_script_templates_dir());
 	if (d) {
 		d->list_dir_begin();
 		String file = d->get_next();
@@ -1181,6 +1253,11 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension) {
 	return templates;
 }
 
+String EditorSettings::get_editor_layouts_config() const {
+
+	return get_settings_dir().plus_file("editor_layouts.cfg");
+}
+
 // Shortcuts
 
 void EditorSettings::add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut) {
@@ -1287,8 +1364,8 @@ void EditorSettings::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert);
 	ClassDB::bind_method(D_METHOD("add_property_info", "info"), &EditorSettings::_add_property_info_bind);
 
-	ClassDB::bind_method(D_METHOD("get_settings_path"), &EditorSettings::get_settings_path);
-	ClassDB::bind_method(D_METHOD("get_project_settings_path"), &EditorSettings::get_project_settings_path);
+	ClassDB::bind_method(D_METHOD("get_settings_dir"), &EditorSettings::get_settings_dir);
+	ClassDB::bind_method(D_METHOD("get_project_settings_dir"), &EditorSettings::get_project_settings_dir);
 
 	ClassDB::bind_method(D_METHOD("set_favorite_dirs", "dirs"), &EditorSettings::set_favorite_dirs);
 	ClassDB::bind_method(D_METHOD("get_favorite_dirs"), &EditorSettings::get_favorite_dirs);

+ 12 - 4
editor/editor_settings.h

@@ -93,9 +93,11 @@ private:
 	Map<String, Ref<ShortCut> > shortcuts;
 
 	String resource_path;
+	String settings_dir;
+	String data_dir;
+	String cache_dir;
 	String config_file_path;
-	String settings_path;
-	String project_config_path;
+	String project_config_dir;
 
 	Vector<String> favorite_dirs;
 	Vector<String> recent_dirs;
@@ -147,8 +149,13 @@ public:
 	void set_resource_clipboard(const Ref<Resource> &p_resource) { clipboard = p_resource; }
 	Ref<Resource> get_resource_clipboard() const { return clipboard; }
 
-	String get_settings_path() const;
-	String get_project_settings_path() const;
+	String get_data_dir() const;
+	String get_templates_dir() const;
+	String get_settings_dir() const;
+	String get_project_settings_dir() const;
+	String get_text_editor_themes_dir() const;
+	String get_script_templates_dir() const;
+	String get_cache_dir() const;
 
 	void set_project_metadata(const String &p_section, const String &p_key, Variant p_data);
 	Variant get_project_metadata(const String &p_section, const String &p_key, Variant p_default);
@@ -166,6 +173,7 @@ public:
 	bool save_text_editor_theme_as(String p_file);
 
 	Vector<String> get_script_templates(const String &p_extension);
+	String get_editor_layouts_config() const;
 
 	void add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut);
 	bool is_shortcut(const String &p_name, const Ref<InputEvent> &p_event) const;

+ 5 - 4
editor/export_template_manager.cpp

@@ -35,6 +35,7 @@
 #include "io/zip_io.h"
 #include "os/dir_access.h"
 #include "version.h"
+
 void ExportTemplateManager::_update_template_list() {
 
 	while (current_hb->get_child_count()) {
@@ -46,7 +47,7 @@ void ExportTemplateManager::_update_template_list() {
 	}
 
 	DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-	Error err = d->change_dir(EditorSettings::get_singleton()->get_settings_path().plus_file("templates"));
+	Error err = d->change_dir(EditorSettings::get_singleton()->get_templates_dir());
 
 	d->list_dir_begin();
 	Set<String> templates;
@@ -142,7 +143,7 @@ void ExportTemplateManager::_uninstall_template(const String &p_version) {
 void ExportTemplateManager::_uninstall_template_confirm() {
 
 	DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-	Error err = d->change_dir(EditorSettings::get_singleton()->get_settings_path().plus_file("templates"));
+	Error err = d->change_dir(EditorSettings::get_singleton()->get_templates_dir());
 
 	ERR_FAIL_COND(err != OK);
 
@@ -244,7 +245,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file) {
 		return;
 	}
 
-	String template_path = EditorSettings::get_singleton()->get_settings_path().plus_file("templates").plus_file(version);
+	String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version);
 
 	DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 	Error err = d->make_dir_recursive(template_path);
@@ -393,7 +394,7 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int
 			if (p_code != 200) {
 				template_list_state->set_text(TTR("Failed:") + " " + itos(p_code));
 			} else {
-				String path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_templates.tpz");
+				String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_templates.tpz");
 				FileAccess *f = FileAccess::open(path, FileAccess::WRITE);
 				if (!f) {
 					template_list_state->set_text(TTR("Can't write file."));

+ 4 - 4
editor/plugins/asset_library_editor_plugin.cpp

@@ -445,7 +445,7 @@ void EditorAssetLibraryItemDownload::_install() {
 
 void EditorAssetLibraryItemDownload::_make_request() {
 	download->cancel_request();
-	download->set_download_file(EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_asset_" + itos(asset_id)) + ".zip");
+	download->set_download_file(EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_asset_" + itos(asset_id)) + ".zip");
 
 	Error err = download->request(host);
 	if (err != OK) {
@@ -680,7 +680,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt
 		PoolByteArray image_data = p_data;
 
 		if (use_cache) {
-			String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
+			String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
 
 			FileAccess *file = FileAccess::open(cache_filename_base + ".data", FileAccess::READ);
 
@@ -738,7 +738,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
 		if (p_code != HTTPClient::RESPONSE_NOT_MODIFIED) {
 			for (int i = 0; i < headers.size(); i++) {
 				if (headers[i].findn("ETag:") == 0) { // Save etag
-					String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
+					String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
 					String new_etag = headers[i].substr(headers[i].find(":") + 1, headers[i].length()).strip_edges();
 					FileAccess *file;
 
@@ -786,7 +786,7 @@ void EditorAssetLibrary::_update_image_queue() {
 	for (Map<int, ImageQueue>::Element *E = image_queue.front(); E; E = E->next()) {
 		if (!E->get().active && current_images < max_images) {
 
-			String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_" + E->get().image_url.md5_text());
+			String cache_filename_base = EditorSettings::get_singleton()->get_cache_dir().plus_file("assetimage_" + E->get().image_url.md5_text());
 			Vector<String> headers;
 
 			if (FileAccess::exists(cache_filename_base + ".etag") && FileAccess::exists(cache_filename_base + ".data")) {

+ 1 - 1
editor/plugins/editor_preview_plugins.cpp

@@ -184,7 +184,7 @@ Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) {
 
 Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) {
 
-	String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+	String temp_path = EditorSettings::get_singleton()->get_cache_dir();
 	String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text();
 	cache_base = temp_path.plus_file("resthumb-" + cache_base);
 

+ 1 - 1
editor/plugins/script_editor_plugin.cpp

@@ -855,7 +855,7 @@ void ScriptEditor::_menu_option(int p_option) {
 			file_dialog_option = FILE_SAVE_THEME_AS;
 			file_dialog->clear_filters();
 			file_dialog->add_filter("*.tet");
-			file_dialog->set_current_path(EditorSettings::get_singleton()->get_settings_path() + "/text_editor_themes/" + EditorSettings::get_singleton()->get("text_editor/theme/color_theme"));
+			file_dialog->set_current_path(EditorSettings::get_singleton()->get_text_editor_themes_dir().plus_file(EditorSettings::get_singleton()->get("text_editor/theme/color_theme")));
 			file_dialog->popup_centered_ratio();
 			file_dialog->set_title(TTR("Save Theme As.."));
 		} break;

+ 3 - 3
editor/pvrtc_compress.cpp

@@ -62,12 +62,12 @@ static void _compress_image(Image::CompressMode p_mode, Image *p_image) {
 		}
 		return;
 	}
-	String spath = EditorSettings::get_singleton()->get_settings_path();
+	String tmppath = EditorSettings::get_singleton()->get_cache_dir();
 
 	List<String> args;
 
-	String src_img = spath + "/" + "_tmp_src_img.png";
-	String dst_img = spath + "/" + "_tmp_dst_img.pvr";
+	String src_img = tmppath.plus_file("_tmp_src_img.png");
+	String dst_img = tmppath.plus_file("_tmp_dst_img.pvr");
 
 	args.push_back("-i");
 	args.push_back(src_img);

+ 1 - 1
editor/script_create_dialog.cpp

@@ -128,7 +128,7 @@ void ScriptCreateDialog::_template_changed(int p_template) {
 	}
 	String ext = ScriptServer::get_language(language_menu->get_selected())->get_extension();
 	String name = template_list[p_template - 1] + "." + ext;
-	script_template = EditorSettings::get_singleton()->get_settings_path() + "/script_templates/" + name;
+	script_template = EditorSettings::get_singleton()->get_script_templates_dir().plus_file(name);
 }
 
 void ScriptCreateDialog::ok_pressed() {

+ 1 - 1
modules/enet/networked_multiplayer_enet.cpp

@@ -505,7 +505,7 @@ uint32_t NetworkedMultiplayerENet::_gen_unique_id() const {
 		hash = hash_djb2_one_32(
 				(uint32_t)OS::get_singleton()->get_unix_time(), hash);
 		hash = hash_djb2_one_32(
-				(uint32_t)OS::get_singleton()->get_data_dir().hash64(), hash);
+				(uint32_t)OS::get_singleton()->get_user_data_dir().hash64(), hash);
 		/*
 		hash = hash_djb2_one_32(
 					(uint32_t)OS::get_singleton()->get_unique_id().hash64(), hash );

+ 3 - 9
modules/mono/godotsharp_dirs.cpp

@@ -57,7 +57,7 @@ String _get_expected_build_config() {
 String _get_mono_user_dir() {
 #ifdef TOOLS_ENABLED
 	if (EditorSettings::get_singleton()) {
-		return EditorSettings::get_singleton()->get_settings_path().plus_file("mono");
+		return EditorSettings::get_singleton()->get_data_dir().plus_file("mono");
 	} else {
 		String settings_path;
 
@@ -68,19 +68,13 @@ String _get_mono_user_dir() {
 			// contain yourself
 			settings_path = exe_dir.plus_file("editor_data");
 		} else {
-			if (OS::get_singleton()->has_environment("APPDATA")) {
-				String app_data = OS::get_singleton()->get_environment("APPDATA").replace("\\", "/");
-				settings_path = app_data.plus_file(String(_MKSTR(VERSION_SHORT_NAME)).capitalize());
-			} else if (OS::get_singleton()->has_environment("HOME")) {
-				String home = OS::get_singleton()->get_environment("HOME");
-				settings_path = home.plus_file("." + String(_MKSTR(VERSION_SHORT_NAME)).to_lower());
-			}
+			settings_path = OS::get_singleton()->get_data_path().plus_file(OS::get_singleton()->get_godot_dir_name());
 		}
 
 		return settings_path.plus_file("mono");
 	}
 #else
-	return OS::get_singleton()->get_data_dir().plus_file("mono");
+	return OS::get_singleton()->get_user_data_dir().plus_file("mono");
 #endif
 }
 

+ 2 - 2
platform/android/export/export.cpp

@@ -1067,7 +1067,7 @@ public:
 		if (use_reverse)
 			p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST;
 
-		String export_to = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpexport.apk";
+		String export_to = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport.apk");
 		Error err = export_project(p_preset, true, export_to, p_debug_flags);
 		if (err) {
 			device_lock->unlock();
@@ -1292,7 +1292,7 @@ public:
 		zlib_filefunc_def io2 = io;
 		FileAccess *dst_f = NULL;
 		io2.opaque = &dst_f;
-		String unaligned_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpexport-unaligned.apk";
+		String unaligned_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned.apk");
 		zipFile unaligned_apk = zipOpen2(unaligned_path.utf8().get_data(), APPEND_STATUS_CREATE, NULL, &io2);
 
 		bool export_x86 = p_preset->get("architecture/x86");

+ 2 - 2
platform/android/java_glue.cpp

@@ -647,7 +647,7 @@ static int _open_uri(const String &p_uri) {
 	return env->CallIntMethod(godot_io, _openURI, jStr);
 }
 
-static String _get_data_dir() {
+static String _get_user_data_dir() {
 
 	JNIEnv *env = ThreadAndroid::get_env();
 	jstring s = (jstring)env->CallObjectMethod(godot_io, _getDataDir);
@@ -825,7 +825,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
 		AudioDriverAndroid::setup(gob);
 	}
 
-	os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _get_vk_height, _set_screen_orient, _get_unique_id, _get_system_dir, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, p_use_apk_expansion);
+	os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_user_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _get_vk_height, _set_screen_orient, _get_unique_id, _get_system_dir, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, p_use_apk_expansion);
 	os_android->set_need_reload_hooks(p_need_reload_hook);
 
 	char wd[500];

+ 5 - 6
platform/android/os_android.cpp

@@ -612,13 +612,13 @@ void OS_Android::set_need_reload_hooks(bool p_needs_them) {
 	use_reload_hooks = p_needs_them;
 }
 
-String OS_Android::get_data_dir() const {
+String OS_Android::get_user_data_dir() const {
 
 	if (data_dir_cache != String())
 		return data_dir_cache;
 
-	if (get_data_dir_func) {
-		String data_dir = get_data_dir_func();
+	if (get_user_data_dir_func) {
+		String data_dir = get_user_data_dir_func();
 
 		//store current dir
 		char real_current_dir_name[2048];
@@ -641,7 +641,6 @@ String OS_Android::get_data_dir() const {
 	}
 
 	return ".";
-	//return Engine::get_singleton()->get_singleton_object("GodotOS")->call("get_data_dir");
 }
 
 void OS_Android::set_screen_orientation(ScreenOrientation p_orientation) {
@@ -709,7 +708,7 @@ bool OS_Android::_check_internal_feature_support(const String &p_feature) {
 	return p_feature == "mobile" || p_feature == "etc" || p_feature == "etc2"; //TODO support etc2 only if GLES3 driver is selected
 }
 
-OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion) {
+OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion) {
 
 	use_apk_expansion = p_use_apk_expansion;
 	default_videomode.width = 800;
@@ -725,7 +724,7 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI
 	use_gl2 = false;
 
 	open_uri_func = p_open_uri_func;
-	get_data_dir_func = p_get_data_dir_func;
+	get_user_data_dir_func = p_get_user_data_dir_func;
 	get_locale_func = p_get_locale_func;
 	get_model_func = p_get_model_func;
 	get_screen_dpi_func = p_get_screen_dpi_func;

+ 4 - 4
platform/android/os_android.h

@@ -48,7 +48,7 @@
 
 typedef void (*GFXInitFunc)(void *ud, bool gl2);
 typedef int (*OpenURIFunc)(const String &);
-typedef String (*GetDataDirFunc)();
+typedef String (*GetUserDataDirFunc)();
 typedef String (*GetLocaleFunc)();
 typedef String (*GetModelFunc)();
 typedef int (*GetScreenDPIFunc)();
@@ -116,7 +116,7 @@ private:
 	MainLoop *main_loop;
 
 	OpenURIFunc open_uri_func;
-	GetDataDirFunc get_data_dir_func;
+	GetUserDataDirFunc get_user_data_dir_func;
 	GetLocaleFunc get_locale_func;
 	GetModelFunc get_model_func;
 	GetScreenDPIFunc get_screen_dpi_func;
@@ -208,7 +208,7 @@ public:
 	virtual void set_screen_orientation(ScreenOrientation p_orientation);
 
 	virtual Error shell_open(String p_uri);
-	virtual String get_data_dir() const;
+	virtual String get_user_data_dir() const;
 	virtual String get_resource_dir() const;
 	virtual String get_locale() const;
 	virtual String get_model_name() const;
@@ -237,7 +237,7 @@ public:
 	void joy_connection_changed(int p_device, bool p_connected, String p_name);
 
 	virtual bool _check_internal_feature_support(const String &p_feature);
-	OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion);
+	OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion);
 	~OS_Android();
 };
 

+ 33 - 0
platform/haiku/os_haiku.cpp

@@ -316,3 +316,36 @@ bool OS_Haiku::_check_internal_feature_support(const String &p_feature) {
 
 	return p_feature == "pc" || p_feature == "s3tc";
 }
+
+String OS_Haiku::get_config_path() const {
+
+	if (has_environment("XDG_CONFIG_HOME")) {
+		return get_environment("XDG_CONFIG_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".config");
+	} else {
+		return ".";
+	}
+}
+
+String OS_Haiku::get_data_path() const {
+
+	if (has_environment("XDG_DATA_HOME")) {
+		return get_environment("XDG_DATA_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".local/share");
+	} else {
+		return get_config_path();
+	}
+}
+
+String OS_Haiku::get_cache_path() const {
+
+	if (has_environment("XDG_CACHE_HOME")) {
+		return get_environment("XDG_CACHE_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".cache");
+	} else {
+		return get_config_path();
+	}
+}

+ 4 - 0
platform/haiku/os_haiku.h

@@ -117,6 +117,10 @@ public:
 	virtual int get_power_percent_left();
 
 	virtual bool _check_internal_feature_support(const String &p_feature);
+
+	virtual String get_config_path() const;
+	virtual String get_data_path() const;
+	virtual String get_cache_path() const;
 };
 
 #endif

+ 3 - 3
platform/iphone/os_iphone.cpp

@@ -470,7 +470,7 @@ void OSIPhone::set_cursor_shape(CursorShape p_shape){
 
 };
 
-String OSIPhone::get_data_dir() const {
+String OSIPhone::get_user_data_dir() const {
 
 	return data_dir;
 };
@@ -509,7 +509,7 @@ Error OSIPhone::native_video_play(String p_path, float p_volume, String p_audio_
 	FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
 	bool exists = f && f->is_open();
 
-	String tempFile = get_data_dir();
+	String tempFile = get_user_data_dir();
 	if (!exists)
 		return FAILED;
 
@@ -521,7 +521,7 @@ Error OSIPhone::native_video_play(String p_path, float p_volume, String p_audio_
 			p_path = p_path.replace("res:/", ProjectSettings::get_singleton()->get_resource_path());
 		}
 	} else if (p_path.begins_with("user://"))
-		p_path = p_path.replace("user:/", get_data_dir());
+		p_path = p_path.replace("user:/", get_user_data_dir());
 
 	memdelete(f);
 

+ 1 - 1
platform/iphone/os_iphone.h

@@ -178,7 +178,7 @@ public:
 
 	Error shell_open(String p_uri);
 
-	String get_data_dir() const;
+	String get_user_data_dir() const;
 
 	void set_locale(String p_locale);
 	String get_locale() const;

+ 1 - 1
platform/javascript/export/export.cpp

@@ -272,7 +272,7 @@ int EditorExportPlatformJavaScript::get_device_count() const {
 
 Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
 
-	String path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmp_export.html";
+	String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_export.html");
 	Error err = export_project(p_preset, true, path, p_debug_flags);
 	if (err) {
 		return err;

+ 5 - 5
platform/javascript/os_javascript.cpp

@@ -882,11 +882,11 @@ String OS_JavaScript::get_resource_dir() const {
 	return "/"; //javascript has it's own filesystem for resources inside the APK
 }
 
-String OS_JavaScript::get_data_dir() const {
+String OS_JavaScript::get_user_data_dir() const {
 
 	/*
-	if (get_data_dir_func)
-		return get_data_dir_func();
+	if (get_user_data_dir_func)
+		return get_user_data_dir_func();
 	*/
 	return "/userfs";
 };
@@ -986,7 +986,7 @@ bool OS_JavaScript::is_userfs_persistent() const {
 	return idbfs_available;
 }
 
-OS_JavaScript::OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_dir_func) {
+OS_JavaScript::OS_JavaScript(const char *p_execpath, GetUserDataDirFunc p_get_user_data_dir_func) {
 	set_cmdline(p_execpath, get_cmdline_args());
 	main_loop = NULL;
 	gl_extensions = NULL;
@@ -994,7 +994,7 @@ OS_JavaScript::OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_d
 	soft_fs_enabled = false;
 	canvas_size_adjustment_requested = false;
 
-	get_data_dir_func = p_get_data_dir_func;
+	get_user_data_dir_func = p_get_user_data_dir_func;
 	FileAccessUnix::close_notification_func = _close_notification_funcs;
 
 	idbfs_available = false;

+ 4 - 4
platform/javascript/os_javascript.h

@@ -41,7 +41,7 @@
 
 #include <emscripten/html5.h>
 
-typedef String (*GetDataDirFunc)();
+typedef String (*GetUserDataDirFunc)();
 
 class OS_JavaScript : public OS_Unix {
 
@@ -62,7 +62,7 @@ class OS_JavaScript : public OS_Unix {
 	CursorShape cursor_shape;
 	MainLoop *main_loop;
 
-	GetDataDirFunc get_data_dir_func;
+	GetUserDataDirFunc get_user_data_dir_func;
 
 	PowerJavascript *power_manager;
 
@@ -141,7 +141,7 @@ public:
 	void set_opengl_extensions(const char *p_gl_extensions);
 
 	virtual Error shell_open(String p_uri);
-	virtual String get_data_dir() const;
+	virtual String get_user_data_dir() const;
 	String get_executable_path() const;
 	virtual String get_resource_dir() const;
 
@@ -160,7 +160,7 @@ public:
 
 	void set_idbfs_available(bool p_idbfs_available);
 
-	OS_JavaScript(const char *p_execpath, GetDataDirFunc p_get_data_dir_func);
+	OS_JavaScript(const char *p_execpath, GetUserDataDirFunc p_get_user_data_dir_func);
 	~OS_JavaScript();
 };
 

+ 3 - 3
platform/osx/export/export.cpp

@@ -160,7 +160,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
 		copy->convert(Image::FORMAT_RGBA8);
 		copy->resize(size, size);
 		it->create_from_image(copy);
-		String path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/icon.png";
+		String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("icon.png");
 		ResourceSaver::save(path, it);
 
 		FileAccess *f = FileAccess::open(path, FileAccess::READ);
@@ -344,7 +344,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 
 	if (use_dmg()) {
 		// We're on OSX so we can export to DMG, but first we create our application bundle
-		tmp_app_path_name = EditorSettings::get_singleton()->get_settings_path() + "/tmp/" + pkg_name + ".app";
+		tmp_app_path_name = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".app");
 		print_line("Exporting to " + tmp_app_path_name);
 		DirAccess *tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
 		if (!tmp_app_path) {
@@ -539,7 +539,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 			OS::get_singleton()->move_to_trash(tmp_app_path_name);
 		} else {
 
-			String pack_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/" + pkg_name + ".pck";
+			String pack_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".pck");
 			Error err = save_pack(p_preset, pack_path);
 
 			if (err == OK) {

+ 5 - 0
platform/osx/os_osx.h

@@ -154,6 +154,11 @@ public:
 
 	virtual MainLoop *get_main_loop() const;
 
+	virtual String get_config_path() const;
+	virtual String get_data_path() const;
+	virtual String get_cache_path() const;
+	virtual String get_godot_dir_name() const;
+
 	virtual String get_system_dir(SystemDir p_dir) const;
 
 	virtual bool can_draw() const;

+ 39 - 1
platform/osx/os_osx.mm

@@ -36,6 +36,7 @@
 #include "print_string.h"
 #include "sem_osx.h"
 #include "servers/visual/visual_server_raster.h"
+#include "version_generated.gen.h"
 
 #include <Carbon/Carbon.h>
 #import <Cocoa/Cocoa.h>
@@ -1089,7 +1090,7 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
 
 	power_manager = memnew(power_osx);
 
-	_ensure_data_dir();
+	_ensure_user_data_dir();
 
 	restore_rect = Rect2(get_window_position(), get_window_size());
 }
@@ -1334,6 +1335,43 @@ MainLoop *OS_OSX::get_main_loop() const {
 	return main_loop;
 }
 
+String OS_OSX::get_config_path() const {
+
+	if (has_environment("XDG_CONFIG_HOME")) {
+		return get_environment("XDG_CONFIG_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file("Library/Application Support");
+	} else {
+		return ".";
+	}
+}
+
+String OS_OSX::get_data_path() const {
+
+	if (has_environment("XDG_DATA_HOME")) {
+		return get_environment("XDG_DATA_HOME");
+	} else {
+		return get_config_path();
+	}
+}
+
+String OS_OSX::get_cache_path() const {
+
+	if (has_environment("XDG_CACHE_HOME")) {
+		return get_environment("XDG_CACHE_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file("Library/Caches");
+	} else {
+		return get_config_path();
+	}
+}
+
+// Get properly capitalized engine name for system paths
+String OS_OSX::get_godot_dir_name() const {
+
+	return String(_MKSTR(VERSION_SHORT_NAME)).capitalize();
+}
+
 String OS_OSX::get_system_dir(SystemDir p_dir) const {
 
 	NSSearchPathDirectory id = 0;

+ 1 - 1
platform/server/os_server.cpp

@@ -73,7 +73,7 @@ void OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p
 
 	input = memnew(InputDefault);
 
-	_ensure_data_dir();
+	_ensure_user_data_dir();
 }
 void OS_Server::finalize() {
 

+ 3 - 3
platform/uwp/export/export.cpp

@@ -456,8 +456,8 @@ void AppxPackager::init(FileAccess *p_fa) {
 	package = p_fa;
 	central_dir_offset = 0;
 	end_of_central_dir_offset = 0;
-	tmp_blockmap_file_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpblockmap.xml";
-	tmp_content_types_file_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmpcontenttypes.xml";
+	tmp_blockmap_file_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpblockmap.xml");
+	tmp_content_types_file_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpcontenttypes.xml");
 }
 
 void AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t p_len, int p_file_no, int p_total_files, bool p_compress) {
@@ -886,7 +886,7 @@ class EditorExportUWP : public EditorExportPlatform {
 
 		if (!image) return data;
 
-		String tmp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/uwp_tmp_logo.png");
+		String tmp_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("uwp_tmp_logo.png");
 
 		Error err = image->get_data()->save_png(tmp_path);
 

+ 3 - 2
platform/uwp/os_uwp.cpp

@@ -28,6 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 #include "os_uwp.h"
+
 #include "drivers/gles3/rasterizer_gles3.h"
 #include "drivers/unix/ip_unix.h"
 #include "drivers/windows/dir_access_windows.h"
@@ -298,7 +299,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud
 				ref new TypedEventHandler<Gyrometer ^, GyrometerReadingChangedEventArgs ^>(managed_object, &ManagedType::on_gyroscope_reading_changed);
 	}
 
-	_ensure_data_dir();
+	_ensure_user_data_dir();
 
 	if (is_keep_screen_on())
 		display_request->RequestActive();
@@ -781,7 +782,7 @@ MainLoop *OSUWP::get_main_loop() const {
 	return main_loop;
 }
 
-String OSUWP::get_data_dir() const {
+String OSUWP::get_user_data_dir() const {
 
 	Windows::Storage::StorageFolder ^ data_folder = Windows::Storage::ApplicationData::Current->LocalFolder;
 

+ 1 - 1
platform/uwp/os_uwp.h

@@ -226,7 +226,7 @@ public:
 	virtual String get_locale() const;
 
 	virtual void move_window_to_foreground();
-	virtual String get_data_dir() const;
+	virtual String get_user_data_dir() const;
 
 	virtual bool _check_internal_feature_support(const String &p_feature);
 

+ 47 - 10
platform/windows/os_windows.cpp

@@ -47,6 +47,7 @@
 #include "servers/visual/visual_server_wrap_mt.h"
 #include "stream_peer_winsock.h"
 #include "tcp_server_winsock.h"
+#include "version_generated.gen.h"
 #include "windows_terminal_logger.h"
 
 #include <process.h>
@@ -1090,7 +1091,7 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
 
 	//RegisterTouchWindow(hWnd, 0); // Windows 7
 
-	_ensure_data_dir();
+	_ensure_user_data_dir();
 
 	DragAcceptFiles(hWnd, true);
 
@@ -2131,6 +2132,43 @@ MainLoop *OS_Windows::get_main_loop() const {
 	return main_loop;
 }
 
+String OS_Windows::get_config_path() const {
+
+	if (has_environment("XDG_CONFIG_HOME")) { // unlikely, but after all why not?
+		return get_environment("XDG_CONFIG_HOME");
+	} else if (has_environment("APPDATA")) {
+		return get_environment("APPDATA");
+	} else {
+		return ".";
+	}
+}
+
+String OS_Windows::get_data_path() const {
+
+	if (has_environment("XDG_DATA_HOME")) {
+		return get_environment("XDG_DATA_HOME");
+	} else {
+		return get_config_path();
+	}
+}
+
+String OS_Windows::get_cache_path() const {
+
+	if (has_environment("XDG_CACHE_HOME")) {
+		return get_environment("XDG_CACHE_HOME");
+	} else if (has_environment("TEMP")) {
+		return get_environment("TEMP");
+	} else {
+		return get_config_path();
+	}
+}
+
+// Get properly capitalized engine name for system paths
+String OS_Windows::get_godot_dir_name() const {
+
+	return String(_MKSTR(VERSION_SHORT_NAME)).capitalize();
+}
+
 String OS_Windows::get_system_dir(SystemDir p_dir) const {
 
 	int id;
@@ -2167,18 +2205,17 @@ String OS_Windows::get_system_dir(SystemDir p_dir) const {
 	ERR_FAIL_COND_V(res != S_OK, String());
 	return String(szPath);
 }
-String OS_Windows::get_data_dir() const {
 
-	String an = get_safe_application_name();
-	if (an != "") {
+String OS_Windows::get_user_data_dir() const {
 
-		if (has_environment("APPDATA")) {
+	String appname = get_safe_application_name();
+	if (appname != "") {
 
-			bool use_godot = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir");
-			if (!use_godot)
-				return (OS::get_singleton()->get_environment("APPDATA") + "/" + an).replace("\\", "/");
-			else
-				return (OS::get_singleton()->get_environment("APPDATA") + "/Godot/app_userdata/" + an).replace("\\", "/");
+		bool use_godot_dir = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir");
+		if (use_godot_dir) {
+			return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname).replace("\\", "/");
+		} else {
+			return get_data_path().plus_file(appname).replace("\\", "/");
 		}
 	}
 

+ 7 - 1
platform/windows/os_windows.h

@@ -253,8 +253,14 @@ public:
 
 	virtual void enable_for_stealing_focus(ProcessID pid);
 	virtual void move_window_to_foreground();
-	virtual String get_data_dir() const;
+
+	virtual String get_config_path() const;
+	virtual String get_data_path() const;
+	virtual String get_cache_path() const;
+	virtual String get_godot_dir_name() const;
+
 	virtual String get_system_dir(SystemDir p_dir) const;
+	virtual String get_user_data_dir() const;
 
 	virtual void release_rendering_thread();
 	virtual void make_rendering_thread();

+ 34 - 1
platform/x11/os_x11.cpp

@@ -464,7 +464,7 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
 #ifdef JOYDEV_ENABLED
 	joypad = memnew(JoypadLinux(input));
 #endif
-	_ensure_data_dir();
+	_ensure_user_data_dir();
 
 	power_manager = memnew(PowerX11);
 }
@@ -1941,6 +1941,39 @@ bool OS_X11::_check_internal_feature_support(const String &p_feature) {
 	return p_feature == "pc" || p_feature == "s3tc";
 }
 
+String OS_X11::get_config_path() const {
+
+	if (has_environment("XDG_CONFIG_HOME")) {
+		return get_environment("XDG_CONFIG_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".config");
+	} else {
+		return ".";
+	}
+}
+
+String OS_X11::get_data_path() const {
+
+	if (has_environment("XDG_DATA_HOME")) {
+		return get_environment("XDG_DATA_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".local/share");
+	} else {
+		return get_config_path();
+	}
+}
+
+String OS_X11::get_cache_path() const {
+
+	if (has_environment("XDG_CACHE_HOME")) {
+		return get_environment("XDG_CACHE_HOME");
+	} else if (has_environment("HOME")) {
+		return get_environment("HOME").plus_file(".cache");
+	} else {
+		return get_config_path();
+	}
+}
+
 String OS_X11::get_system_dir(SystemDir p_dir) const {
 
 	String xdgparam;

+ 4 - 0
platform/x11/os_x11.h

@@ -213,6 +213,10 @@ public:
 	virtual void make_rendering_thread();
 	virtual void swap_buffers();
 
+	virtual String get_config_path() const;
+	virtual String get_data_path() const;
+	virtual String get_cache_path() const;
+
 	virtual String get_system_dir(SystemDir p_dir) const;
 
 	virtual Error shell_open(String p_uri);