Browse Source

Merge pull request #46931 from akien-mga/3.2-cherrypicks

Cherry-picks for the 3.2 branch (future 3.2.4) - 28th batch
Rémi Verschelde 4 years ago
parent
commit
e3b16be6cd

+ 2 - 0
core/bind/core_bind.cpp

@@ -798,6 +798,8 @@ Dictionary _OS::get_time(bool utc) const {
  * @return epoch calculated
  */
 int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
+	// if datetime is an empty Dictionary throws an error
+	ERR_FAIL_COND_V_MSG(datetime.empty(), 0, "Invalid datetime Dictionary: Dictionary is empty");
 
 	// Bunch of conversion constants
 	static const unsigned int SECONDS_PER_MINUTE = 60;

+ 5 - 1
core/os/thread.cpp

@@ -47,7 +47,7 @@ uint64_t Thread::_thread_id_hash(const std::thread::id &p_t) {
 }
 
 Thread::ID Thread::main_thread_id = _thread_id_hash(std::this_thread::get_id());
-thread_local Thread::ID Thread::caller_id = _thread_id_hash(std::this_thread::get_id());
+thread_local Thread::ID Thread::caller_id = 0;
 
 void Thread::_set_platform_funcs(
 		Error (*p_set_name_func)(const String &),
@@ -112,6 +112,10 @@ Error Thread::set_name(const String &p_name) {
 	return ERR_UNAVAILABLE;
 }
 
+Thread::Thread() {
+	caller_id = _thread_id_hash(std::this_thread::get_id());
+}
+
 Thread::~Thread() {
 	if (id != _thread_id_hash(std::thread::id())) {
 #ifdef DEBUG_ENABLED

+ 1 - 0
core/os/thread.h

@@ -98,6 +98,7 @@ public:
 	///< waits until thread is finished, and deallocates it.
 	void wait_to_finish();
 
+	Thread();
 	~Thread();
 #else
 	_FORCE_INLINE_ ID get_id() const { return 0; }

+ 1 - 0
doc/classes/OS.xml

@@ -549,6 +549,7 @@
 			<description>
 				Gets an epoch time value from a dictionary of time values.
 				[code]datetime[/code] must be populated with the following keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]hour[/code], [code]minute[/code], [code]second[/code].
+				If the dictionary is empty [code]0[/code] is returned.
 				You can pass the output from [method get_datetime_from_unix_time] directly into this function. Daylight Savings Time ([code]dst[/code]), if present, is ignored.
 			</description>
 		</method>

+ 1 - 1
doc/classes/Physics2DServer.xml

@@ -58,7 +58,7 @@
 			<return type="RID">
 			</return>
 			<description>
-				Creates an [Area2D].
+				Creates an [Area2D]. After creating an [Area2D] with this method, assign it to a space using [method area_set_space] to use the created [Area2D] in the physics world.
 			</description>
 		</method>
 		<method name="area_get_canvas_instance_id" qualifiers="const">

+ 39 - 12
editor/editor_export.cpp

@@ -299,6 +299,7 @@ void EditorExportPlatform::gen_debug_flags(Vector<String> &r_flags, int p_flags)
 }
 
 Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) {
+	ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export.");
 
 	PackData *pd = (PackData *)p_userdata;
 
@@ -332,6 +333,7 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa
 }
 
 Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) {
+	ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export.");
 
 	String path = p_path.replace_first("res://", "");
 
@@ -740,18 +742,26 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
 	// Ignore import files, since these are automatically added to the jar later with the resources
 	_edit_filter_list(paths, String("*.import"), true);
 
+	Error err = OK;
 	Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
+
 	for (int i = 0; i < export_plugins.size(); i++) {
 
 		export_plugins.write[i]->set_export_preset(p_preset);
 
 		if (p_so_func) {
 			for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) {
-				p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
+				err = p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
+				if (err != OK) {
+					return err;
+				}
 			}
 		}
 		for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) {
-			p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size());
+			err = p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size());
+			if (err != OK) {
+				return err;
+			}
 		}
 
 		export_plugins.write[i]->_clear();
@@ -774,7 +784,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
 			//file is imported, replace by what it imports
 			Ref<ConfigFile> config;
 			config.instance();
-			Error err = config->load(path + ".import");
+			err = config->load(path + ".import");
 			if (err != OK) {
 				ERR_PRINTS("Could not parse: '" + path + "', not exported.");
 				continue;
@@ -841,12 +851,18 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
 				}
 				if (p_so_func) {
 					for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) {
-						p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
+						err = p_so_func(p_udata, export_plugins[i]->shared_objects[j]);
+						if (err != OK) {
+							return err;
+						}
 					}
 				}
 
 				for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) {
-					p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total);
+					err = p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total);
+					if (err != OK) {
+						return err;
+					}
 					if (export_plugins[i]->extra_files[j].remap) {
 						do_export = false; //if remap, do not
 						path_remaps.push_back(path);
@@ -865,7 +881,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
 			//just store it as it comes
 			if (do_export) {
 				Vector<uint8_t> array = FileAccess::get_file_as_array(path);
-				p_func(p_udata, path, array, idx, total);
+				err = p_func(p_udata, path, array, idx, total);
+				if (err != OK) {
+					return err;
+				}
 			}
 		}
 
@@ -902,7 +921,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
 					new_file.write[j] = utf8[j];
 				}
 
-				p_func(p_udata, from + ".remap", new_file, idx, total);
+				err = p_func(p_udata, from + ".remap", new_file, idx, total);
+				if (err != OK) {
+					return err;
+				}
 			}
 		} else {
 			//old remap mode, will still work, but it's unused because it's not multiple pck export friendly
@@ -915,11 +937,17 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
 	String splash = ProjectSettings::get_singleton()->get("application/boot_splash/image");
 	if (icon != String() && FileAccess::exists(icon)) {
 		Vector<uint8_t> array = FileAccess::get_file_as_array(icon);
-		p_func(p_udata, icon, array, idx, total);
+		err = p_func(p_udata, icon, array, idx, total);
+		if (err != OK) {
+			return err;
+		}
 	}
 	if (splash != String() && FileAccess::exists(splash) && icon != splash) {
 		Vector<uint8_t> array = FileAccess::get_file_as_array(splash);
-		p_func(p_udata, splash, array, idx, total);
+		err = p_func(p_udata, splash, array, idx, total);
+		if (err != OK) {
+			return err;
+		}
 	}
 
 	String config_file = "project.binary";
@@ -928,9 +956,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
 	Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
 	DirAccess::remove_file_or_error(engine_cfb);
 
-	p_func(p_udata, "res://" + config_file, data, idx, total);
-
-	return OK;
+	return p_func(p_udata, "res://" + config_file, data, idx, total);
 }
 
 Error EditorExportPlatform::_add_shared_object(void *p_userdata, const SharedObject &p_so) {
@@ -965,6 +991,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
 
 	if (err != OK) {
 		DirAccess::remove_file_or_error(tmppath);
+		ERR_PRINT("Failed to export project files");
 		return err;
 	}
 

+ 40 - 32
editor/plugins/canvas_item_editor_plugin.cpp

@@ -924,9 +924,11 @@ void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_it
 	for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
 		CanvasItem *canvas_item = E->get();
 		CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
-		canvas_item->_edit_set_state(se->undo_state);
-		if (restore_bones) {
-			_restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state));
+		if (se) {
+			canvas_item->_edit_set_state(se->undo_state);
+			if (restore_bones) {
+				_restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state));
+			}
 		}
 	}
 }
@@ -951,13 +953,15 @@ void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_ite
 	for (List<CanvasItem *>::Element *E = modified_canvas_items.front(); E; E = E->next()) {
 		CanvasItem *canvas_item = E->get();
 		CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
-		undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
-		undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
-		if (commit_bones) {
-			for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) {
-				canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
-				undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
-				undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get());
+		if (se) {
+			undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
+			undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
+			if (commit_bones) {
+				for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) {
+					canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
+					undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
+					undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get());
+				}
 			}
 		}
 	}
@@ -2126,17 +2130,19 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
 			for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
 				CanvasItem *canvas_item = E->get();
 				CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
-				Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
-
-				Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
-				if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) {
-					real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
-					_restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
-					real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
-					node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
-					_solve_IK(node2d, new_pos);
-				} else {
-					canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+				if (se) {
+					Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
+
+					Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
+					if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) {
+						real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
+						_restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
+						real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
+						node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
+						_solve_IK(node2d, new_pos);
+					} else {
+						canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+					}
 				}
 				index++;
 			}
@@ -2258,17 +2264,19 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
 			for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
 				CanvasItem *canvas_item = E->get();
 				CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
-				Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
-
-				Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
-				if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
-					real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
-					_restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
-					real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
-					node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
-					_solve_IK(node2d, new_pos);
-				} else {
-					canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+				if (se) {
+					Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
+
+					Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
+					if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
+						real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
+						_restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
+						real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
+						node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
+						_solve_IK(node2d, new_pos);
+					} else {
+						canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
+					}
 				}
 				index++;
 			}

+ 2 - 2
misc/dist/html/editor.html

@@ -502,7 +502,7 @@
 									showTab('loader');
 									setLoaderEnabled(true);
 								};
-								editor.start({'args': args});
+								editor.start({'args': args, 'persistentDrops': is_project_manager});
 							});
 						}, 0);
 						OnEditorExit = null;
@@ -563,7 +563,7 @@
 					//selectVideoMode();
 					showTab('editor');
 					setLoaderEnabled(false);
-					editor.start({'args': ['--video-driver', video_driver]}).then(function() {
+					editor.start({'args': ['--project-manager', '--video-driver', video_driver], 'persistentDrops': true}).then(function() {
 						setStatusMode('hidden');
 						initializing = false;
 					});

+ 3 - 1
modules/gdnative/include/gdnative/gdnative.h

@@ -53,7 +53,9 @@ extern "C" {
 #endif
 
 // This is for libraries *using* the header, NOT GODOT EXPOSING STUFF!!
-#ifdef _WIN32
+#ifdef __GNUC__
+#define GDN_EXPORT __attribute__((visibility("default")))
+#elif defined(_WIN32)
 #define GDN_EXPORT __declspec(dllexport)
 #else
 #define GDN_EXPORT

+ 7 - 0
platform/javascript/js/engine/config.js

@@ -103,6 +103,11 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
 		 * @type {Array.<string>}
 		 */
 		persistentPaths: ['/userfs'],
+		/**
+		 * @ignore
+		 * @type {boolean}
+		 */
+		persistentDrops: false,
 		/**
 		 * @ignore
 		 * @type {Array.<string>}
@@ -231,6 +236,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
 		this.locale = parse('locale', this.locale);
 		this.canvasResizePolicy = parse('canvasResizePolicy', this.canvasResizePolicy);
 		this.persistentPaths = parse('persistentPaths', this.persistentPaths);
+		this.persistentDrops = parse('persistentDrops', this.persistentDrops);
 		this.experimentalVK = parse('experimentalVK', this.experimentalVK);
 		this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs);
 		this.fileSizes = parse('fileSizes', this.fileSizes);
@@ -316,6 +322,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
 			'canvas': this.canvas,
 			'canvasResizePolicy': this.canvasResizePolicy,
 			'locale': locale,
+			'persistentDrops': this.persistentDrops,
 			'virtualKeyboard': this.experimentalVK,
 			'onExecute': this.onExecute,
 			'onExit': function (p_code) {

+ 39 - 26
platform/javascript/js/libs/library_godot_display.js

@@ -192,33 +192,45 @@ const GodotDisplayDragDrop = {
 				GodotDisplayDragDrop.promises = [];
 				GodotDisplayDragDrop.pending_files = [];
 				callback(drops);
-				const dirs = [DROP.substr(0, DROP.length - 1)];
-				// Remove temporary files
-				files.forEach(function (file) {
-					FS.unlink(file);
-					let dir = file.replace(DROP, '');
-					let idx = dir.lastIndexOf('/');
-					while (idx > 0) {
-						dir = dir.substr(0, idx);
-						if (dirs.indexOf(DROP + dir) === -1) {
-							dirs.push(DROP + dir);
-						}
-						idx = dir.lastIndexOf('/');
-					}
-				});
-				// Remove dirs.
-				dirs.sort(function (a, b) {
-					const al = (a.match(/\//g) || []).length;
-					const bl = (b.match(/\//g) || []).length;
-					if (al > bl) {
-						return -1;
-					} else if (al < bl) {
-						return 1;
+				if (GodotConfig.persistent_drops) {
+					// Delay removal at exit.
+					GodotOS.atexit(function (resolve, reject) {
+						GodotDisplayDragDrop.remove_drop(files, DROP);
+						resolve();
+					});
+				} else {
+					GodotDisplayDragDrop.remove_drop(files, DROP);
+				}
+			});
+		},
+
+		remove_drop: function (files, drop_path) {
+			const dirs = [drop_path.substr(0, drop_path.length - 1)];
+			// Remove temporary files
+			files.forEach(function (file) {
+				FS.unlink(file);
+				let dir = file.replace(drop_path, '');
+				let idx = dir.lastIndexOf('/');
+				while (idx > 0) {
+					dir = dir.substr(0, idx);
+					if (dirs.indexOf(drop_path + dir) === -1) {
+						dirs.push(drop_path + dir);
 					}
-					return 0;
-				}).forEach(function (dir) {
-					FS.rmdir(dir);
-				});
+					idx = dir.lastIndexOf('/');
+				}
+			});
+			// Remove dirs.
+			dirs.sort(function (a, b) {
+				const al = (a.match(/\//g) || []).length;
+				const bl = (b.match(/\//g) || []).length;
+				if (al > bl) {
+					return -1;
+				} else if (al < bl) {
+					return 1;
+				}
+				return 0;
+			}).forEach(function (dir) {
+				FS.rmdir(dir);
 			});
 		},
 
@@ -908,6 +920,7 @@ const GodotDisplay = {
 			canvas.style.left = 0;
 			break;
 		}
+		GodotDisplayScreen.updateSize();
 		if (p_fullscreen) {
 			GodotDisplayScreen.requestFullscreen();
 		}

+ 3 - 0
platform/javascript/js/libs/library_godot_os.js

@@ -60,6 +60,7 @@ const GodotConfig = {
 		locale: 'en',
 		canvas_resize_policy: 2, // Adaptive
 		virtual_keyboard: false,
+		persistent_drops: false,
 		on_execute: null,
 		on_exit: null,
 
@@ -68,6 +69,7 @@ const GodotConfig = {
 			GodotConfig.canvas = p_opts['canvas'];
 			GodotConfig.locale = p_opts['locale'] || GodotConfig.locale;
 			GodotConfig.virtual_keyboard = p_opts['virtualKeyboard'];
+			GodotConfig.persistent_drops = !!p_opts['persistentDrops'];
 			GodotConfig.on_execute = p_opts['onExecute'];
 			GodotConfig.on_exit = p_opts['onExit'];
 		},
@@ -80,6 +82,7 @@ const GodotConfig = {
 			GodotConfig.locale = 'en';
 			GodotConfig.canvas_resize_policy = 2;
 			GodotConfig.virtual_keyboard = false;
+			GodotConfig.persistent_drops = false;
 			GodotConfig.on_execute = null;
 			GodotConfig.on_exit = null;
 		},

+ 3 - 1
scene/gui/control.cpp

@@ -70,7 +70,9 @@ Dictionary Control::_edit_get_state() const {
 }
 
 void Control::_edit_set_state(const Dictionary &p_state) {
-
+	ERR_FAIL_COND((p_state.size() <= 0) ||
+				  !p_state.has("rotation") || !p_state.has("scale") ||
+				  !p_state.has("pivot") || !p_state.has("anchors") || !p_state.has("offsets"));
 	Dictionary state = p_state;
 
 	set_rotation(state["rotation"]);