summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/templates/search_array.h67
-rw-r--r--core/templates/vector.h6
-rw-r--r--core/variant/array.cpp36
-rw-r--r--core/variant/variant_call.cpp9
-rw-r--r--doc/classes/PackedByteArray.xml9
-rw-r--r--doc/classes/PackedColorArray.xml9
-rw-r--r--doc/classes/PackedFloat32Array.xml9
-rw-r--r--doc/classes/PackedFloat64Array.xml9
-rw-r--r--doc/classes/PackedInt32Array.xml9
-rw-r--r--doc/classes/PackedInt64Array.xml9
-rw-r--r--doc/classes/PackedStringArray.xml9
-rw-r--r--doc/classes/PackedVector2Array.xml9
-rw-r--r--doc/classes/PackedVector3Array.xml9
-rw-r--r--doc/classes/Tabs.xml26
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/editor_themes.cpp4
-rw-r--r--editor/plugins/theme_editor_plugin.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp17
-rw-r--r--scene/3d/physics_body_3d.cpp21
-rw-r--r--scene/3d/physics_body_3d.h2
-rw-r--r--scene/gui/tabs.cpp14
-rw-r--r--scene/resources/default_theme/default_theme.cpp4
-rw-r--r--scene/resources/tile_set.h2
-rw-r--r--tests/test_vector.h13
24 files changed, 248 insertions, 60 deletions
diff --git a/core/templates/search_array.h b/core/templates/search_array.h
new file mode 100644
index 0000000000..8efc32df82
--- /dev/null
+++ b/core/templates/search_array.h
@@ -0,0 +1,67 @@
+/*************************************************************************/
+/* search_array.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef SEARCH_ARRAY_H
+#define SEARCH_ARRAY_H
+
+#include <core/templates/sort_array.h>
+
+template <class T, class Comparator = _DefaultComparator<T>>
+class SearchArray {
+public:
+ Comparator compare;
+
+ inline int bisect(const T *p_array, int p_len, const T &p_value, bool p_before) const {
+ int lo = 0;
+ int hi = p_len;
+ if (p_before) {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (compare(p_array[mid], p_value)) {
+ lo = mid + 1;
+ } else {
+ hi = mid;
+ }
+ }
+ } else {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (compare(p_value, p_array[mid])) {
+ hi = mid;
+ } else {
+ lo = mid + 1;
+ }
+ }
+ }
+ return lo;
+ }
+};
+
+#endif // SEARCH_ARRAY_H
diff --git a/core/templates/vector.h b/core/templates/vector.h
index 2600604eb7..4b008a45a4 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -40,6 +40,7 @@
#include "core/error/error_macros.h"
#include "core/os/memory.h"
#include "core/templates/cowdata.h"
+#include "core/templates/search_array.h"
#include "core/templates/sort_array.h"
template <class T>
@@ -112,6 +113,11 @@ public:
sort_custom<_DefaultComparator<T>>();
}
+ int bsearch(const T &p_value, bool p_before) {
+ SearchArray<T> search;
+ return search.bisect(ptrw(), size(), p_value, p_before);
+ }
+
Vector<T> duplicate() {
return *this;
}
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 8373cbd4e8..b4d6dffc6f 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -34,6 +34,7 @@
#include "core/object/class_db.h"
#include "core/object/script_language.h"
#include "core/templates/hashfuncs.h"
+#include "core/templates/search_array.h"
#include "core/templates/vector.h"
#include "core/variant/callable.h"
#include "core/variant/variant.h"
@@ -484,44 +485,19 @@ void Array::shuffle() {
}
}
-template <typename Less>
-_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
- int lo = 0;
- int hi = p_array.size();
- if (p_before) {
- while (lo < hi) {
- const int mid = (lo + hi) / 2;
- if (p_less(p_array.get(mid), p_value)) {
- lo = mid + 1;
- } else {
- hi = mid;
- }
- }
- } else {
- while (lo < hi) {
- const int mid = (lo + hi) / 2;
- if (p_less(p_value, p_array.get(mid))) {
- hi = mid;
- } else {
- lo = mid + 1;
- }
- }
- }
- return lo;
-}
-
int Array::bsearch(const Variant &p_value, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "binary search"), -1);
- return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
+ SearchArray<Variant, _ArrayVariantSort> avs;
+ return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
}
int Array::bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1);
- _ArrayVariantSortCustom less;
- less.func = p_callable;
+ SearchArray<Variant, _ArrayVariantSortCustom> avs;
+ avs.compare.func = p_callable;
- return bisect(_p->array, p_value, p_before, less);
+ return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
}
void Array::reverse() {
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 5682a7c7b5..6284caae2d 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1845,6 +1845,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedByteArray, reverse, sarray(), varray());
bind_method(PackedByteArray, subarray, sarray("from", "to"), varray());
bind_method(PackedByteArray, sort, sarray(), varray());
+ bind_method(PackedByteArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedByteArray, duplicate, sarray(), varray());
bind_function(PackedByteArray, get_string_from_ascii, _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray());
@@ -1906,6 +1907,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt32Array, subarray, sarray("from", "to"), varray());
bind_method(PackedInt32Array, to_byte_array, sarray(), varray());
bind_method(PackedInt32Array, sort, sarray(), varray());
+ bind_method(PackedInt32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt32Array, duplicate, sarray(), varray());
/* Int64 Array */
@@ -1925,6 +1927,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt64Array, subarray, sarray("from", "to"), varray());
bind_method(PackedInt64Array, to_byte_array, sarray(), varray());
bind_method(PackedInt64Array, sort, sarray(), varray());
+ bind_method(PackedInt64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt64Array, duplicate, sarray(), varray());
/* Float32 Array */
@@ -1944,6 +1947,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat32Array, subarray, sarray("from", "to"), varray());
bind_method(PackedFloat32Array, to_byte_array, sarray(), varray());
bind_method(PackedFloat32Array, sort, sarray(), varray());
+ bind_method(PackedFloat32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat32Array, duplicate, sarray(), varray());
/* Float64 Array */
@@ -1963,6 +1967,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat64Array, subarray, sarray("from", "to"), varray());
bind_method(PackedFloat64Array, to_byte_array, sarray(), varray());
bind_method(PackedFloat64Array, sort, sarray(), varray());
+ bind_method(PackedFloat64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat64Array, duplicate, sarray(), varray());
/* String Array */
@@ -1982,6 +1987,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedStringArray, subarray, sarray("from", "to"), varray());
bind_method(PackedStringArray, to_byte_array, sarray(), varray());
bind_method(PackedStringArray, sort, sarray(), varray());
+ bind_method(PackedStringArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedStringArray, duplicate, sarray(), varray());
/* Vector2 Array */
@@ -2001,6 +2007,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector2Array, subarray, sarray("from", "to"), varray());
bind_method(PackedVector2Array, to_byte_array, sarray(), varray());
bind_method(PackedVector2Array, sort, sarray(), varray());
+ bind_method(PackedVector2Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector2Array, duplicate, sarray(), varray());
/* Vector3 Array */
@@ -2020,6 +2027,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector3Array, subarray, sarray("from", "to"), varray());
bind_method(PackedVector3Array, to_byte_array, sarray(), varray());
bind_method(PackedVector3Array, sort, sarray(), varray());
+ bind_method(PackedVector3Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector3Array, duplicate, sarray(), varray());
/* Color Array */
@@ -2039,6 +2047,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedColorArray, subarray, sarray("from", "to"), varray());
bind_method(PackedColorArray, to_byte_array, sarray(), varray());
bind_method(PackedColorArray, sort, sarray(), varray());
+ bind_method(PackedColorArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedColorArray, duplicate, sarray(), varray());
/* Register constants */
diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml
index 8e94254a1f..39733baf40 100644
--- a/doc/classes/PackedByteArray.xml
+++ b/doc/classes/PackedByteArray.xml
@@ -43,6 +43,15 @@
Appends a [PackedByteArray] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="int" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="compress" qualifiers="const">
<return type="PackedByteArray" />
<argument index="0" name="compression_mode" type="int" default="0" />
diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml
index 4bccdcd939..00e670646d 100644
--- a/doc/classes/PackedColorArray.xml
+++ b/doc/classes/PackedColorArray.xml
@@ -43,6 +43,15 @@
Appends a [PackedColorArray] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="Color" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedColorArray" />
<description>
diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml
index 51e14ea3d4..2ee2ac44df 100644
--- a/doc/classes/PackedFloat32Array.xml
+++ b/doc/classes/PackedFloat32Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedFloat32Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="float" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedFloat32Array" />
<description>
diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml
index 25c9c025f7..7414bc72fc 100644
--- a/doc/classes/PackedFloat64Array.xml
+++ b/doc/classes/PackedFloat64Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedFloat64Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="float" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedFloat64Array" />
<description>
diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml
index 1a61ce0ead..8ecf4a70ae 100644
--- a/doc/classes/PackedInt32Array.xml
+++ b/doc/classes/PackedInt32Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedInt32Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="int" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedInt32Array" />
<description>
diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml
index 06f7900237..b82ce79009 100644
--- a/doc/classes/PackedInt64Array.xml
+++ b/doc/classes/PackedInt64Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedInt64Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="int" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedInt64Array" />
<description>
diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml
index 763ed0cc55..353bbfb827 100644
--- a/doc/classes/PackedStringArray.xml
+++ b/doc/classes/PackedStringArray.xml
@@ -44,6 +44,15 @@
Appends a [PackedStringArray] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="String" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedStringArray" />
<description>
diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml
index 3f0797bb59..7b7df221e7 100644
--- a/doc/classes/PackedVector2Array.xml
+++ b/doc/classes/PackedVector2Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedVector2Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="Vector2" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedVector2Array" />
<description>
diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml
index 6b950cad61..efbf2169fd 100644
--- a/doc/classes/PackedVector3Array.xml
+++ b/doc/classes/PackedVector3Array.xml
@@ -43,6 +43,15 @@
Appends a [PackedVector3Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="Vector3" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedVector3Array" />
<description>
diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml
index 3ee3feb365..ded4f0b32f 100644
--- a/doc/classes/Tabs.xml
+++ b/doc/classes/Tabs.xml
@@ -217,18 +217,12 @@
</member>
</members>
<signals>
- <signal name="reposition_active_tab_request">
+ <signal name="active_tab_rearranged">
<argument index="0" name="idx_to" type="int" />
<description>
Emitted when the active tab is rearranged via mouse drag. See [member drag_to_rearrange_enabled].
</description>
</signal>
- <signal name="right_button_pressed">
- <argument index="0" name="tab" type="int" />
- <description>
- Emitted when a tab is right-clicked.
- </description>
- </signal>
<signal name="tab_changed">
<argument index="0" name="tab" type="int" />
<description>
@@ -253,6 +247,12 @@
Emitted when a tab is hovered by the mouse.
</description>
</signal>
+ <signal name="tab_rmb_clicked">
+ <argument index="0" name="tab" type="int" />
+ <description>
+ Emitted when a tab is right-clicked.
+ </description>
+ </signal>
</signals>
<constants>
<constant name="ALIGN_LEFT" value="0" enum="TabAlign">
@@ -281,15 +281,15 @@
</constant>
</constants>
<theme_items>
- <theme_item name="button" data_type="style" type="StyleBox">
+ <theme_item name="close" data_type="icon" type="Texture2D">
+ The icon for the close button (see [member tab_close_display_policy]).
+ </theme_item>
+ <theme_item name="close_bg_highlight" data_type="style" type="StyleBox">
Background of the close button when it's being hovered with the cursor.
</theme_item>
- <theme_item name="button_pressed" data_type="style" type="StyleBox">
+ <theme_item name="close_bg_pressed" data_type="style" type="StyleBox">
Background of the close button when it's being pressed.
</theme_item>
- <theme_item name="close" data_type="icon" type="Texture2D">
- The icon for the close button (see [member tab_close_display_policy]).
- </theme_item>
<theme_item name="decrement" data_type="icon" type="Texture2D">
Icon for the left arrow button that appears when there are too many tabs to fit in the container width. When the button is disabled (i.e. the first tab is visible), it appears semi-transparent.
</theme_item>
@@ -315,7 +315,7 @@
Font color of the other, unselected tabs.
</theme_item>
<theme_item name="hseparation" data_type="constant" type="int" default="4">
- The horizontal separation between the tabs.
+ The horizontal separation between the elements inside tabs.
</theme_item>
<theme_item name="increment" data_type="icon" type="Texture2D">
Icon for the right arrow button that appears when there are too many tabs to fit in the container width. When the button is disabled (i.e. the last tab is visible) it appears semi-transparent.
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 44825d2536..8bc87b7f81 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -6221,12 +6221,12 @@ EditorNode::EditorNode() {
scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
scene_tabs->set_drag_to_rearrange_enabled(true);
scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed));
- scene_tabs->connect("right_button_pressed", callable_mp(this, &EditorNode::_scene_tab_script_edited));
+ scene_tabs->connect("tab_rmb_clicked", callable_mp(this, &EditorNode::_scene_tab_script_edited));
scene_tabs->connect("tab_closed", callable_mp(this, &EditorNode::_scene_tab_closed), varray(SCENE_TAB_CLOSE));
scene_tabs->connect("tab_hovered", callable_mp(this, &EditorNode::_scene_tab_hovered));
scene_tabs->connect("mouse_exited", callable_mp(this, &EditorNode::_scene_tab_exit));
scene_tabs->connect("gui_input", callable_mp(this, &EditorNode::_scene_tab_input));
- scene_tabs->connect("reposition_active_tab_request", callable_mp(this, &EditorNode::_reposition_active_tab));
+ scene_tabs->connect("active_tab_rearranged", callable_mp(this, &EditorNode::_reposition_active_tab));
scene_tabs->connect("resized", callable_mp(this, &EditorNode::_update_scene_tabs));
tabbar_container = memnew(HBoxContainer);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index de1d7b5706..0579fb4cbd 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -962,8 +962,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("SceneTabFG", "EditorStyles", style_tab_selected);
theme->set_stylebox("SceneTabBG", "EditorStyles", style_tab_unselected);
theme->set_icon("close", "Tabs", theme->get_icon("GuiClose", "EditorIcons"));
- theme->set_stylebox("button_pressed", "Tabs", style_menu);
- theme->set_stylebox("button", "Tabs", style_menu);
+ theme->set_stylebox("close_bg_pressed", "Tabs", style_menu);
+ theme->set_stylebox("close_bg_highlight", "Tabs", style_menu);
theme->set_icon("increment", "TabContainer", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
theme->set_icon("decrement", "TabContainer", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
theme->set_icon("increment", "Tabs", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index a1591ce9d8..19e1b40a0d 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -3333,7 +3333,7 @@ ThemeEditor::ThemeEditor() {
preview_tabs->set_h_size_flags(SIZE_EXPAND_FILL);
preview_tabbar_hb->add_child(preview_tabs);
preview_tabs->connect("tab_changed", callable_mp(this, &ThemeEditor::_change_preview_tab));
- preview_tabs->connect("right_button_pressed", callable_mp(this, &ThemeEditor::_remove_preview_tab));
+ preview_tabs->connect("tab_rmb_clicked", callable_mp(this, &ThemeEditor::_remove_preview_tab));
HBoxContainer *add_preview_button_hb = memnew(HBoxContainer);
preview_tabbar_hb->add_child(add_preview_button_hb);
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 3c25f99ada..5f56f86029 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1131,6 +1131,8 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
bool sliding_enabled = !floor_stop_on_slope;
// Constant speed can be applied only the first time sliding is enabled.
bool can_apply_constant_speed = sliding_enabled;
+ // If the platform's ceiling push down the body.
+ bool apply_ceiling_velocity = false;
bool first_slide = true;
bool vel_dir_facing_up = motion_velocity.dot(up_direction) > 0;
Vector2 last_travel;
@@ -1147,6 +1149,19 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
motion_results.push_back(result);
_set_collision_direction(result);
+ // If we hit a ceiling platform, we set the vertical motion_velocity to at least the platform one.
+ if (on_ceiling && result.collider_velocity != Vector2() && result.collider_velocity.dot(up_direction) < 0) {
+ // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
+ if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (result.collision_normal + up_direction).length() < 0.01) {
+ apply_ceiling_velocity = true;
+ Vector2 ceiling_vertical_velocity = up_direction * up_direction.dot(result.collider_velocity);
+ Vector2 motion_vertical_velocity = up_direction * up_direction.dot(motion_velocity);
+ if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
+ motion_velocity = ceiling_vertical_velocity + motion_velocity.slide(up_direction);
+ }
+ }
+ }
+
if (on_floor && floor_stop_on_slope && (motion_velocity.normalized() + up_direction).length() < 0.01) {
Transform2D gt = get_global_transform();
if (result.travel.length() <= margin + CMP_EPSILON) {
@@ -1200,7 +1215,7 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
motion = motion_slide_norm * (motion_slide_up.length() - result.travel.slide(up_direction).length() - last_travel.slide(up_direction).length());
}
// Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
- else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up)) {
+ else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
Vector2 slide_motion = result.remainder.slide(result.collision_normal);
if (slide_motion.dot(motion_velocity) > 0.0) {
motion = slide_motion;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 8603d15162..e6dbe115dd 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -1168,14 +1168,18 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
platform_rid = RID();
platform_velocity = Vector3();
+ platform_ceiling_velocity = Vector3();
floor_normal = Vector3();
wall_normal = Vector3();
+ ceiling_normal = Vector3();
// No sliding on first attempt to keep floor motion stable when possible,
// When stop on slope is enabled or when there is no up direction.
bool sliding_enabled = !floor_stop_on_slope;
// Constant speed can be applied only the first time sliding is enabled.
bool can_apply_constant_speed = sliding_enabled;
+ // If the platform's ceiling push down the body.
+ bool apply_ceiling_velocity = false;
bool first_slide = true;
bool vel_dir_facing_up = motion_velocity.dot(up_direction) > 0;
Vector3 total_travel;
@@ -1193,6 +1197,19 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
CollisionState result_state;
_set_collision_direction(result, result_state);
+ // If we hit a ceiling platform, we set the vertical motion_velocity to at least the platform one.
+ if (collision_state.ceiling && platform_ceiling_velocity != Vector3() && platform_ceiling_velocity.dot(up_direction) < 0) {
+ // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
+ if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (ceiling_normal + up_direction).length() < 0.01) {
+ apply_ceiling_velocity = true;
+ Vector3 ceiling_vertical_velocity = up_direction * up_direction.dot(platform_ceiling_velocity);
+ Vector3 motion_vertical_velocity = up_direction * up_direction.dot(motion_velocity);
+ if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
+ motion_velocity = ceiling_vertical_velocity + motion_velocity.slide(up_direction);
+ }
+ }
+ }
+
if (collision_state.floor && floor_stop_on_slope && (motion_velocity.normalized() + up_direction).length() < 0.01) {
Transform3D gt = get_global_transform();
if (result.travel.length() <= margin + CMP_EPSILON) {
@@ -1304,7 +1321,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
if (apply_default_sliding) {
// Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
- if ((sliding_enabled || !collision_state.floor) && (!collision_state.ceiling || slide_on_ceiling || !vel_dir_facing_up)) {
+ if ((sliding_enabled || !collision_state.floor) && (!collision_state.ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
const PhysicsServer3D::MotionCollision &collision = result.collisions[0];
Vector3 slide_motion = result.remainder.slide(collision.normal);
@@ -1526,6 +1543,8 @@ void CharacterBody3D::_set_collision_direction(const PhysicsServer3D::MotionResu
if (ceiling_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
r_state.ceiling = true;
if (p_apply_state.ceiling) {
+ platform_ceiling_velocity = collision.collider_velocity;
+ ceiling_normal = collision.normal;
collision_state.ceiling = true;
}
continue;
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 916b2cd464..2e96c4472e 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -392,8 +392,10 @@ private:
Vector3 motion_velocity;
Vector3 floor_normal;
Vector3 wall_normal;
+ Vector3 ceiling_normal;
Vector3 last_motion;
Vector3 platform_velocity;
+ Vector3 platform_ceiling_velocity;
Vector3 previous_position;
Vector3 real_velocity;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index ef34bec347..ba8dba847c 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -164,7 +164,7 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) {
if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (rb_hover != -1) {
//pressed
- emit_signal(SNAME("right_button_pressed"), rb_hover);
+ emit_signal(SNAME("tab_rmb_clicked"), rb_hover);
}
rb_pressing = false;
@@ -401,7 +401,7 @@ void Tabs::_notification(int p_what) {
w += tabs[i].size_text;
if (tabs[i].right_button.is_valid()) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("button"));
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("close_bg_highlight"));
Ref<Texture2D> rb = tabs[i].right_button;
w += get_theme_constant(SNAME("hseparation"));
@@ -433,7 +433,7 @@ void Tabs::_notification(int p_what) {
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("button"));
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("close_bg_highlight"));
Ref<Texture2D> cb = close;
w += get_theme_constant(SNAME("hseparation"));
@@ -449,7 +449,7 @@ void Tabs::_notification(int p_what) {
if (!tabs[i].disabled && cb_hover == i) {
if (cb_pressing) {
- get_theme_stylebox(SNAME("button_pressed"))->draw(ci, cb_rect);
+ get_theme_stylebox(SNAME("close_bg_pressed"))->draw(ci, cb_rect);
} else {
style->draw(ci, cb_rect);
}
@@ -886,7 +886,7 @@ void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
hover_now = get_tab_count() - 1;
}
move_tab(tab_from_id, hover_now);
- emit_signal(SNAME("reposition_active_tab_request"), hover_now);
+ emit_signal(SNAME("active_tab_rearranged"), hover_now);
set_current_tab(hover_now);
} else if (get_tabs_rearrange_group() != -1) {
// drag and drop between Tabs
@@ -1165,10 +1165,10 @@ void Tabs::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &Tabs::get_select_with_rmb);
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
- ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab")));
+ ADD_SIGNAL(MethodInfo("tab_rmb_clicked", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_closed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_hovered", PropertyInfo(Variant::INT, "tab")));
- ADD_SIGNAL(MethodInfo("reposition_active_tab_request", PropertyInfo(Variant::INT, "idx_to")));
+ ADD_SIGNAL(MethodInfo("active_tab_rearranged", PropertyInfo(Variant::INT, "idx_to")));
ADD_SIGNAL(MethodInfo("tab_clicked", PropertyInfo(Variant::INT, "tab")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 492e0512e4..94cf826477 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -790,8 +790,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("tab_selected", "Tabs", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2));
theme->set_stylebox("tab_unselected", "Tabs", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3));
theme->set_stylebox("tab_disabled", "Tabs", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3));
- theme->set_stylebox("button_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4));
- theme->set_stylebox("button", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4));
+ theme->set_stylebox("close_bg_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4));
+ theme->set_stylebox("close_bg_highlight", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4));
theme->set_icon("increment", "Tabs", make_icon(scroll_button_right_png));
theme->set_icon("increment_highlight", "Tabs", make_icon(scroll_button_right_hl_png));
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 42b82957fb..2b4929b3df 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -646,7 +646,7 @@ private:
};
Vector2 linear_velocity;
- float angular_velocity;
+ float angular_velocity = 0.0;
Vector<PolygonShapeTileData> polygons;
};
Vector<PhysicsLayerTileData> physics;
diff --git a/tests/test_vector.h b/tests/test_vector.h
index 02c56e59f6..bfdf389aa7 100644
--- a/tests/test_vector.h
+++ b/tests/test_vector.h
@@ -472,6 +472,19 @@ TEST_CASE("[Vector] Sort custom") {
CHECK(vector[7] == "World");
}
+TEST_CASE("[Vector] Search") {
+ Vector<int> vector;
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ vector.push_back(5);
+ vector.push_back(8);
+ CHECK(vector.bsearch(2, true) == 1);
+ CHECK(vector.bsearch(2, false) == 2);
+ CHECK(vector.bsearch(5, true) == 3);
+ CHECK(vector.bsearch(5, false) == 4);
+}
+
TEST_CASE("[Vector] Operators") {
Vector<int> vector;
vector.push_back(2);