summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/cowdata.h1
-rw-r--r--core/io/config_file.cpp8
-rw-r--r--core/io/config_file.h1
-rw-r--r--core/list.h1
-rw-r--r--core/map.h1
-rw-r--r--core/math/basis.h4
-rw-r--r--core/math/math_funcs.cpp2
-rw-r--r--core/math/vector3.cpp15
-rw-r--r--core/math/vector3.h22
-rw-r--r--core/os/memory.h1
-rw-r--r--core/self_list.h1
-rw-r--r--core/sort_array.h1
-rw-r--r--core/typedefs.h1
-rw-r--r--doc/classes/Camera2D.xml7
-rw-r--r--doc/classes/CameraFeed.xml8
-rw-r--r--doc/classes/ClippedCamera.xml19
-rw-r--r--doc/classes/ColorPicker.xml2
-rw-r--r--doc/classes/Input.xml1
-rw-r--r--doc/classes/PopupMenu.xml51
-rw-r--r--doc/classes/RigidBody.xml4
-rw-r--r--doc/classes/RigidBody2D.xml2
-rw-r--r--doc/classes/StaticBody.xml2
-rw-r--r--doc/classes/StaticBody2D.xml2
-rw-r--r--doc/classes/TreeItem.xml9
-rw-r--r--doc/classes/VideoPlayer.xml1
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp25
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp3
-rw-r--r--drivers/unix/net_socket_posix.cpp20
-rw-r--r--drivers/unix/net_socket_posix.h1
-rw-r--r--editor/editor_about.cpp2
-rw-r--r--editor/editor_help.cpp58
-rw-r--r--editor/editor_properties.cpp1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp33
-rw-r--r--editor/project_settings_editor.cpp42
-rw-r--r--editor/project_settings_editor.h1
-rw-r--r--editor/settings_config_dialog.cpp50
-rw-r--r--modules/gdnative/doc_classes/GDNativeLibrary.xml15
-rw-r--r--modules/gdnative/gdnative.cpp2
-rw-r--r--modules/gdnative/register_types.cpp2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java13
-rw-r--r--platform/android/java_godot_lib_jni.cpp7
-rw-r--r--platform/android/java_godot_lib_jni.h1
-rw-r--r--platform/android/os_android.cpp17
-rw-r--r--platform/android/os_android.h2
-rw-r--r--scene/2d/sprite.cpp12
-rw-r--r--scene/2d/sprite.h4
-rw-r--r--scene/gui/control.cpp26
-rw-r--r--scene/gui/file_dialog.cpp2
-rw-r--r--scene/gui/item_list.cpp1
-rw-r--r--scene/gui/popup_menu.cpp166
-rw-r--r--scene/gui/popup_menu.h14
-rw-r--r--scene/gui/rich_text_label.cpp5
-rw-r--r--scene/gui/text_edit.cpp5
-rw-r--r--scene/gui/texture_rect.cpp20
-rw-r--r--scene/gui/texture_rect.h2
-rw-r--r--scene/gui/tree.cpp1
-rw-r--r--scene/resources/texture.cpp13
-rw-r--r--scene/resources/world.cpp2
-rw-r--r--scene/resources/world_2d.cpp4
-rw-r--r--servers/visual/shader_language.cpp38
61 files changed, 571 insertions, 211 deletions
diff --git a/core/cowdata.h b/core/cowdata.h
index 3e40ad0f4b..c92e20920c 100644
--- a/core/cowdata.h
+++ b/core/cowdata.h
@@ -33,6 +33,7 @@
#include <string.h>
+#include "core/error_macros.h"
#include "core/os/memory.h"
#include "core/safe_refcount.h"
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index 271e5c5a0b..5684c82d1c 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -123,6 +123,13 @@ void ConfigFile::erase_section(const String &p_section) {
values.erase(p_section);
}
+void ConfigFile::erase_section_key(const String &p_section, const String &p_key) {
+
+ ERR_FAIL_COND_MSG(!values.has(p_section), "Cannot erase key from nonexistent section '" + p_section + "'.");
+
+ values[p_section].erase(p_key);
+}
+
Error ConfigFile::save(const String &p_path) {
Error err;
@@ -293,6 +300,7 @@ void ConfigFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_section_keys", "section"), &ConfigFile::_get_section_keys);
ClassDB::bind_method(D_METHOD("erase_section", "section"), &ConfigFile::erase_section);
+ ClassDB::bind_method(D_METHOD("erase_section_key", "section", "key"), &ConfigFile::erase_section_key);
ClassDB::bind_method(D_METHOD("load", "path"), &ConfigFile::load);
ClassDB::bind_method(D_METHOD("save", "path"), &ConfigFile::save);
diff --git a/core/io/config_file.h b/core/io/config_file.h
index 3ab6fef868..d927779f9c 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -60,6 +60,7 @@ public:
void get_section_keys(const String &p_section, List<String> *r_keys) const;
void erase_section(const String &p_section);
+ void erase_section_key(const String &p_section, const String &p_key);
Error save(const String &p_path);
Error load(const String &p_path);
diff --git a/core/list.h b/core/list.h
index d1b528562d..c46888e01c 100644
--- a/core/list.h
+++ b/core/list.h
@@ -31,6 +31,7 @@
#ifndef GLOBALS_LIST_H
#define GLOBALS_LIST_H
+#include "core/error_macros.h"
#include "core/os/memory.h"
#include "core/sort_array.h"
diff --git a/core/map.h b/core/map.h
index c87ee42e1b..77e73d70cb 100644
--- a/core/map.h
+++ b/core/map.h
@@ -31,6 +31,7 @@
#ifndef MAP_H
#define MAP_H
+#include "core/error_macros.h"
#include "core/set.h"
// based on the very nice implementation of rb-trees by:
diff --git a/core/math/basis.h b/core/math/basis.h
index 053effda69..4be4ea4cd3 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -28,13 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Circular dependency between Vector3 and Basis :/
-#include "core/math/vector3.h"
-
#ifndef BASIS_H
#define BASIS_H
#include "core/math/quat.h"
+#include "core/math/vector3.h"
class Basis {
public:
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index f04e40cb6c..50fcdb2c13 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -30,6 +30,8 @@
#include "math_funcs.h"
+#include "core/error_macros.h"
+
RandomPCG Math::default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC);
#define PHI 0x9e3779b9
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index 73927821cf..ebc1599820 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -134,6 +134,21 @@ Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const {
return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
}
+Basis Vector3::outer(const Vector3 &p_b) const {
+
+ Vector3 row0(x * p_b.x, x * p_b.y, x * p_b.z);
+ Vector3 row1(y * p_b.x, y * p_b.y, y * p_b.z);
+ Vector3 row2(z * p_b.x, z * p_b.y, z * p_b.z);
+
+ return Basis(row0, row1, row2);
+}
+
+Basis Vector3::to_diagonal_matrix() const {
+ return Basis(x, 0, 0,
+ 0, y, 0,
+ 0, 0, z);
+}
+
Vector3::operator String() const {
return (rtos(x) + ", " + rtos(y) + ", " + rtos(z));
diff --git a/core/math/vector3.h b/core/math/vector3.h
index c68b075613..de1743d88f 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -96,8 +96,8 @@ struct Vector3 {
_FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const;
_FORCE_INLINE_ real_t dot(const Vector3 &p_b) const;
- _FORCE_INLINE_ Basis outer(const Vector3 &p_b) const;
- _FORCE_INLINE_ Basis to_diagonal_matrix() const;
+ Basis outer(const Vector3 &p_b) const;
+ Basis to_diagonal_matrix() const;
_FORCE_INLINE_ Vector3 abs() const;
_FORCE_INLINE_ Vector3 floor() const;
@@ -154,9 +154,6 @@ struct Vector3 {
_FORCE_INLINE_ Vector3() { x = y = z = 0; }
};
-// Should be included after class definition, otherwise we get circular refs
-#include "core/math/basis.h"
-
Vector3 Vector3::cross(const Vector3 &p_b) const {
Vector3 ret(
@@ -172,21 +169,6 @@ real_t Vector3::dot(const Vector3 &p_b) const {
return x * p_b.x + y * p_b.y + z * p_b.z;
}
-Basis Vector3::outer(const Vector3 &p_b) const {
-
- Vector3 row0(x * p_b.x, x * p_b.y, x * p_b.z);
- Vector3 row1(y * p_b.x, y * p_b.y, y * p_b.z);
- Vector3 row2(z * p_b.x, z * p_b.y, z * p_b.z);
-
- return Basis(row0, row1, row2);
-}
-
-Basis Vector3::to_diagonal_matrix() const {
- return Basis(x, 0, 0,
- 0, y, 0,
- 0, 0, z);
-}
-
Vector3 Vector3::abs() const {
return Vector3(Math::abs(x), Math::abs(y), Math::abs(z));
diff --git a/core/os/memory.h b/core/os/memory.h
index 8778cb63ad..a68a359546 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -31,6 +31,7 @@
#ifndef MEMORY_H
#define MEMORY_H
+#include "core/error_macros.h"
#include "core/safe_refcount.h"
#include <stddef.h>
diff --git a/core/self_list.h b/core/self_list.h
index 314d440977..07abcd1d53 100644
--- a/core/self_list.h
+++ b/core/self_list.h
@@ -31,6 +31,7 @@
#ifndef SELF_LIST_H
#define SELF_LIST_H
+#include "core/error_macros.h"
#include "core/typedefs.h"
template <class T>
diff --git a/core/sort_array.h b/core/sort_array.h
index 8660ee3333..d330e0c647 100644
--- a/core/sort_array.h
+++ b/core/sort_array.h
@@ -31,6 +31,7 @@
#ifndef SORT_ARRAY_H
#define SORT_ARRAY_H
+#include "core/error_macros.h"
#include "core/typedefs.h"
#define ERR_BAD_COMPARE(cond) \
diff --git a/core/typedefs.h b/core/typedefs.h
index 660139b90a..767a97ac38 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -108,7 +108,6 @@ T *_nullptr() {
#include "core/int_types.h"
#include "core/error_list.h"
-#include "core/error_macros.h"
/** Generic ABS function, for math uses please use Math::abs */
diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml
index aeeebdf00d..6f1627e296 100644
--- a/doc/classes/Camera2D.xml
+++ b/doc/classes/Camera2D.xml
@@ -51,6 +51,7 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
+ Returns the specified margin. See also [member drag_margin_bottom], [member drag_margin_top], [member drag_margin_left], and [member drag_margin_right].
</description>
</method>
<method name="get_limit" qualifiers="const">
@@ -59,6 +60,7 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
+ Returns the specified camera limit. See also [member limit_bottom], [member limit_top], [member limit_left], and [member limit_right].
</description>
</method>
<method name="make_current">
@@ -84,6 +86,7 @@
<argument index="1" name="drag_margin" type="float">
</argument>
<description>
+ Sets the specified margin. See also [member drag_margin_bottom], [member drag_margin_top], [member drag_margin_left], and [member drag_margin_right].
</description>
</method>
<method name="set_limit">
@@ -94,6 +97,7 @@
<argument index="1" name="limit" type="int">
</argument>
<description>
+ Sets the specified camera limit. See also [member limit_bottom], [member limit_top], [member limit_left], and [member limit_right].
</description>
</method>
</methods>
@@ -161,6 +165,7 @@
[b]Note:[/b] Used the same as [member offset_h].
</member>
<member name="process_mode" type="int" setter="set_process_mode" getter="get_process_mode" enum="Camera2D.Camera2DProcessMode" default="1">
+ The camera's process callback. See [enum Camera2DProcessMode].
</member>
<member name="rotating" type="bool" setter="set_rotating" getter="is_rotating" default="false">
If [code]true[/code], the camera rotates with the target.
@@ -183,8 +188,10 @@
The camera's position takes into account vertical/horizontal offsets and the screen size.
</constant>
<constant name="CAMERA2D_PROCESS_PHYSICS" value="0" enum="Camera2DProcessMode">
+ The camera updates with the [code]_physics_process[/code] callback.
</constant>
<constant name="CAMERA2D_PROCESS_IDLE" value="1" enum="Camera2DProcessMode">
+ The camera updates with the [code]_process[/code] callback.
</constant>
</constants>
</class>
diff --git a/doc/classes/CameraFeed.xml b/doc/classes/CameraFeed.xml
index 6d7757f9f5..f490faf369 100644
--- a/doc/classes/CameraFeed.xml
+++ b/doc/classes/CameraFeed.xml
@@ -14,28 +14,30 @@
<return type="int">
</return>
<description>
- Gets the unique ID for this feed.
+ Returns the unique ID for this feed.
</description>
</method>
<method name="get_name" qualifiers="const">
<return type="String">
</return>
<description>
- Gets the camera's name.
+ Returns the camera's name.
</description>
</method>
<method name="get_position" qualifiers="const">
<return type="int" enum="CameraFeed.FeedPosition">
</return>
<description>
- Position of camera on the device.
+ Returns the position of camera on the device.
</description>
</method>
</methods>
<members>
<member name="feed_is_active" type="bool" setter="set_active" getter="is_active" default="false">
+ If [code]true[/code], the feed is active.
</member>
<member name="feed_transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D( 1, 0, 0, -1, 0, 1 )">
+ The transform applied to the camera's image.
</member>
</members>
<constants>
diff --git a/doc/classes/ClippedCamera.xml b/doc/classes/ClippedCamera.xml
index f6a2a3bc11..9eda79bbae 100644
--- a/doc/classes/ClippedCamera.xml
+++ b/doc/classes/ClippedCamera.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ClippedCamera" inherits="Camera" category="Core" version="3.2">
<brief_description>
+ A [Camera] that includes collision.
</brief_description>
<description>
+ This node extends [Camera] to add collisions with [Area] and/or [PhysicsBody] nodes. The camera cannot move through colliding objects.
</description>
<tutorials>
</tutorials>
@@ -13,6 +15,7 @@
<argument index="0" name="node" type="Object">
</argument>
<description>
+ Adds a collision exception so the camera does not collide with the specified node.
</description>
</method>
<method name="add_exception_rid">
@@ -21,18 +24,21 @@
<argument index="0" name="rid" type="RID">
</argument>
<description>
+ Adds a collision exception so the camera does not collide with the specified [RID].
</description>
</method>
<method name="clear_exceptions">
<return type="void">
</return>
<description>
+ Removes all collision exceptions.
</description>
</method>
<method name="get_clip_offset" qualifiers="const">
<return type="float">
</return>
<description>
+ Returns the distance the camera has been offset due to a collision.
</description>
</method>
<method name="get_collision_mask_bit" qualifiers="const">
@@ -41,6 +47,8 @@
<argument index="0" name="bit" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the specified bit index is on.
+ [b]Note:[/b] Bit indices range from 0-19.
</description>
</method>
<method name="remove_exception">
@@ -49,6 +57,7 @@
<argument index="0" name="node" type="Object">
</argument>
<description>
+ Removes a collision exception with the specified node.
</description>
</method>
<method name="remove_exception_rid">
@@ -57,6 +66,7 @@
<argument index="0" name="rid" type="RID">
</argument>
<description>
+ Removes a collision exception with the specified [RID].
</description>
</method>
<method name="set_collision_mask_bit">
@@ -67,25 +77,34 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
+ Sets the specified bit index to the [code]value[/code].
+ [b]Note:[/b] Bit indices range from 0-19.
</description>
</method>
</methods>
<members>
<member name="clip_to_areas" type="bool" setter="set_clip_to_areas" getter="is_clip_to_areas_enabled" default="false">
+ If [code]true[/code], the camera stops on contact with [Area]s.
</member>
<member name="clip_to_bodies" type="bool" setter="set_clip_to_bodies" getter="is_clip_to_bodies_enabled" default="true">
+ If [code]true[/code], the camera stops on contact with [PhysicsBody]s.
</member>
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1">
+ The camera's collision mask. Only objects in at least one collision layer matching the mask will be detected.
</member>
<member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0">
+ The camera's collision margin. The camera can't get closer than this distance to a colliding object.
</member>
<member name="process_mode" type="int" setter="set_process_mode" getter="get_process_mode" enum="ClippedCamera.ProcessMode" default="0">
+ The camera's process callback. See [enum ProcessMode].
</member>
</members>
<constants>
<constant name="CLIP_PROCESS_PHYSICS" value="0" enum="ProcessMode">
+ The camera updates with the [code]_physics_process[/code] callback.
</constant>
<constant name="CLIP_PROCESS_IDLE" value="1" enum="ProcessMode">
+ The camera updates with the [code]_process[/code] callback.
</constant>
</constants>
</class>
diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml
index cd36f4fdf0..07ce76fdb2 100644
--- a/doc/classes/ColorPicker.xml
+++ b/doc/classes/ColorPicker.xml
@@ -51,8 +51,10 @@
[b]Note:[/b] Cannot be enabled if raw mode is on.
</member>
<member name="presets_enabled" type="bool" setter="set_presets_enabled" getter="are_presets_enabled" default="true">
+ If [code]true[/code], the "add preset" button is enabled.
</member>
<member name="presets_visible" type="bool" setter="set_presets_visible" getter="are_presets_visible" default="true">
+ If [code]true[/code], saved color presets are visible.
</member>
<member name="raw_mode" type="bool" setter="set_raw_mode" getter="is_raw_mode" default="false">
If [code]true[/code], allows the color R, G, B component values to go beyond 1.0, which can be used for certain special operations that require it (like tinting without darkening or rendering sprites in HDR).
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index afb3977849..6d4adfad51 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -71,6 +71,7 @@
<return type="int" enum="Input.CursorShape">
</return>
<description>
+ Returns the currently assigned cursor shape (see [enum CursorShape]).
</description>
</method>
<method name="get_gravity" qualifiers="const">
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index d9400088dd..50b300d216 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -89,6 +89,36 @@
An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
</description>
</method>
+ <method name="add_icon_radio_check_item">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="Texture">
+ </argument>
+ <argument index="1" name="label" type="String">
+ </argument>
+ <argument index="2" name="id" type="int" default="-1">
+ </argument>
+ <argument index="3" name="accel" type="int" default="0">
+ </argument>
+ <description>
+ Same as [method add_icon_check_item], but uses a radio check button.
+ </description>
+ </method>
+ <method name="add_icon_radio_check_shortcut">
+ <return type="void">
+ </return>
+ <argument index="0" name="texture" type="Texture">
+ </argument>
+ <argument index="1" name="shortcut" type="ShortCut">
+ </argument>
+ <argument index="2" name="id" type="int" default="-1">
+ </argument>
+ <argument index="3" name="global" type="bool" default="false">
+ </argument>
+ <description>
+ Same as [method add_icon_check_shortcut], but uses a radio check button.
+ </description>
+ </method>
<method name="add_icon_shortcut">
<return type="void">
</return>
@@ -119,6 +149,25 @@
An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
</description>
</method>
+ <method name="add_multistate_item">
+ <return type="void">
+ </return>
+ <argument index="0" name="label" type="String">
+ </argument>
+ <argument index="1" name="max_states" type="int">
+ </argument>
+ <argument index="2" name="default_state" type="int">
+ </argument>
+ <argument index="3" name="id" type="int" default="-1">
+ </argument>
+ <argument index="4" name="accel" type="int" default="0">
+ </argument>
+ <description>
+ Adds a new multistate item with text [code]label[/code].
+ Contrarily to normal binary items, multistate items can have more than two states, as defined by [code]max_states[/code]. Each press or activate of the item will increase the state by one. The default value is defined by [code]default_state[/code].
+ An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
+ </description>
+ </method>
<method name="add_radio_check_item">
<return type="void">
</return>
@@ -129,7 +178,7 @@
<argument index="2" name="accel" type="int" default="0">
</argument>
<description>
- Adds a new radio button with text [code]label[/code].
+ Adds a new radio check button with text [code]label[/code].
An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
[b]Note:[/b] Checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it.
</description>
diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml
index 4378fc3ffe..624b576f4d 100644
--- a/doc/classes/RigidBody.xml
+++ b/doc/classes/RigidBody.xml
@@ -88,6 +88,7 @@
<argument index="0" name="axis" type="int" enum="PhysicsServer.BodyAxis">
</argument>
<description>
+ Returns [code]true[/code] if the specified linear or rotational axis is locked.
</description>
</method>
<method name="get_colliding_bodies" qualifiers="const">
@@ -106,6 +107,7 @@
<argument index="1" name="lock" type="bool">
</argument>
<description>
+ Locks the specified linear or rotational axis.
</description>
</method>
<method name="set_axis_velocity">
@@ -183,6 +185,8 @@
The body mode. See [enum Mode] for possible values.
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
+ The physics material override for the body.
+ If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping" default="false">
If [code]true[/code], the body is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method.
diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml
index 32a1634f77..c960ef5aee 100644
--- a/doc/classes/RigidBody2D.xml
+++ b/doc/classes/RigidBody2D.xml
@@ -169,6 +169,8 @@
The body's mode. See [enum Mode] for possible values.
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
+ The physics material override for the body.
+ If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping" default="false">
If [code]true[/code], the body is sleeping and will not calculate forces until woken up by a collision or by using [method apply_impulse] or [method add_force].
diff --git a/doc/classes/StaticBody.xml b/doc/classes/StaticBody.xml
index a9709d00df..f8840ddc14 100644
--- a/doc/classes/StaticBody.xml
+++ b/doc/classes/StaticBody.xml
@@ -28,6 +28,8 @@
Deprecated, use [member PhysicsMaterial.friction] instead via [member physics_material_override].
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
+ The physics material override for the body.
+ If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
</members>
<constants>
diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml
index 4a7f71b667..34276ec535 100644
--- a/doc/classes/StaticBody2D.xml
+++ b/doc/classes/StaticBody2D.xml
@@ -27,6 +27,8 @@
Deprecated, use [member PhysicsMaterial.friction] instead via [member physics_material_override].
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
+ The physics material override for the body.
+ If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
</members>
<constants>
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index 01d690589b..a4c976591f 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -120,6 +120,15 @@
Returns the custom background color of column [code]column[/code].
</description>
</method>
+ <method name="get_custom_color" qualifiers="const">
+ <return type="Color">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <description>
+ Returns the custom color of column [code]column[/code].
+ </description>
+ </method>
<method name="get_expand_right" qualifiers="const">
<return type="bool">
</return>
diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml
index 18a85d496f..2215f26c23 100644
--- a/doc/classes/VideoPlayer.xml
+++ b/doc/classes/VideoPlayer.xml
@@ -65,6 +65,7 @@
If [code]true[/code], the video is paused.
</member>
<member name="stream" type="VideoStream" setter="set_stream" getter="get_stream">
+ The assigned video stream. See description for supported formats.
</member>
<member name="stream_position" type="float" setter="set_stream_position" getter="get_stream_position">
The current position of the stream, in seconds.
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index 61bcfff419..088ce3d198 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -2905,16 +2905,10 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
glActiveTexture(GL_TEXTURE0);
- if (!storage->frame.current_rt->used_dof_blur_near) {
- if (storage->frame.current_rt->mip_maps[0].color) {
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
- } else {
- for (int i = 0; i < storage->frame.current_rt->mip_maps[i].sizes.size(); i++) {
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[i].color);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, storage->frame.current_rt->mip_maps[0].sizes[i].width, storage->frame.current_rt->mip_maps[0].sizes[i].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[0].color);
- }
+ if (storage->frame.current_rt->mip_maps[0].color) {
+ glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[0].color);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -3303,6 +3297,12 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
reflection_probe_count = 0;
}
+ if (env && env->bg_mode == VS::ENV_BG_CANVAS) {
+ // If using canvas background, copy 2d to screen copy texture
+ // TODO: When GLES2 renders to current_rt->mip_maps[], this copy will no longer be needed
+ _copy_texture_to_buffer(storage->frame.current_rt->color, storage->frame.current_rt->copy_screen_effect.fbo);
+ }
+
// render list stuff
render_list.clear();
@@ -3439,8 +3439,11 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
clear_color = Color(0.0, 1.0, 0.0, 1.0);
}
} break;
+ case VS::ENV_BG_CANVAS: {
+ // use screen copy as background
+ _copy_texture_to_buffer(storage->frame.current_rt->copy_screen_effect.color, current_fb);
+ } break;
default: {
- // FIXME: implement other background modes
} break;
}
}
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 6faf76e395..451d6adaa9 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -5757,7 +5757,8 @@ void RasterizerStorageGLES2::initialize() {
config.multisample_supported = config.extensions.has("GL_EXT_framebuffer_multisample") || config.extensions.has("GL_EXT_multisampled_render_to_texture") || config.extensions.has("GL_APPLE_framebuffer_multisample");
#ifdef GLES_OVER_GL
- config.render_to_mipmap_supported = true;
+ //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps
+ config.render_to_mipmap_supported = false;
#else
//check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms
config.render_to_mipmap_supported = config.extensions.has("GL_OES_fbo_render_mipmap") && config.extensions.has("GL_EXT_texture_lod");
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index 6a57a2e562..da46b393c6 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -30,6 +30,7 @@
#include "net_socket_posix.h"
+#ifndef UNIX_SOCKET_UNAVAILABLE
#if defined(UNIX_ENABLED)
#include <errno.h>
@@ -280,6 +281,21 @@ void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_
_sock = p_sock;
_ip_type = p_ip_type;
_is_stream = p_is_stream;
+ // Disable descriptor sharing with subprocesses.
+ _set_close_exec_enabled(true);
+}
+
+void NetSocketPosix::_set_close_exec_enabled(bool p_enabled) {
+#ifndef WINDOWS_ENABLED
+ // Enable close on exec to avoid sharing with subprocesses. Off by default on Windows.
+#if defined(NO_FCNTL)
+ unsigned long par = p_enabled ? 1 : 0;
+ SOCK_IOCTL(_sock, FIOCLEX, &par);
+#else
+ int opts = fcntl(_sock, F_GETFD);
+ fcntl(_sock, F_SETFD, opts | FD_CLOEXEC);
+#endif
+#endif
}
Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
@@ -320,6 +336,9 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
_is_stream = p_sock_type == TYPE_TCP;
+ // Disable descriptor sharing with subprocesses.
+ _set_close_exec_enabled(true);
+
#if defined(WINDOWS_ENABLED)
if (!_is_stream) {
// Disable windows feature/bug reporting WSAECONNRESET/WSAENETRESET when
@@ -691,3 +710,4 @@ Error NetSocketPosix::join_multicast_group(const IP_Address &p_multi_address, St
Error NetSocketPosix::leave_multicast_group(const IP_Address &p_multi_address, String p_if_name) {
return _change_multicast_group(p_multi_address, p_if_name, false);
}
+#endif
diff --git a/drivers/unix/net_socket_posix.h b/drivers/unix/net_socket_posix.h
index 40406b241a..e549ea1d6a 100644
--- a/drivers/unix/net_socket_posix.h
+++ b/drivers/unix/net_socket_posix.h
@@ -61,6 +61,7 @@ private:
NetError _get_socket_error();
void _set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream);
_FORCE_INLINE_ Error _change_multicast_group(IP_Address p_ip, String p_if_name, bool p_add);
+ _FORCE_INLINE_ void _set_close_exec_enabled(bool p_enabled);
protected:
static NetSocket *_create_func();
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index b2567249d8..8a03292708 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -141,7 +141,7 @@ EditorAbout::EditorAbout() {
hbc->add_child(about_text);
TabContainer *tc = memnew(TabContainer);
- tc->set_custom_minimum_size(Size2(630, 240) * EDSCALE);
+ tc->set_custom_minimum_size(Size2(950, 400) * EDSCALE);
tc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
vbc->add_child(tc);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 2b58d105de..83434a6d9f 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -1107,37 +1107,47 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
class_desc->add_newline();
- for (int i = 0; i < methods.size(); i++) {
+ for (int pass = 0; pass < 2; pass++) {
+ Vector<DocData::MethodDoc> methods_filtered;
- class_desc->push_font(doc_code_font);
- _add_method(methods[i], false);
- class_desc->pop();
+ for (int i = 0; i < methods.size(); i++) {
+ const String &q = methods[i].qualifiers;
+ if ((pass == 0 && q.find("virtual") != -1) || (pass == 1 && q.find("virtual") == -1)) {
+ methods_filtered.push_back(methods[i]);
+ }
+ }
- class_desc->add_newline();
- class_desc->add_newline();
+ for (int i = 0; i < methods_filtered.size(); i++) {
- class_desc->push_color(text_color);
- class_desc->push_font(doc_font);
- class_desc->push_indent(1);
- if (methods[i].description.strip_edges() != String()) {
- _add_text(methods[i].description);
- } else {
- class_desc->add_image(get_icon("Error", "EditorIcons"));
- class_desc->add_text(" ");
- class_desc->push_color(comment_color);
- class_desc->append_bbcode(TTR("There is currently no description for this method. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ class_desc->push_font(doc_code_font);
+ _add_method(methods_filtered[i], false);
class_desc->pop();
- }
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
- class_desc->add_newline();
+ class_desc->add_newline();
+ class_desc->add_newline();
+
+ class_desc->push_color(text_color);
+ class_desc->push_font(doc_font);
+ class_desc->push_indent(1);
+ if (methods_filtered[i].description.strip_edges() != String()) {
+ _add_text(methods_filtered[i].description);
+ } else {
+ class_desc->add_image(get_icon("Error", "EditorIcons"));
+ class_desc->add_text(" ");
+ class_desc->push_color(comment_color);
+ class_desc->append_bbcode(TTR("There is currently no description for this method. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ class_desc->pop();
+ }
+
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
}
}
-
scroll_locked = false;
}
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 690b7a8ec4..460f75eef0 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -2649,6 +2649,7 @@ void EditorPropertyResource::update_property() {
if (res == RES()) {
assign->set_icon(Ref<Texture>());
assign->set_text(TTR("[empty]"));
+ assign->set_tooltip("");
} else {
assign->set_icon(EditorNode::get_singleton()->get_object_icon(res.operator->(), "Node"));
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index b7d36ce75a..0d388512f4 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -72,7 +72,7 @@ class SnapDialog : public ConfirmationDialog {
public:
SnapDialog() {
- const int SPIN_BOX_GRID_RANGE = 256;
+ const int SPIN_BOX_GRID_RANGE = 16384;
const int SPIN_BOX_ROTATION_RANGE = 360;
Label *label;
VBoxContainer *container;
@@ -96,6 +96,8 @@ public:
grid_offset_x = memnew(SpinBox);
grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
+ grid_offset_x->set_allow_lesser(true);
+ grid_offset_x->set_allow_greater(true);
grid_offset_x->set_suffix("px");
grid_offset_x->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_offset_x);
@@ -103,6 +105,8 @@ public:
grid_offset_y = memnew(SpinBox);
grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
+ grid_offset_y->set_allow_lesser(true);
+ grid_offset_y->set_allow_greater(true);
grid_offset_y->set_suffix("px");
grid_offset_y->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_offset_y);
@@ -115,6 +119,7 @@ public:
grid_step_x = memnew(SpinBox);
grid_step_x->set_min(0.01);
grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
+ grid_step_x->set_allow_greater(true);
grid_step_x->set_suffix("px");
grid_step_x->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_step_x);
@@ -122,6 +127,7 @@ public:
grid_step_y = memnew(SpinBox);
grid_step_y->set_min(0.01);
grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
+ grid_step_y->set_allow_greater(true);
grid_step_y->set_suffix("px");
grid_step_y->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_step_y);
@@ -2708,6 +2714,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
font_secondary_color.a = 0.5;
float text_height = font->get_height();
const float text_width = 76;
+ const float angle_text_width = 54;
Point2 text_pos = (begin + end) / 2 - Vector2(text_width / 2, text_height / 2);
text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
@@ -2715,14 +2722,38 @@ void CanvasItemEditor::_draw_ruler_tool() {
viewport->draw_string(font, text_pos, vformat("%.2f px", length_vector.length()), font_color);
if (draw_secondary_lines) {
+ int horizontal_axis_angle = round(180 * atan2(length_vector.y, length_vector.x) / Math_PI);
+ int vertictal_axis_angle = 90 - horizontal_axis_angle;
Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
viewport->draw_string(font, text_pos2, vformat("%.2f px", length_vector.y), font_secondary_color);
+ Point2 v_angle_text_pos = Point2();
+ v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
+ v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5);
+ viewport->draw_string(font, v_angle_text_pos, vformat("%d deg", vertictal_axis_angle), font_secondary_color);
+
text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2);
viewport->draw_string(font, text_pos2, vformat("%.2f px", length_vector.x), font_secondary_color);
+
+ Point2 h_angle_text_pos = Point2();
+ h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
+ if (begin.y < end.y) {
+ h_angle_text_pos.y = end.y + text_height * 1.5;
+ if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) {
+ int height_multiplier = 1.5 + (int)is_snap_active;
+ h_angle_text_pos.y = MAX(text_pos.y + height_multiplier * text_height, MAX(end.y + text_height * 1.5, text_pos2.y + height_multiplier * text_height));
+ }
+ } else {
+ h_angle_text_pos.y = end.y - text_height * 0.5;
+ if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) {
+ int height_multiplier = 1 + (int)is_snap_active;
+ h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height));
+ }
+ }
+ viewport->draw_string(font, h_angle_text_pos, vformat("%d deg", horizontal_axis_angle), font_secondary_color);
}
if (is_snap_active) {
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index a56cfede34..35187214a6 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -74,6 +74,26 @@ static const char *_axis_names[JOY_AXIS_MAX * 2] = {
"", " (R2)"
};
+void ProjectSettingsEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
+
+ const Ref<InputEventKey> k = p_event;
+
+ if (k.is_valid() && is_window_modal_on_top() && k->is_pressed()) {
+
+ if (k->get_scancode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) {
+ if (search_button->is_pressed()) {
+ search_box->grab_focus();
+ search_box->select_all();
+ } else {
+ // This toggles the search bar display while giving the button its "pressed" appearance
+ search_button->set_pressed(true);
+ }
+
+ accept_event();
+ }
+ }
+}
+
void ProjectSettingsEditor::_notification(int p_what) {
switch (p_what) {
@@ -116,6 +136,7 @@ void ProjectSettingsEditor::_notification(int p_what) {
} break;
case NOTIFICATION_POPUP_HIDE: {
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "project_settings", get_rect());
+ set_process_unhandled_input(false);
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
search_button->set_icon(get_icon("Search", "EditorIcons"));
@@ -800,6 +821,7 @@ void ProjectSettingsEditor::popup_project_settings() {
_update_translations();
autoload_settings->update_autoload();
plugin_settings->update_plugins();
+ set_process_unhandled_input(true);
}
void ProjectSettingsEditor::update_plugins() {
@@ -823,13 +845,9 @@ void ProjectSettingsEditor::_item_adds(String) {
void ProjectSettingsEditor::_item_add() {
- Variant value;
- switch (type->get_selected()) {
- case 0: value = false; break;
- case 1: value = 0; break;
- case 2: value = 0.0; break;
- case 3: value = ""; break;
- }
+ // Initialize the property with the default value for the given type
+ Variant::CallError ce;
+ const Variant value = Variant::construct(Variant::Type(type->get_selected()), NULL, 0, ce);
String catname = category->get_text().strip_edges();
String propname = property->get_text().strip_edges();
@@ -1697,6 +1715,7 @@ void ProjectSettingsEditor::_editor_restart_close() {
void ProjectSettingsEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_unhandled_input"), &ProjectSettingsEditor::_unhandled_input);
ClassDB::bind_method(D_METHOD("_item_selected"), &ProjectSettingsEditor::_item_selected);
ClassDB::bind_method(D_METHOD("_item_add"), &ProjectSettingsEditor::_item_add);
ClassDB::bind_method(D_METHOD("_item_adds"), &ProjectSettingsEditor::_item_adds);
@@ -1811,10 +1830,11 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
type = memnew(OptionButton);
type->set_h_size_flags(Control::SIZE_EXPAND_FILL);
add_prop_bar->add_child(type);
- type->add_item("bool");
- type->add_item("int");
- type->add_item("float");
- type->add_item("string");
+
+ // Start at 1 to avoid adding "Nil" as an option
+ for (int i = 1; i < Variant::VARIANT_MAX; i++) {
+ type->add_item(Variant::get_type_name(Variant::Type(i)), i);
+ }
Button *add = memnew(Button);
add_prop_bar->add_child(add);
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index 4dfd8ba602..c164b49d0e 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -178,6 +178,7 @@ class ProjectSettingsEditor : public AcceptDialog {
void _editor_restart_close();
protected:
+ void _unhandled_input(const Ref<InputEvent> &p_event);
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index c9c1f9c3e0..f8425ebe22 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -140,32 +140,35 @@ void EditorSettingsDialog::_notification(int p_what) {
void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
- Ref<InputEventKey> k = p_event;
+ const Ref<InputEventKey> k = p_event;
- if (k.is_valid() && is_window_modal_on_top()) {
+ if (k.is_valid() && is_window_modal_on_top() && k->is_pressed()) {
- if (k->is_pressed()) {
+ bool handled = false;
- bool handled = false;
+ if (ED_IS_SHORTCUT("editor/undo", p_event)) {
+ String action = undo_redo->get_current_action_name();
+ if (action != "")
+ EditorNode::get_log()->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR);
+ undo_redo->undo();
+ handled = true;
+ }
- if (ED_IS_SHORTCUT("editor/undo", p_event)) {
- String action = undo_redo->get_current_action_name();
- if (action != "")
- EditorNode::get_log()->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR);
- undo_redo->undo();
- handled = true;
- }
- if (ED_IS_SHORTCUT("editor/redo", p_event)) {
- undo_redo->redo();
- String action = undo_redo->get_current_action_name();
- if (action != "")
- EditorNode::get_log()->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR);
- handled = true;
- }
+ if (ED_IS_SHORTCUT("editor/redo", p_event)) {
+ undo_redo->redo();
+ String action = undo_redo->get_current_action_name();
+ if (action != "")
+ EditorNode::get_log()->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR);
+ handled = true;
+ }
- if (handled) {
- accept_event();
- }
+ if (k->get_scancode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) {
+ _focus_current_search_box();
+ handled = true;
+ }
+
+ if (handled) {
+ accept_event();
}
}
}
@@ -408,7 +411,6 @@ EditorSettingsDialog::EditorSettingsDialog() {
tabs->set_tab_align(TabContainer::ALIGN_LEFT);
tabs->connect("tab_changed", this, "_tabs_tab_changed");
add_child(tabs);
- //set_child_rect(tabs);
// General Tab
@@ -425,7 +427,6 @@ EditorSettingsDialog::EditorSettingsDialog() {
hbc->add_child(search_box);
inspector = memnew(SectionedInspector);
- //inspector->hide_top_label();
inspector->get_inspector()->set_use_filter(true);
inspector->register_search_box(search_box);
inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@@ -474,7 +475,6 @@ EditorSettingsDialog::EditorSettingsDialog() {
shortcuts->set_v_size_flags(SIZE_EXPAND_FILL);
shortcuts->set_columns(2);
shortcuts->set_hide_root(true);
- //shortcuts->set_hide_folding(true);
shortcuts->set_column_titles_visible(true);
shortcuts->set_column_title(0, TTR("Name"));
shortcuts->set_column_title(1, TTR("Binding"));
@@ -495,9 +495,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
press_a_key->connect("gui_input", this, "_wait_for_key");
press_a_key->connect("confirmed", this, "_press_a_key_confirm");
- //get_ok()->set_text("Apply");
set_hide_on_ok(true);
- //get_cancel()->set_text("Close");
timer = memnew(Timer);
timer->set_wait_time(1.5);
diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml
index 7e1cac243a..aa48ab44f2 100644
--- a/modules/gdnative/doc_classes/GDNativeLibrary.xml
+++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml
@@ -1,35 +1,50 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.2">
<brief_description>
+ An external library containing functions or script classes to use in Godot.
</brief_description>
<description>
+ A GDNative library can implement [NativeScript]s, global functions to call with the [GDNative] class, or low-level engine extensions through interfaces such as [ARVRInterfaceGDNative]. The library must be compiled for each platform and architecture that the project will run on.
</description>
<tutorials>
+ <link>https://docs.godotengine.org/en/latest/tutorials/plugins/gdnative/gdnative-c-example.html</link>
+ <link>https://docs.godotengine.org/en/latest/tutorials/plugins/gdnative/gdnative-cpp-example.html</link>
</tutorials>
<methods>
<method name="get_current_dependencies" qualifiers="const">
<return type="PoolStringArray">
</return>
<description>
+ Returns paths to all dependency libraries for the current platform and architecture.
</description>
</method>
<method name="get_current_library_path" qualifiers="const">
<return type="String">
</return>
<description>
+ Returns the path to the dynamic library file for the current platform and architecture.
</description>
</method>
</methods>
<members>
<member name="config_file" type="ConfigFile" setter="set_config_file" getter="get_config_file">
+ This resource in INI-style [ConfigFile] format, as in [code].gdnlib[/code] files.
</member>
<member name="load_once" type="bool" setter="set_load_once" getter="should_load_once" default="true">
+ If [code]true[/code], Godot loads only one copy of the library and each script that references the library will share static data like static or global variables.
+ If [code]false[/code], Godot loads a separate copy of the library into memory for each script that references it.
</member>
<member name="reloadable" type="bool" setter="set_reloadable" getter="is_reloadable" default="true">
+ If [code]true[/code], the editor will temporarily unload the library whenever the user switches away from the editor window, allowing the user to recompile the library without restarting Godot.
+ [b]Note:[/b] If the library defines tool scripts that run inside the editor, [code]reloadable[/code] must be [code]false[/code]. Otherwise, the editor will attempt to unload the tool scripts while they're in use and crash.
</member>
<member name="singleton" type="bool" setter="set_singleton" getter="is_singleton" default="false">
+ If [code]true[/code], Godot loads the library at startup rather than the first time a script uses the library, calling [code]{prefix}gdnative_singleton[/code] after initializing the library (where [code]{prefix}[/code] is the value of [member symbol_prefix]). The library remains loaded as long as Godot is running.
+ [b]Note:[/b] A singleton library cannot be [member reloadable].
</member>
<member name="symbol_prefix" type="String" setter="set_symbol_prefix" getter="get_symbol_prefix" default="&quot;godot_&quot;">
+ The prefix this library's entry point functions begin with. For example, a GDNativeLibrary would declare its [code]gdnative_init[/code] function as [code]godot_gdnative_init[/code] by default.
+ On platforms that require statically linking libraries (currently only iOS), each library must have a different [code]symbol_prefix[/code].
</member>
</members>
<constants>
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 783ad4e147..ee9e71d4a0 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -339,7 +339,7 @@ bool GDNative::initialize() {
if (err || !library_init) {
OS::get_singleton()->close_dynamic_library(native_handle);
native_handle = NULL;
- ERR_PRINT("Failed to obtain godot_gdnative_init symbol");
+ ERR_PRINTS("Failed to obtain " + library->get_symbol_prefix() + "gdnative_init symbol");
return false;
}
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 6ff6262b56..0194199133 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -277,7 +277,7 @@ void register_gdnative_types() {
proc_ptr);
if (err != OK) {
- ERR_PRINT((String("No godot_gdnative_singleton in \"" + singleton->get_library()->get_current_library_path()) + "\" found").utf8().get_data());
+ ERR_PRINTS("No " + lib->get_symbol_prefix() + "gdnative_singleton in \"" + singleton->get_library()->get_current_library_path() + "\" found");
} else {
singleton_gdnatives.push_back(singleton);
((void (*)())proc_ptr)();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index 067fa6f4b9..67dce172dc 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -95,6 +95,11 @@ public class GodotLib {
public static native void touch(int what, int pointer, int howmany, int[] arr);
/**
+ * Forward hover events from the main thread to the GL thread.
+ */
+ public static native void hover(int type, int x, int y);
+
+ /**
* Forward accelerometer sensor events from the main thread to the GL thread.
* @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)
*/
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index 2beca67922..2756ca6c83 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -188,7 +188,18 @@ public class GodotInputHandler implements InputDeviceListener {
}
return true;
}
- };
+ } else if ((event.getSource() & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) {
+ final int x = Math.round(event.getX());
+ final int y = Math.round(event.getY());
+ final int type = event.getAction();
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.hover(type, x, y);
+ }
+ });
+ return true;
+ }
return false;
}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 30676783db..7daea19961 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -826,6 +826,13 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jo
*/
}
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jobject obj, jint p_type, jint p_x, jint p_y) {
+ if (step == 0)
+ return;
+
+ os_android->process_hover(p_type, Point2(p_x, p_y));
+}
+
/*
* Android Key codes.
*/
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index 11bda94f8d..a564bbd4a1 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -45,6 +45,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *en
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jobject obj, jint p_type, jint p_x, jint p_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 49ab0ea84a..91bd6cbdd2 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -477,6 +477,23 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
}
}
+void OS_Android::process_hover(int p_type, Point2 p_pos) {
+ // https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER
+ switch (p_type) {
+ case 7: // hover move
+ case 9: // hover enter
+ case 10: { // hover exit
+ Ref<InputEventMouseMotion> ev;
+ ev.instance();
+ ev->set_position(p_pos);
+ ev->set_global_position(p_pos);
+ ev->set_relative(p_pos - hover_prev_pos);
+ input->parse_input_event(ev);
+ hover_prev_pos = p_pos;
+ } break;
+ }
+}
+
void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) {
input->set_accelerometer(p_accelerometer);
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index a17941f7c0..9bad9b2e01 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -70,6 +70,7 @@ public:
private:
Vector<TouchPos> touch;
+ Point2 hover_prev_pos; // needed to calculate the relative position on hover events
bool use_gl2;
bool use_apk_expansion;
@@ -186,6 +187,7 @@ public:
void process_magnetometer(const Vector3 &p_magnetometer);
void process_gyroscope(const Vector3 &p_gyroscope);
void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points);
+ void process_hover(int p_type, Point2 p_pos);
void process_joy_event(JoypadEvent p_event);
void process_event(Ref<InputEvent> p_event);
void init_video_mode(int p_video_width, int p_video_height);
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index af9ce2a4bf..83f92ce2bc 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -135,12 +135,12 @@ void Sprite::set_texture(const Ref<Texture> &p_texture) {
return;
if (texture.is_valid())
- texture->remove_change_receptor(this);
+ texture->disconnect(CoreStringNames::get_singleton()->changed, this, "_texture_changed");
texture = p_texture;
if (texture.is_valid())
- texture->add_change_receptor(this);
+ texture->connect(CoreStringNames::get_singleton()->changed, this, "_texture_changed");
update();
emit_signal("texture_changed");
@@ -389,11 +389,11 @@ void Sprite::_validate_property(PropertyInfo &property) const {
}
}
-void Sprite::_changed_callback(Object *p_changed, const char *p_prop) {
+void Sprite::_texture_changed() {
// Changes to the texture need to trigger an update to make
// the editor redraw the sprite with the updated texture.
- if (texture.is_valid() && texture.ptr() == p_changed) {
+ if (texture.is_valid()) {
update();
}
}
@@ -443,6 +443,8 @@ void Sprite::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rect"), &Sprite::get_rect);
+ ClassDB::bind_method(D_METHOD("_texture_changed"), &Sprite::_texture_changed);
+
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_SIGNAL(MethodInfo("texture_changed"));
@@ -480,6 +482,4 @@ Sprite::Sprite() {
}
Sprite::~Sprite() {
- if (texture.is_valid())
- texture->remove_change_receptor(this);
}
diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h
index 5e6717a3f5..d3c0112e62 100644
--- a/scene/2d/sprite.h
+++ b/scene/2d/sprite.h
@@ -57,6 +57,8 @@ class Sprite : public Node2D {
void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const;
+ void _texture_changed();
+
protected:
void _notification(int p_what);
@@ -64,8 +66,6 @@ protected:
virtual void _validate_property(PropertyInfo &property) const;
- virtual void _changed_callback(Object *p_changed, const char *p_prop);
-
public:
virtual Dictionary _edit_get_state() const;
virtual void _edit_set_state(const Dictionary &p_state);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index fc67b28095..fafbcf0c55 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1412,6 +1412,9 @@ void Control::_size_changed() {
}
void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bool p_push_opposite_anchor) {
+
+ ERR_FAIL_INDEX((int)p_margin, 4);
+
Rect2 parent_rect = get_parent_anchorable_rect();
float parent_range = (p_margin == MARGIN_LEFT || p_margin == MARGIN_RIGHT) ? parent_rect.size.x : parent_rect.size.y;
float previous_margin_pos = data.margin[p_margin] + data.anchor[p_margin] * parent_range;
@@ -1456,6 +1459,9 @@ void Control::set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos
}
void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margins) {
+
+ ERR_FAIL_INDEX((int)p_preset, 16);
+
//Left
switch (p_preset) {
case PRESET_TOP_LEFT:
@@ -1570,6 +1576,10 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margins) {
}
void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode, int p_margin) {
+
+ ERR_FAIL_INDEX((int)p_preset, 16);
+ ERR_FAIL_INDEX((int)p_resize_mode, 4);
+
// Calculate the size if the node is not resized
Size2 min_size = get_minimum_size();
Size2 new_size = get_size();
@@ -1704,6 +1714,8 @@ void Control::set_anchors_and_margins_preset(LayoutPreset p_preset, LayoutPreset
float Control::get_anchor(Margin p_margin) const {
+ ERR_FAIL_INDEX_V(int(p_margin), 4, 0.0);
+
return data.anchor[p_margin];
}
@@ -1720,6 +1732,8 @@ void Control::_change_notify_margins() {
void Control::set_margin(Margin p_margin, float p_value) {
+ ERR_FAIL_INDEX((int)p_margin, 4);
+
data.margin[p_margin] = p_value;
_size_changed();
}
@@ -1740,6 +1754,8 @@ void Control::set_end(const Size2 &p_point) {
float Control::get_margin(Margin p_margin) const {
+ ERR_FAIL_INDEX_V((int)p_margin, 4, 0);
+
return data.margin[p_margin];
}
@@ -1951,6 +1967,8 @@ void Control::add_constant_override(const StringName &p_name, int p_constant) {
void Control::set_focus_mode(FocusMode p_focus_mode) {
+ ERR_FAIL_INDEX((int)p_focus_mode, 3);
+
if (is_inside_tree() && p_focus_mode == FOCUS_NONE && data.focus_mode != FOCUS_NONE && has_focus())
release_focus();
@@ -2298,6 +2316,8 @@ Control *Control::make_custom_tooltip(const String &p_text) const {
void Control::set_default_cursor_shape(CursorShape p_shape) {
+ ERR_FAIL_INDEX(int(p_shape), CURSOR_MAX);
+
data.default_cursor = p_shape;
}
@@ -2358,6 +2378,8 @@ NodePath Control::get_focus_previous() const {
Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
+ ERR_FAIL_INDEX_V((int)p_margin, 4, NULL);
+
if (p_count >= MAX_NEIGHBOUR_SEARCH_COUNT)
return NULL;
if (!data.focus_neighbour[p_margin].is_empty()) {
@@ -2760,6 +2782,8 @@ bool Control::is_clipping_contents() {
void Control::set_h_grow_direction(GrowDirection p_direction) {
+ ERR_FAIL_INDEX((int)p_direction, 3);
+
data.h_grow = p_direction;
_size_changed();
}
@@ -2771,6 +2795,8 @@ Control::GrowDirection Control::get_h_grow_direction() const {
void Control::set_v_grow_direction(GrowDirection p_direction) {
+ ERR_FAIL_INDEX((int)p_direction, 3);
+
data.v_grow = p_direction;
_size_changed();
}
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 9bc593ea3b..24c046457b 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -637,6 +637,8 @@ bool FileDialog::is_mode_overriding_title() const {
void FileDialog::set_mode(Mode p_mode) {
+ ERR_FAIL_INDEX((int)p_mode, 5);
+
mode = p_mode;
switch (mode) {
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index a3bc68ffcd..4d06bee0d4 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -430,6 +430,7 @@ ItemList::SelectMode ItemList::get_select_mode() const {
void ItemList::set_icon_mode(IconMode p_mode) {
+ ERR_FAIL_INDEX((int)p_mode, 2);
icon_mode = p_mode;
update();
shape_changed = true;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index a7c6c5ccab..08faaf7d45 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -79,7 +79,7 @@ Size2 PopupMenu::get_minimum_size() const {
if (items[i].checkable_type)
has_check = true;
- String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].xl_text;
+ String text = items[i].xl_text;
size.width += font->get_string_size(text).width;
if (i > 0)
size.height += vseparation;
@@ -519,7 +519,7 @@ void PopupMenu::_notification(int p_what) {
hover->draw(ci, Rect2(item_ofs + Point2(-hseparation, -vseparation / 2), Size2(get_size().width - style->get_minimum_size().width + hseparation * 2, h + vseparation)));
}
- String text = items[i].shortcut.is_valid() ? String(tr(items[i].shortcut->get_name())) : items[i].xl_text;
+ String text = items[i].xl_text;
item_ofs.x += items[i].h_ofs;
if (items[i].separator) {
@@ -627,63 +627,50 @@ void PopupMenu::_notification(int p_what) {
}
}
-void PopupMenu::add_icon_item(const Ref<Texture> &p_icon, const String &p_label, int p_id, uint32_t p_accel) {
+/* Methods to add items with or without icon, checkbox, shortcut.
+ * Be sure to keep them in sync when adding new properties in the Item struct.
+ */
- Item item;
- item.icon = p_icon;
- item.text = p_label;
- item.xl_text = tr(p_label);
+#define ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel) \
+ item.text = p_label; \
+ item.xl_text = tr(p_label); \
+ item.id = p_id == -1 ? items.size() : p_id; \
item.accel = p_accel;
- item.id = p_id;
- items.push_back(item);
- update();
- minimum_size_changed();
-}
+
void PopupMenu::add_item(const String &p_label, int p_id, uint32_t p_accel) {
Item item;
- item.text = p_label;
- item.xl_text = tr(p_label);
- item.accel = p_accel;
- item.id = p_id == -1 ? items.size() : p_id;
+ ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
items.push_back(item);
update();
minimum_size_changed();
}
-void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, int p_id) {
+void PopupMenu::add_icon_item(const Ref<Texture> &p_icon, const String &p_label, int p_id, uint32_t p_accel) {
Item item;
- item.text = p_label;
- item.xl_text = tr(p_label);
- item.id = p_id;
- item.submenu = p_submenu;
+ ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
+ item.icon = p_icon;
items.push_back(item);
update();
minimum_size_changed();
}
-void PopupMenu::add_icon_check_item(const Ref<Texture> &p_icon, const String &p_label, int p_id, uint32_t p_accel) {
+void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel) {
Item item;
- item.icon = p_icon;
- item.text = p_label;
- item.xl_text = tr(p_label);
- item.accel = p_accel;
- item.id = p_id;
+ ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
update();
minimum_size_changed();
}
-void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel) {
+void PopupMenu::add_icon_check_item(const Ref<Texture> &p_icon, const String &p_label, int p_id, uint32_t p_accel) {
Item item;
- item.text = p_label;
- item.xl_text = tr(p_label);
- item.accel = p_accel;
- item.id = p_id == -1 ? items.size() : p_id;
+ ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
+ item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
update();
@@ -692,63 +679,59 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel
void PopupMenu::add_radio_check_item(const String &p_label, int p_id, uint32_t p_accel) {
- add_check_item(p_label, p_id, p_accel);
- items.write[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
+ Item item;
+ ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
+ item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
+ items.push_back(item);
update();
minimum_size_changed();
}
void PopupMenu::add_icon_radio_check_item(const Ref<Texture> &p_icon, const String &p_label, int p_id, uint32_t p_accel) {
- add_icon_check_item(p_icon, p_label, p_id, p_accel);
- items.write[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
+ Item item;
+ ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
+ item.icon = p_icon;
+ item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
+ items.push_back(item);
update();
minimum_size_changed();
}
-void PopupMenu::add_icon_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
-
- ERR_FAIL_COND(p_shortcut.is_null());
-
- _ref_shortcut(p_shortcut);
+void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_id, uint32_t p_accel) {
Item item;
- item.id = p_id;
- item.icon = p_icon;
- item.shortcut = p_shortcut;
- item.shortcut_is_global = p_global;
+ ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
+ item.max_states = p_max_states;
+ item.state = p_default_state;
items.push_back(item);
update();
minimum_size_changed();
}
-void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
-
- ERR_FAIL_COND(p_shortcut.is_null());
+#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global) \
+ ERR_FAIL_COND_MSG(p_shortcut.is_null(), "Cannot add item with invalid ShortCut."); \
+ _ref_shortcut(p_shortcut); \
+ item.text = p_shortcut->get_name(); \
+ item.xl_text = tr(item.text); \
+ item.id = p_id == -1 ? items.size() : p_id; \
+ item.shortcut = p_shortcut; \
+ item.shortcut_is_global = p_global;
- _ref_shortcut(p_shortcut);
+void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
Item item;
- item.id = p_id;
- item.shortcut = p_shortcut;
- item.shortcut_is_global = p_global;
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
items.push_back(item);
update();
minimum_size_changed();
}
-void PopupMenu::add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
-
- ERR_FAIL_COND(p_shortcut.is_null());
-
- _ref_shortcut(p_shortcut);
+void PopupMenu::add_icon_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
Item item;
- item.id = p_id;
- item.shortcut = p_shortcut;
- item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.icon = p_icon;
- item.shortcut_is_global = p_global;
items.push_back(item);
update();
minimum_size_changed();
@@ -756,14 +739,19 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<Sh
void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
- ERR_FAIL_COND(p_shortcut.is_null());
+ Item item;
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
+ items.push_back(item);
+ update();
+ minimum_size_changed();
+}
- _ref_shortcut(p_shortcut);
+void PopupMenu::add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
Item item;
- item.id = p_id;
- item.shortcut = p_shortcut;
- item.shortcut_is_global = p_global;
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
update();
@@ -772,26 +760,42 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bo
void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
- add_check_shortcut(p_shortcut, p_id, p_global);
- items.write[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
+ Item item;
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
+ items.push_back(item);
update();
minimum_size_changed();
}
-void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_id, uint32_t p_accel) {
+void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
+
+ Item item;
+ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
+ item.icon = p_icon;
+ item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
+ items.push_back(item);
+ update();
+ minimum_size_changed();
+}
+
+void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, int p_id) {
Item item;
item.text = p_label;
item.xl_text = tr(p_label);
- item.accel = p_accel;
- item.id = p_id;
- item.max_states = p_max_states;
- item.state = p_default_state;
+ item.id = p_id == -1 ? items.size() : p_id;
+ item.submenu = p_submenu;
items.push_back(item);
update();
minimum_size_changed();
}
+#undef ITEM_SETUP_WITH_ACCEL
+#undef ITEM_SETUP_WITH_SHORTCUT
+
+/* Methods to modify existing items. */
+
void PopupMenu::set_item_text(int p_idx, const String &p_text) {
ERR_FAIL_INDEX(p_idx, items.size());
@@ -1380,18 +1384,24 @@ void PopupMenu::clear_autohide_areas() {
void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &PopupMenu::_gui_input);
- ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_item, DEFVAL(-1), DEFVAL(0));
+
ClassDB::bind_method(D_METHOD("add_item", "label", "id", "accel"), &PopupMenu::add_item, DEFVAL(-1), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("add_icon_check_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_check_item, DEFVAL(-1), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_item, DEFVAL(-1), DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_check_item", "label", "id", "accel"), &PopupMenu::add_check_item, DEFVAL(-1), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_icon_check_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_check_item, DEFVAL(-1), DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_radio_check_item", "label", "id", "accel"), &PopupMenu::add_radio_check_item, DEFVAL(-1), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("add_submenu_item", "label", "submenu", "id"), &PopupMenu::add_submenu_item, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_icon_radio_check_item", "texture", "label", "id", "accel"), &PopupMenu::add_icon_radio_check_item, DEFVAL(-1), DEFVAL(0));
+
+ ClassDB::bind_method(D_METHOD("add_multistate_item", "label", "max_states", "default_state", "id", "accel"), &PopupMenu::add_multistate_item, DEFVAL(0), DEFVAL(-1), DEFVAL(0));
- ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut", "id", "global"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_check_shortcut, DEFVAL(-1), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_radio_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_radio_check_shortcut, DEFVAL(-1), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_icon_radio_check_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_radio_check_shortcut, DEFVAL(-1), DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("add_submenu_item", "label", "submenu", "id"), &PopupMenu::add_submenu_item, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("set_item_text", "idx", "text"), &PopupMenu::set_item_text);
ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &PopupMenu::set_item_icon);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 8bfe8fc607..8c33178b09 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -120,21 +120,23 @@ protected:
static void _bind_methods();
public:
- void add_icon_item(const Ref<Texture> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0);
void add_item(const String &p_label, int p_id = -1, uint32_t p_accel = 0);
- void add_icon_check_item(const Ref<Texture> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0);
+ void add_icon_item(const Ref<Texture> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0);
void add_check_item(const String &p_label, int p_id = -1, uint32_t p_accel = 0);
+ void add_icon_check_item(const Ref<Texture> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0);
void add_radio_check_item(const String &p_label, int p_id = -1, uint32_t p_accel = 0);
void add_icon_radio_check_item(const Ref<Texture> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0);
- void add_submenu_item(const String &p_label, const String &p_submenu, int p_id = -1);
- void add_icon_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_multistate_item(const String &p_label, int p_max_states, int p_default_state = 0, int p_id = -1, uint32_t p_accel = 0);
+
void add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
- void add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_icon_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
void add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
void add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
+ void add_icon_radio_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false);
- void add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_id = -1, uint32_t p_accel = 0);
+ void add_submenu_item(const String &p_label, const String &p_submenu, int p_id = -1);
void set_item_text(int p_idx, const String &p_text);
void set_item_icon(int p_idx, const Ref<Texture> &p_icon);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index c5330c78e1..42cb89b2d6 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -143,6 +143,8 @@ Rect2 RichTextLabel::_get_text_rect() {
int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Color &p_font_color_shadow, bool p_shadow_as_outline, const Point2 &shadow_ofs, const Point2i &p_click_pos, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count) {
+ ERR_FAIL_INDEX_V((int)p_mode, 3, 0);
+
RID ci;
if (r_outside)
*r_outside = false;
@@ -1416,6 +1418,9 @@ bool RichTextLabel::_find_strikethrough(Item *p_item) {
}
bool RichTextLabel::_find_by_type(Item *p_item, ItemType p_type) {
+
+ ERR_FAIL_INDEX_V((int)p_type, 19, false);
+
Item *item = p_item;
while (item) {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index e2bb4e3e91..c0b0944e47 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1271,7 +1271,8 @@ void TextEdit::_notification(int p_what) {
}
// Loop through characters in one line.
- for (int j = 0; j < str.length(); j++) {
+ int j = 0;
+ for (; j < str.length(); j++) {
if (syntax_coloring) {
if (color_map.has(last_wrap_column + j)) {
@@ -1501,7 +1502,7 @@ void TextEdit::_notification(int p_what) {
}
}
- if (cursor.column == last_wrap_column + str.length() && cursor.line == line && cursor_wrap_index == line_wrap_index && (char_ofs + char_margin) >= xmargin_beg) {
+ if (cursor.column == (last_wrap_column + j) && cursor.line == line && cursor_wrap_index == line_wrap_index && (char_ofs + char_margin) >= xmargin_beg) {
cursor_pos = Point2i(char_ofs + char_margin + ofs_x, ofs_y);
cursor_pos.y += (get_row_height() - cache.font->get_height()) / 2;
diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp
index 423794d8ba..473cee5ca1 100644
--- a/scene/gui/texture_rect.cpp
+++ b/scene/gui/texture_rect.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "texture_rect.h"
+#include "core/core_string_names.h"
#include "servers/visual_server.h"
void TextureRect::_notification(int p_what) {
@@ -123,6 +124,7 @@ void TextureRect::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_flipped_v"), &TextureRect::is_flipped_v);
ClassDB::bind_method(D_METHOD("set_stretch_mode", "stretch_mode"), &TextureRect::set_stretch_mode);
ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureRect::get_stretch_mode);
+ ClassDB::bind_method(D_METHOD("_texture_changed"), &TextureRect::_texture_changed);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand");
@@ -140,9 +142,27 @@ void TextureRect::_bind_methods() {
BIND_ENUM_CONSTANT(STRETCH_KEEP_ASPECT_COVERED);
}
+void TextureRect::_texture_changed() {
+
+ if (texture.is_valid()) {
+ update();
+ minimum_size_changed();
+ }
+}
+
void TextureRect::set_texture(const Ref<Texture> &p_tex) {
+ if (p_tex == texture)
+ return;
+
+ if (texture.is_valid())
+ texture->disconnect(CoreStringNames::get_singleton()->changed, this, "_texture_changed");
+
texture = p_tex;
+
+ if (texture.is_valid())
+ texture->connect(CoreStringNames::get_singleton()->changed, this, "_texture_changed");
+
update();
/*
if (texture.is_valid())
diff --git a/scene/gui/texture_rect.h b/scene/gui/texture_rect.h
index 1c5bd9d99c..d144020562 100644
--- a/scene/gui/texture_rect.h
+++ b/scene/gui/texture_rect.h
@@ -56,6 +56,8 @@ private:
Ref<Texture> texture;
StretchMode stretch_mode;
+ void _texture_changed();
+
protected:
void _notification(int p_what);
virtual Size2 get_minimum_size() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 1b52796dc7..c9d1295557 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -827,6 +827,7 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_color", "column", "color"), &TreeItem::set_custom_color);
ClassDB::bind_method(D_METHOD("clear_custom_color", "column"), &TreeItem::clear_custom_color);
+ ClassDB::bind_method(D_METHOD("get_custom_color", "column"), &TreeItem::get_custom_color);
ClassDB::bind_method(D_METHOD("set_custom_bg_color", "column", "color", "just_outline"), &TreeItem::set_custom_bg_color, DEFVAL(false));
ClassDB::bind_method(D_METHOD("clear_custom_bg_color", "column"), &TreeItem::clear_custom_bg_color);
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index d15a972358..c2e2f85723 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -117,6 +117,7 @@ void ImageTexture::reload_from_file() {
} else {
Resource::reload_from_file();
_change_notify();
+ emit_changed();
}
}
@@ -180,6 +181,7 @@ void ImageTexture::_reload_hook(const RID &p_hook) {
VisualServer::get_singleton()->texture_set_data(texture, img);
_change_notify();
+ emit_changed();
}
void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags) {
@@ -190,6 +192,7 @@ void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uin
w = p_width;
h = p_height;
_change_notify();
+ emit_changed();
}
void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags) {
@@ -202,23 +205,23 @@ void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags
VisualServer::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_flags);
VisualServer::get_singleton()->texture_set_data(texture, p_image);
_change_notify();
+ emit_changed();
image_stored = true;
}
void ImageTexture::set_flags(uint32_t p_flags) {
- /* uint32_t cube = flags & FLAG_CUBEMAP;
- if (flags == p_flags&cube)
+ if (flags == p_flags)
return;
- flags=p_flags|cube; */
flags = p_flags;
if (w == 0 || h == 0) {
return; //uninitialized, do not set to texture
}
VisualServer::get_singleton()->texture_set_flags(texture, p_flags);
_change_notify("flags");
+ emit_changed();
}
uint32_t ImageTexture::get_flags() const {
@@ -250,6 +253,8 @@ void ImageTexture::set_data(const Ref<Image> &p_image) {
VisualServer::get_singleton()->texture_set_data(texture, p_image);
_change_notify();
+ emit_changed();
+
alpha_cache.unref();
image_stored = true;
}
@@ -736,6 +741,7 @@ Error StreamTexture::load(const String &p_path) {
format = image->get_format();
_change_notify();
+ emit_changed();
return OK;
}
String StreamTexture::get_load_path() const {
@@ -827,6 +833,7 @@ void StreamTexture::set_flags(uint32_t p_flags) {
flags = p_flags;
VS::get_singleton()->texture_set_flags(texture, flags);
_change_notify("flags");
+ emit_changed();
}
void StreamTexture::reload_from_file() {
diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp
index 0ca5d7eb36..2c22f45f9d 100644
--- a/scene/resources/world.cpp
+++ b/scene/resources/world.cpp
@@ -332,7 +332,9 @@ World::World() {
PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/3d/default_gravity", 9.8));
PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/3d/default_gravity_vector", Vector3(0, -1, 0)));
PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/3d/default_linear_damp", 0.1));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_linear_damp", PropertyInfo(Variant::REAL, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::REAL, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
#ifdef _3D_DISABLED
indexer = NULL;
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index 13b45f58dc..b5743ad416 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -394,7 +394,9 @@ World2D::World2D() {
Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98));
Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1)));
Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/2d/default_linear_damp", 0.1));
- Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::REAL, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
+ Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_angular_damp", PropertyInfo(Variant::REAL, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
indexer = memnew(SpatialIndexer2D);
}
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 3b549afb02..ae99d64eee 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -2914,6 +2914,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
bool ok = _parse_function_arguments(p_block, p_builtin_types, func, &carg);
+ // Check if block has a variable with the same name as function to prevent shader crash.
+ ShaderLanguage::BlockNode *bnode = p_block;
+ while (bnode) {
+ if (bnode->variables.has(name)) {
+ _set_error("Expected function name");
+ return NULL;
+ }
+ bnode = bnode->parent_block;
+ }
+
//test if function was parsed first
for (int i = 0; i < shader->functions.size(); i++) {
if (shader->functions[i].name == name) {
@@ -3842,9 +3852,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
StringName name = tk.text;
- if (_find_identifier(p_block, p_builtin_types, name)) {
- _set_error("Redefinition of '" + String(name) + "'");
- return ERR_PARSE_ERROR;
+ ShaderLanguage::IdentifierType itype;
+ if (_find_identifier(p_block, p_builtin_types, name, (ShaderLanguage::DataType *)0, &itype)) {
+ if (itype != IDENTIFIER_FUNCTION) {
+ _set_error("Redefinition of '" + String(name) + "'");
+ return ERR_PARSE_ERROR;
+ }
}
BlockNode::Variable var;
@@ -4002,6 +4015,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
return ERR_PARSE_ERROR;
}
+ if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ _set_error("Expected constant expression");
+ return ERR_PARSE_ERROR;
+ }
+
if (var.type != n->get_datatype()) {
_set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'");
return ERR_PARSE_ERROR;
@@ -4062,7 +4080,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!n)
return ERR_PARSE_ERROR;
-
+ if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ _set_error("Expected constant expression after '='");
+ return ERR_PARSE_ERROR;
+ }
decl.initializer = n;
if (var.type != n->get_datatype()) {
@@ -5121,9 +5142,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
pname = tk.text;
- if (_find_identifier(func_node->body, builtin_types, pname)) {
- _set_error("Redefinition of '" + String(pname) + "'");
- return ERR_PARSE_ERROR;
+ ShaderLanguage::IdentifierType itype;
+ if (_find_identifier(func_node->body, builtin_types, pname, (ShaderLanguage::DataType *)0, &itype)) {
+ if (itype != IDENTIFIER_FUNCTION) {
+ _set_error("Redefinition of '" + String(pname) + "'");
+ return ERR_PARSE_ERROR;
+ }
}
FunctionNode::Argument arg;
arg.type = ptype;