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/PopupMenu.xml51
-rw-r--r--drivers/unix/net_socket_posix.cpp20
-rw-r--r--drivers/unix/net_socket_posix.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp8
-rw-r--r--modules/gdnative/doc_classes/GDNativeLibrary.xml2
-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/gui/popup_menu.cpp166
-rw-r--r--scene/gui/popup_menu.h14
-rw-r--r--scene/gui/text_edit.cpp5
-rw-r--r--scene/resources/world.cpp2
-rw-r--r--scene/resources/world_2d.cpp4
31 files changed, 264 insertions, 117 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/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/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/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 7055abd643..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);
diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml
index ae9a00543c..aa48ab44f2 100644
--- a/modules/gdnative/doc_classes/GDNativeLibrary.xml
+++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml
@@ -39,7 +39,7 @@
[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]gdnative_singleton[/code] after initializing the library. The library remains loaded as long as Godot is running.
+ 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;">
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/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/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/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);
}