diff options
-rw-r--r-- | core/bind/core_bind.cpp | 5 | ||||
-rw-r--r-- | core/io/stream_peer_tcp.cpp | 11 | ||||
-rw-r--r-- | core/oa_hash_map.h | 47 | ||||
-rw-r--r-- | core/reference.cpp | 18 | ||||
-rw-r--r-- | core/reference.h | 2 | ||||
-rw-r--r-- | core/safe_refcount.h | 9 | ||||
-rw-r--r-- | doc/classes/OS.xml | 4 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 2 | ||||
-rw-r--r-- | editor/connections_dialog.cpp | 68 | ||||
-rw-r--r-- | editor/editor_node.cpp | 8 | ||||
-rw-r--r-- | editor/editor_spin_slider.cpp | 9 | ||||
-rw-r--r-- | editor/filesystem_dock.cpp | 60 | ||||
-rw-r--r-- | editor/icons/icon_rotate_left.svg | 1 | ||||
-rw-r--r-- | editor/icons/icon_rotate_right.svg | 1 | ||||
-rw-r--r-- | editor/import/editor_scene_importer_gltf.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/tile_map_editor_plugin.cpp | 4 | ||||
-rw-r--r-- | editor/script_editor_debugger.cpp | 2 | ||||
-rw-r--r-- | main/tests/test_oa_hash_map.cpp | 13 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 57 | ||||
-rw-r--r-- | scene/2d/tile_map.cpp | 14 |
20 files changed, 171 insertions, 166 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 30aaa0e646..d07ba44788 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -481,15 +481,18 @@ Error _OS::shell_open(String p_uri) { int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output, bool p_read_stderr) { OS::ProcessID pid = -2; + int exitcode = 0; List<String> args; for (int i = 0; i < p_arguments.size(); i++) args.push_back(p_arguments[i]); String pipe; - Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe, NULL, p_read_stderr); + Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe, &exitcode, p_read_stderr); p_output.clear(); p_output.push_back(pipe); if (err != OK) return -1; + else if (p_blocking) + return exitcode; else return pid; } diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 310bb12bc0..b9c5896b24 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -248,16 +248,7 @@ void StreamPeerTCP::set_no_delay(bool p_enabled) { bool StreamPeerTCP::is_connected_to_host() const { - if (status == STATUS_NONE || status == STATUS_ERROR) { - - return false; - } - - if (status != STATUS_CONNECTED) { - return true; - } - - return _sock.is_valid() && _sock->is_open(); + return _sock.is_valid() && _sock->is_open() && (status == STATUS_CONNECTED || status == STATUS_CONNECTING); } StreamPeerTCP::Status StreamPeerTCP::get_status() { diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h index 5ea6d8b0d4..1a466e57f4 100644 --- a/core/oa_hash_map.h +++ b/core/oa_hash_map.h @@ -37,10 +37,11 @@ #include "core/os/memory.h" /** - * A HashMap implementation that uses open addressing with robinhood hashing. - * Robinhood hashing swaps out entries that have a smaller probing distance + * A HashMap implementation that uses open addressing with Robin Hood hashing. + * Robin Hood hashing swaps out entries that have a smaller probing distance * than the to-be-inserted entry, that evens out the average probing distance - * and enables faster lookups. + * and enables faster lookups. Backward shift deletion is employed to further + * improve the performance and to avoid infinite loops in rare cases. * * The entries are stored inplace, so huge keys or values might fill cache lines * a lot faster. @@ -60,25 +61,20 @@ private: uint32_t num_elements; static const uint32_t EMPTY_HASH = 0; - static const uint32_t DELETED_HASH_BIT = 1 << 31; _FORCE_INLINE_ uint32_t _hash(const TKey &p_key) const { uint32_t hash = Hasher::hash(p_key); if (hash == EMPTY_HASH) { hash = EMPTY_HASH + 1; - } else if (hash & DELETED_HASH_BIT) { - hash &= ~DELETED_HASH_BIT; } return hash; } _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash) const { - p_hash = p_hash & ~DELETED_HASH_BIT; // we don't care if it was deleted or not - uint32_t original_pos = p_hash % capacity; - return (p_pos - original_pos) % capacity; + return (p_pos - original_pos + capacity) % capacity; } _FORCE_INLINE_ void _construct(uint32_t p_pos, uint32_t p_hash, const TKey &p_key, const TValue &p_value) { @@ -132,14 +128,6 @@ private: // not an empty slot, let's check the probing length of the existing one uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos]); if (existing_probe_len < distance) { - - if (hashes[pos] & DELETED_HASH_BIT) { - // we found a place where we can fit in! - _construct(pos, hash, key, value); - - return; - } - SWAP(hash, hashes[pos]); SWAP(key, keys[pos]); SWAP(value, values[pos]); @@ -173,9 +161,6 @@ private: if (old_hashes[i] == EMPTY_HASH) { continue; } - if (old_hashes[i] & DELETED_HASH_BIT) { - continue; - } _insert_with_hash(old_hashes[i], old_keys[i], old_values[i]); } @@ -205,10 +190,6 @@ public: continue; } - if (hashes[i] & DELETED_HASH_BIT) { - continue; - } - hashes[i] = EMPTY_HASH; values[i].~TValue(); keys[i].~TKey(); @@ -219,7 +200,7 @@ public: void insert(const TKey &p_key, const TValue &p_value) { - if ((float)num_elements / (float)capacity > 0.9) { + if (num_elements + 1 > 0.9 * capacity) { _resize_and_rehash(); } @@ -272,9 +253,20 @@ public: return; } - hashes[pos] |= DELETED_HASH_BIT; + uint32_t next_pos = (pos + 1) % capacity; + while (hashes[next_pos] != EMPTY_HASH && + _get_probe_length(next_pos, hashes[next_pos]) != 0) { + SWAP(hashes[next_pos], hashes[pos]); + SWAP(keys[next_pos], keys[pos]); + SWAP(values[next_pos], values[pos]); + pos = next_pos; + next_pos = (pos + 1) % capacity; + } + + hashes[pos] = EMPTY_HASH; values[pos].~TValue(); keys[pos].~TKey(); + num_elements--; } @@ -326,9 +318,6 @@ public: if (hashes[i] == EMPTY_HASH) { continue; } - if (hashes[i] & DELETED_HASH_BIT) { - continue; - } it.valid = true; it.key = &keys[i]; diff --git a/core/reference.cpp b/core/reference.cpp index 1984af9a34..92bbdacd5d 100644 --- a/core/reference.cpp +++ b/core/reference.cpp @@ -36,12 +36,7 @@ bool Reference::init_ref() { if (reference()) { - // this may fail in the scenario of two threads assigning the pointer for the FIRST TIME - // at the same time, which is never likely to happen (would be crazy to do) - // so don't do it. - - if (refcount_init.get() > 0) { - refcount_init.unref(); + if (!is_referenced() && refcount_init.unref()) { unreference(); // first referencing is already 1, so compensate for the ref above } @@ -64,9 +59,11 @@ int Reference::reference_get_count() const { } bool Reference::reference() { - bool success = refcount.ref(); - if (success && refcount.get() <= 2 /* higher is not relevant */) { + uint32_t rc_val = refcount.refval(); + bool success = rc_val != 0; + + if (success && rc_val <= 2 /* higher is not relevant */) { if (get_script_instance()) { get_script_instance()->refcount_incremented(); } @@ -84,9 +81,10 @@ bool Reference::reference() { bool Reference::unreference() { - bool die = refcount.unref(); + uint32_t rc_val = refcount.unrefval(); + bool die = rc_val == 0; - if (refcount.get() <= 1 /* higher is not relevant */) { + if (rc_val <= 1 /* higher is not relevant */) { if (get_script_instance()) { bool script_ret = get_script_instance()->refcount_decremented(); die = die && script_ret; diff --git a/core/reference.h b/core/reference.h index 20ee22ddfc..b8d00a94ad 100644 --- a/core/reference.h +++ b/core/reference.h @@ -47,7 +47,7 @@ protected: static void _bind_methods(); public: - _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() < 1; } + _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() != 1; } bool init_ref(); bool reference(); // returns false if refcount is at zero and didn't get increased bool unreference(); diff --git a/core/safe_refcount.h b/core/safe_refcount.h index 54f540b0c7..47161eed57 100644 --- a/core/safe_refcount.h +++ b/core/safe_refcount.h @@ -177,12 +177,12 @@ struct SafeRefCount { public: // destroy() is called when weak_count_ drops to zero. - _ALWAYS_INLINE_ bool ref() { //true on success + _ALWAYS_INLINE_ bool ref() { // true on success return atomic_conditional_increment(&count) != 0; } - _ALWAYS_INLINE_ uint32_t refval() { //true on success + _ALWAYS_INLINE_ uint32_t refval() { // none-zero on success return atomic_conditional_increment(&count); } @@ -192,6 +192,11 @@ public: return atomic_decrement(&count) == 0; } + _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of + + return atomic_decrement(&count); + } + _ALWAYS_INLINE_ uint32_t get() const { // nothrow return count; diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 9f61245819..9acddb3115 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -105,11 +105,11 @@ This method has slightly different behavior based on whether the [code]blocking[/code] mode is enabled. If [code]blocking[/code] is [code]true[/code], the Godot thread will pause its execution while waiting for the process to terminate. The shell output of the process will be written to the [code]output[/code] array as a single string. When the process terminates, the Godot thread will resume execution. If [code]blocking[/code] is [code]false[/code], the Godot thread will continue while the new process runs. It is not possible to retrieve the shell output in non-blocking mode, so [code]output[/code] will be empty. - The return value also depends on the blocking mode. When blocking, the method will return -2 (no process ID information is available in blocking mode). When non-blocking, the method returns a process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process forking (non-blocking) or opening (blocking) fails, the method will return [code]-1[/code]. + The return value also depends on the blocking mode. When blocking, the method will return an exit code of the process. When non-blocking, the method returns a process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process forking (non-blocking) or opening (blocking) fails, the method will return [code]-1[/code] or another exit code. Example of blocking mode and retrieving the shell output: [codeblock] var output = [] - OS.execute("ls", ["-l", "/tmp"], true, output) + var exit_code = OS.execute("ls", ["-l", "/tmp"], true, output) [/codeblock] Example of non-blocking mode, running another instance of the project and storing its process ID: [codeblock] diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index bc57c0b8df..80d7a2ccaa 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -314,7 +314,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo } int rv = pclose(f); if (r_exitcode) - *r_exitcode = rv; + *r_exitcode = WEXITSTATUS(rv); return OK; } diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index cfc2ec11cf..1e5eabc24e 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -108,8 +108,8 @@ public: }; /* -Signal automatically called by parent dialog. -*/ + * Signal automatically called by parent dialog. + */ void ConnectDialog::ok_pressed() { if (dst_method->get_text() == "") { @@ -134,8 +134,8 @@ void ConnectDialog::_cancel_pressed() { } /* -Called each time a target node is selected within the target node tree. -*/ + * Called each time a target node is selected within the target node tree. + */ void ConnectDialog::_tree_node_selected() { Node *current = tree->get_selected(); @@ -148,8 +148,8 @@ void ConnectDialog::_tree_node_selected() { } /* -Adds a new parameter bind to connection. -*/ + * Adds a new parameter bind to connection. + */ void ConnectDialog::_add_bind() { if (cdbinds->params.size() >= VARIANT_ARG_MAX) @@ -184,8 +184,8 @@ void ConnectDialog::_add_bind() { } /* -Remove parameter bind from connection. -*/ + * Remove parameter bind from connection. + */ void ConnectDialog::_remove_bind() { String st = bind_editor->get_selected_path(); @@ -265,18 +265,18 @@ bool ConnectDialog::get_oneshot() const { } /* -Returns true if ConnectDialog is being used to edit an existing connection. -*/ + * Returns true if ConnectDialog is being used to edit an existing connection. + */ bool ConnectDialog::is_editing() const { return bEditMode; } /* -Initialize ConnectDialog and populate fields with expected data. -If creating a connection from scratch, sensible defaults are used. -If editing an existing connection, previous data is retained. -*/ + * Initialize ConnectDialog and populate fields with expected data. + * If creating a connection from scratch, sensible defaults are used. + * If editing an existing connection, previous data is retained. + */ void ConnectDialog::init(Connection c, bool bEdit) { source = static_cast<Node *>(c.source); @@ -482,9 +482,9 @@ struct _ConnectionsDockMethodInfoSort { }; /* -Post-ConnectDialog callback for creating/editing connections. -Creates or edits connections based on state of the ConnectDialog when "Connect" is pressed. -*/ + * Post-ConnectDialog callback for creating/editing connections. + * Creates or edits connections based on state of the ConnectDialog when "Connect" is pressed. + */ void ConnectionsDock::_make_or_edit_connection() { TreeItem *it = tree->get_selected(); @@ -552,8 +552,8 @@ void ConnectionsDock::_make_or_edit_connection() { } /* -Creates single connection w/ undo-redo functionality. -*/ + * Creates single connection w/ undo-redo functionality. + */ void ConnectionsDock::_connect(Connection cToMake) { Node *source = static_cast<Node *>(cToMake.source); @@ -575,8 +575,8 @@ void ConnectionsDock::_connect(Connection cToMake) { } /* -Break single connection w/ undo-redo functionality. -*/ + * Break single connection w/ undo-redo functionality. + */ void ConnectionsDock::_disconnect(TreeItem &item) { Connection c = item.get_metadata(0); @@ -595,9 +595,9 @@ void ConnectionsDock::_disconnect(TreeItem &item) { } /* -Break all connections of currently selected signal. -Can undo-redo as a single action. -*/ + * Break all connections of currently selected signal. + * Can undo-redo as a single action. + */ void ConnectionsDock::_disconnect_all() { TreeItem *item = tree->get_selected(); @@ -659,8 +659,8 @@ bool ConnectionsDock::_is_item_signal(TreeItem &item) { } /* -Open connection dialog with TreeItem data to CREATE a brand-new connection. -*/ + * Open connection dialog with TreeItem data to CREATE a brand-new connection. + */ void ConnectionsDock::_open_connection_dialog(TreeItem &item) { String signal = item.get_metadata(0).operator Dictionary()["name"]; @@ -700,8 +700,8 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &item) { } /* -Open connection dialog with Connection data to EDIT an existing connection. -*/ + * Open connection dialog with Connection data to EDIT an existing connection. + */ void ConnectionsDock::_open_connection_dialog(Connection cToEdit) { Node *src = static_cast<Node *>(cToEdit.source); @@ -715,8 +715,8 @@ void ConnectionsDock::_open_connection_dialog(Connection cToEdit) { } /* -Open slot method location in script editor. -*/ + * Open slot method location in script editor. + */ void ConnectionsDock::_go_to_script(TreeItem &item) { if (_is_item_signal(item)) @@ -914,7 +914,6 @@ void ConnectionsDock::update_tree() { String signaldesc = "("; PoolStringArray argnames; if (mi.arguments.size()) { - signaldesc += " "; for (int i = 0; i < mi.arguments.size(); i++) { PropertyInfo &pi = mi.arguments[i]; @@ -927,10 +926,9 @@ void ConnectionsDock::update_tree() { } else if (pi.type != Variant::NIL) { tname = Variant::get_type_name(pi.type); } - signaldesc += tname + " " + (pi.name == "" ? String("arg " + itos(i)) : pi.name); + signaldesc += (pi.name == "" ? String("arg " + itos(i)) : pi.name) + ": " + tname; argnames.push_back(pi.name + ":" + tname); } - signaldesc += " "; } signaldesc += ")"; @@ -1000,14 +998,14 @@ void ConnectionsDock::update_tree() { path += " (oneshot)"; if (c.binds.size()) { - path += " binds( "; + path += " binds("; for (int i = 0; i < c.binds.size(); i++) { if (i > 0) path += ", "; path += c.binds[i].operator String(); } - path += " )"; + path += ")"; } TreeItem *item2 = tree->create_item(item); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index df1e8005ed..05b50d5dfe 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2365,6 +2365,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } } break; + case RUN_PROJECT_DATA_FOLDER: { + OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir()); + } break; case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: { OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().plus_file("android")); } break; @@ -2571,8 +2574,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { save_all_scenes(); restart_editor(); } break; - default: { - } } } @@ -2605,9 +2606,6 @@ void EditorNode::_tool_menu_option(int p_idx) { case TOOLS_ORPHAN_RESOURCES: { orphan_resources->show(); } break; - case RUN_PROJECT_DATA_FOLDER: { - OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir()); - } break; case TOOLS_CUSTOM: { if (tool_menu->get_item_submenu(p_idx) == "") { Array params = tool_menu->get_item_metadata(p_idx); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 35fe366526..918b0ef96d 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -109,13 +109,8 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { } if (grabbing_spinner) { - if (mm->get_control() || updown_offset != -1) { - set_value(Math::round(get_value())); - if (ABS(grabbing_spinner_dist_cache) > 6) { - set_value(get_value() + SGN(grabbing_spinner_dist_cache)); - grabbing_spinner_dist_cache = 0; - pre_grab_value = get_value(); - } + if (mm->get_control()) { + set_value(Math::round(pre_grab_value + get_step() * grabbing_spinner_dist_cache * 10)); } else { set_value(pre_grab_value + get_step() * grabbing_spinner_dist_cache * 10); } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 426ea8f196..e3f0021fbc 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -477,6 +477,7 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa } void FileSystemDock::navigate_to_path(const String &p_path) { + file_list_search_box->clear(); _navigate_to_path(p_path); } @@ -2099,6 +2100,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str bool all_folders = true; bool all_favorites = true; bool all_not_favorites = true; + for (int i = 0; i < p_paths.size(); i++) { String fpath = p_paths[i]; if (fpath.ends_with("/")) { @@ -2128,25 +2130,25 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str if (all_files) { if (all_files_scenes) { if (filenames.size() == 1) { - p_popup->add_item(TTR("Open Scene"), FILE_OPEN); - p_popup->add_item(TTR("New Inherited Scene"), FILE_INHERIT); + p_popup->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open Scene"), FILE_OPEN); + p_popup->add_icon_item(get_icon("CreateNewSceneFrom", "EditorIcons"), TTR("New Inherited Scene"), FILE_INHERIT); } else { - p_popup->add_item(TTR("Open Scenes"), FILE_OPEN); + p_popup->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open Scenes"), FILE_OPEN); } - p_popup->add_item(TTR("Instance"), FILE_INSTANCE); + p_popup->add_icon_item(get_icon("Instance", "EditorIcons"), TTR("Instance"), FILE_INSTANCE); p_popup->add_separator(); } else if (filenames.size() == 1) { - p_popup->add_item(TTR("Open"), FILE_OPEN); + p_popup->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open"), FILE_OPEN); p_popup->add_separator(); } } if (p_paths.size() >= 1) { if (!all_favorites) { - p_popup->add_item(TTR("Add to Favorites"), FILE_ADD_FAVORITE); + p_popup->add_icon_item(get_icon("Favorites", "EditorIcons"), TTR("Add to Favorites"), FILE_ADD_FAVORITE); } if (!all_not_favorites) { - p_popup->add_item(TTR("Remove from Favorites"), FILE_REMOVE_FAVORITE); + p_popup->add_icon_item(get_icon("NonFavorite", "EditorIcons"), TTR("Remove from Favorites"), FILE_REMOVE_FAVORITE); } p_popup->add_separator(); } @@ -2159,36 +2161,36 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str } } else if (all_folders && foldernames.size() > 0) { - p_popup->add_item(TTR("Open"), FILE_OPEN); + p_popup->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open"), FILE_OPEN); p_popup->add_separator(); } if (p_paths.size() == 1) { - p_popup->add_item(TTR("Copy Path"), FILE_COPY_PATH); + p_popup->add_icon_item(get_icon("ActionCopy", "EditorIcons"), TTR("Copy Path"), FILE_COPY_PATH); if (p_paths[0] != "res://") { - p_popup->add_item(TTR("Rename..."), FILE_RENAME); - p_popup->add_item(TTR("Duplicate..."), FILE_DUPLICATE); + p_popup->add_icon_item(get_icon("Rename", "EditorIcons"), TTR("Rename..."), FILE_RENAME); + p_popup->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Duplicate..."), FILE_DUPLICATE); } } if (p_paths.size() > 1 || p_paths[0] != "res://") { - p_popup->add_item(TTR("Move To..."), FILE_MOVE); - p_popup->add_item(TTR("Delete"), FILE_REMOVE); + p_popup->add_icon_item(get_icon("MoveUp", "EditorIcons"), TTR("Move To..."), FILE_MOVE); + p_popup->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete"), FILE_REMOVE); } if (p_paths.size() == 1) { p_popup->add_separator(); if (p_display_path_dependent_options) { - p_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); - p_popup->add_item(TTR("New Scene..."), FILE_NEW_SCENE); - p_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); - p_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); + p_popup->add_icon_item(get_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); + p_popup->add_icon_item(get_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); + p_popup->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); + p_popup->add_icon_item(get_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); p_popup->add_separator(); } String fpath = p_paths[0]; String item_text = fpath.ends_with("/") ? TTR("Open in File Manager") : TTR("Show in File Manager"); - p_popup->add_item(item_text, FILE_SHOW_IN_EXPLORER); + p_popup->add_icon_item(get_icon("Filesystem", "EditorIcons"), item_text, FILE_SHOW_IN_EXPLORER); } } @@ -2198,8 +2200,8 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { if (paths.size() == 1) { if (paths[0].ends_with("/")) { - tree_popup->add_item(TTR("Expand All"), FOLDER_EXPAND_ALL); - tree_popup->add_item(TTR("Collapse All"), FOLDER_COLLAPSE_ALL); + tree_popup->add_icon_item(get_icon("GuiTreeArrowDown", "EditorIcons"), TTR("Expand All"), FOLDER_EXPAND_ALL); + tree_popup->add_icon_item(get_icon("GuiTreeArrowRight", "EditorIcons"), TTR("Collapse All"), FOLDER_COLLAPSE_ALL); tree_popup->add_separator(); } } @@ -2219,10 +2221,10 @@ void FileSystemDock::_tree_rmb_empty(const Vector2 &p_pos) { path = "res://"; tree_popup->clear(); tree_popup->set_size(Size2(1, 1)); - tree_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); - tree_popup->add_item(TTR("New Scene..."), FILE_NEW_SCENE); - tree_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); - tree_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); + tree_popup->add_icon_item(get_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); + tree_popup->add_icon_item(get_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); + tree_popup->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); + tree_popup->add_icon_item(get_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); tree_popup->set_position(tree->get_global_position() + p_pos); tree_popup->popup(); } @@ -2262,12 +2264,12 @@ void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) { file_list_popup->clear(); file_list_popup->set_size(Size2(1, 1)); - file_list_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); - file_list_popup->add_item(TTR("New Scene..."), FILE_NEW_SCENE); - file_list_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); - file_list_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); + file_list_popup->add_icon_item(get_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); + file_list_popup->add_icon_item(get_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); + file_list_popup->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); + file_list_popup->add_icon_item(get_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); file_list_popup->add_separator(); - file_list_popup->add_item(TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER); + file_list_popup->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER); file_list_popup->set_position(files->get_global_position() + p_pos); file_list_popup->popup(); } diff --git a/editor/icons/icon_rotate_left.svg b/editor/icons/icon_rotate_left.svg new file mode 100644 index 0000000000..223a725332 --- /dev/null +++ b/editor/icons/icon_rotate_left.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg>
\ No newline at end of file diff --git a/editor/icons/icon_rotate_right.svg b/editor/icons/icon_rotate_right.svg new file mode 100644 index 0000000000..2b66bae998 --- /dev/null +++ b/editor/icons/icon_rotate_right.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="matrix(-1 0 0 1 16.026308 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg>
\ No newline at end of file diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index df5511f540..49091dc812 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -156,7 +156,7 @@ static Transform _arr_to_xform(const Array &p_array) { } String EditorSceneImporterGLTF::_sanitize_scene_name(const String &name) { - RegEx regex("([^a-zA-Z0-9_ ]+)"); + RegEx regex("([^a-zA-Z0-9_ -]+)"); String p_name = regex.sub(name, "", true); return p_name; } diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 86d538e702..2d66087699 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -71,8 +71,8 @@ void TileMapEditor::_notification(int p_what) { picker_button->set_icon(get_icon("ColorPick", "EditorIcons")); select_button->set_icon(get_icon("ActionCopy", "EditorIcons")); - rotate_left_button->set_icon(get_icon("Rotate270", "EditorIcons")); - rotate_right_button->set_icon(get_icon("Rotate90", "EditorIcons")); + rotate_left_button->set_icon(get_icon("RotateLeft", "EditorIcons")); + rotate_right_button->set_icon(get_icon("RotateRight", "EditorIcons")); flip_horizontal_button->set_icon(get_icon("MirrorX", "EditorIcons")); flip_vertical_button->set_icon(get_icon("MirrorY", "EditorIcons")); clear_transform_button->set_icon(get_icon("Clear", "EditorIcons")); diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 6a9dbb103a..e96dfdd7b9 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -423,10 +423,12 @@ void ScriptEditorDebugger::_scene_tree_request() { int ScriptEditorDebugger::_update_scene_tree(TreeItem *parent, const Array &nodes, int current_index) { String filter = EditorNode::get_singleton()->get_scene_tree_dock()->get_filter(); String item_text = nodes[current_index + 1]; + String item_type = nodes[current_index + 2]; bool keep = filter.is_subsequence_ofi(item_text); TreeItem *item = inspect_scene_tree->create_item(parent); item->set_text(0, item_text); + item->set_tooltip(0, TTR("Type:") + " " + item_type); ObjectID id = ObjectID(nodes[current_index + 3]); Ref<Texture> icon = EditorNode::get_singleton()->get_class_icon(nodes[current_index + 2], ""); if (icon.is_valid()) { diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp index bf5b4588ea..beee52d1de 100644 --- a/main/tests/test_oa_hash_map.cpp +++ b/main/tests/test_oa_hash_map.cpp @@ -140,6 +140,19 @@ MainLoop *test() { OS::get_singleton()->print("test for issue #31402 passed.\n"); } + // test collision resolution, should not crash or run indefinitely + { + OAHashMap<int, int> map(4); + map.set(1, 1); + map.set(5, 1); + map.set(9, 1); + map.set(13, 1); + map.remove(5); + map.remove(9); + map.remove(13); + map.set(5, 1); + } + return NULL; } } // namespace TestOAHashMap diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 915a01af7e..b2e1deca01 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -119,26 +119,29 @@ void gdmono_debug_init() { mono_debug_init(MONO_DEBUG_FORMAT_MONO); + CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8(); + +#ifdef TOOLS_ENABLED int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685); bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false); int da_timeout = GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000); - CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8(); - -#ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint() || ProjectSettings::get_singleton()->get_resource_path().empty() || Main::is_project_manager()) { if (da_args.size() == 0) return; } -#endif if (da_args.length() == 0) { da_args = String("--debugger-agent=transport=dt_socket,address=127.0.0.1:" + itos(da_port) + ",embedding=1,server=y,suspend=" + (da_suspend ? "y,timeout=" + itos(da_timeout) : "n")) .utf8(); } +#else + if (da_args.length() == 0) + return; // Exported games don't use the project settings to setup the debugger agent +#endif // --debugger-agent=help const char *options[] = { @@ -761,7 +764,9 @@ bool GDMono::_try_load_api_assemblies() { void GDMono::_load_api_assemblies() { - if (!_try_load_api_assemblies()) { + bool api_assemblies_loaded = _try_load_api_assemblies(); + + if (!api_assemblies_loaded) { #ifdef TOOLS_ENABLED // The API assemblies are out of sync. Fine, try one more time, but this time // update them from the prebuilt assemblies directory before trying to load them. @@ -782,28 +787,30 @@ void GDMono::_load_api_assemblies() { CRASH_COND_MSG(domain_load_err != OK, "Mono: Failed to load scripts domain."); // 4. Try loading the updated assemblies - if (!_try_load_api_assemblies()) { - // welp... too bad - - if (_are_api_assemblies_out_of_sync()) { - if (core_api_assembly_out_of_sync) { - ERR_PRINT("The assembly '" CORE_API_ASSEMBLY_NAME "' is out of sync."); - } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { - ERR_PRINT("The loaded assembly '" CORE_API_ASSEMBLY_NAME "' is in sync, but the cache update failed."); - } - - if (editor_api_assembly_out_of_sync) { - ERR_PRINT("The assembly '" EDITOR_API_ASSEMBLY_NAME "' is out of sync."); - } - - CRASH_NOW(); - } else { - CRASH_NOW_MSG("Failed to load one of the API assemblies."); + api_assemblies_loaded = _try_load_api_assemblies(); +#endif + } + + if (!api_assemblies_loaded) { + // welp... too bad + + if (_are_api_assemblies_out_of_sync()) { + if (core_api_assembly_out_of_sync) { + ERR_PRINT("The assembly '" CORE_API_ASSEMBLY_NAME "' is out of sync."); + } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { + ERR_PRINT("The loaded assembly '" CORE_API_ASSEMBLY_NAME "' is in sync, but the cache update failed."); + } + +#ifdef TOOLS_ENABLED + if (editor_api_assembly_out_of_sync) { + ERR_PRINT("The assembly '" EDITOR_API_ASSEMBLY_NAME "' is out of sync."); } - } -#else - CRASH_NOW_MSG("Failed to load one of the API assemblies."); #endif + + CRASH_NOW(); + } else { + CRASH_NOW_MSG("Failed to load one of the API assemblies."); + } } } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index c0c1d8f691..2bfdfd7d02 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -1549,7 +1549,8 @@ Vector2 TileMap::_map_to_world(int p_x, int p_y, bool p_ignore_ofs) const { ret += get_cell_transform()[1] * (half_offset == HALF_OFFSET_Y ? 0.5 : -0.5); } } break; - default: { + case HALF_OFFSET_DISABLED: { + // Nothing to do. } } } @@ -1612,26 +1613,27 @@ Vector2 TileMap::world_to_map(const Vector2 &p_pos) const { switch (half_offset) { case HALF_OFFSET_X: { - if (ret.y > 0 ? int(ret.y) & 1 : (int(ret.y) - 1) & 1) { + if (int(floor(ret.y)) & 1) { ret.x -= 0.5; } } break; case HALF_OFFSET_NEGATIVE_X: { - if (ret.y > 0 ? int(ret.y) & 1 : (int(ret.y) - 1) & 1) { + if (int(floor(ret.y)) & 1) { ret.x += 0.5; } } break; case HALF_OFFSET_Y: { - if (ret.x > 0 ? int(ret.x) & 1 : (int(ret.x) - 1) & 1) { + if (int(floor(ret.x)) & 1) { ret.y -= 0.5; } } break; case HALF_OFFSET_NEGATIVE_Y: { - if (ret.x > 0 ? int(ret.x) & 1 : (int(ret.x) - 1) & 1) { + if (int(floor(ret.x)) & 1) { ret.y += 0.5; } } break; - default: { + case HALF_OFFSET_DISABLED: { + // Nothing to do. } } |