summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/class_db.h13
-rw-r--r--core/image.cpp32
-rw-r--r--core/io/multiplayer_api.cpp5
-rw-r--r--core/project_settings.cpp4
-rw-r--r--doc/classes/AnimationNode.xml2
-rw-r--r--doc/classes/DynamicFontData.xml4
-rw-r--r--doc/classes/Node.xml1
-rw-r--r--doc/classes/OS.xml1
-rw-r--r--doc/classes/PopupMenu.xml6
-rw-r--r--doc/classes/SceneTree.xml4
-rw-r--r--doc/classes/SphereMesh.xml2
-rw-r--r--doc/classes/SplitContainer.xml2
-rw-r--r--doc/classes/TextureProgress.xml2
-rw-r--r--doc/classes/Timer.xml2
-rw-r--r--doc/classes/VisualServer.xml2
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp6
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp13
-rw-r--r--drivers/gles3/shaders/canvas.glsl2
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp9
-rw-r--r--editor/spatial_editor_gizmos.cpp4
-rw-r--r--methods.py2
-rw-r--r--modules/etc/image_etc.cpp7
-rw-r--r--modules/gdnative/gdnative/gdnative.cpp13
-rw-r--r--modules/gdnative/gdnative_api.json15
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h4
-rw-r--r--modules/gdscript/gdscript_parser.cpp88
-rw-r--r--modules/mono/editor/bindings_generator.cpp17
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs6
-rw-r--r--scene/2d/line_2d.cpp2
-rw-r--r--scene/3d/camera.cpp3
-rw-r--r--scene/gui/popup_menu.cpp1
-rw-r--r--scene/gui/tree.cpp64
-rw-r--r--scene/main/scene_tree.cpp12
-rw-r--r--scene/main/scene_tree.h2
-rw-r--r--servers/visual/rasterizer.h1
-rw-r--r--servers/visual/visual_server_canvas.cpp4
-rw-r--r--servers/visual/visual_server_canvas.h2
-rw-r--r--servers/visual/visual_server_raster.h2
-rw-r--r--servers/visual/visual_server_wrap_mt.h2
-rw-r--r--servers/visual_server.cpp2
-rw-r--r--servers/visual_server.h2
42 files changed, 246 insertions, 123 deletions
diff --git a/core/class_db.h b/core/class_db.h
index 490deb7873..34301d6cba 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -114,6 +114,7 @@ public:
APIType api;
ClassInfo *inherits_ptr;
+ void *class_ptr;
HashMap<StringName, MethodBind *> method_map;
HashMap<StringName, int> constant_map;
HashMap<StringName, List<StringName> > enum_map;
@@ -177,6 +178,7 @@ public:
ERR_FAIL_COND(!t);
t->creation_func = &creator<T>;
t->exposed = true;
+ t->class_ptr = T::get_class_ptr_static();
T::register_custom_data_to_otdb();
}
@@ -188,6 +190,7 @@ public:
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->exposed = true;
+ t->class_ptr = T::get_class_ptr_static();
//nothing
}
@@ -206,6 +209,7 @@ public:
ERR_FAIL_COND(!t);
t->creation_func = &_create_ptr_func<T>;
t->exposed = true;
+ t->class_ptr = T::get_class_ptr_static();
T::register_custom_data_to_otdb();
}
@@ -293,6 +297,15 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 7);
}
+ template <class N, class M>
+ static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7, const Variant &p_def8) {
+
+ MethodBind *bind = create_method_bind(p_method);
+ const Variant *ptr[8] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7, &p_def8 };
+
+ return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 8);
+ }
+
template <class M>
static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
diff --git a/core/image.cpp b/core/image.cpp
index 5f99fe1532..672f850a1f 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -2432,19 +2432,19 @@ Color Image::get_pixel(int p_x, int p_y) const {
}
case FORMAT_RGBA4444: {
uint16_t u = ((uint16_t *)ptr)[ofs];
- float r = (u & 0xF) / 15.0;
- float g = ((u >> 4) & 0xF) / 15.0;
- float b = ((u >> 8) & 0xF) / 15.0;
- float a = ((u >> 12) & 0xF) / 15.0;
+ float r = ((u >> 12) & 0xF) / 15.0;
+ float g = ((u >> 8) & 0xF) / 15.0;
+ float b = ((u >> 4) & 0xF) / 15.0;
+ float a = (u & 0xF) / 15.0;
return Color(r, g, b, a);
}
case FORMAT_RGBA5551: {
uint16_t u = ((uint16_t *)ptr)[ofs];
- float r = (u & 0x1F) / 15.0;
- float g = ((u >> 5) & 0x1F) / 15.0;
- float b = ((u >> 10) & 0x1F) / 15.0;
- float a = ((u >> 15) & 0x1) / 1.0;
+ float r = ((u >> 11) & 0x1F) / 15.0;
+ float g = ((u >> 6) & 0x1F) / 15.0;
+ float b = ((u >> 1) & 0x1F) / 15.0;
+ float a = (u & 0x1) / 1.0;
return Color(r, g, b, a);
}
case FORMAT_RF: {
@@ -2558,10 +2558,10 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
uint16_t rgba = 0;
- rgba = uint16_t(CLAMP(p_color.r * 15.0, 0, 15));
- rgba |= uint16_t(CLAMP(p_color.g * 15.0, 0, 15)) << 4;
- rgba |= uint16_t(CLAMP(p_color.b * 15.0, 0, 15)) << 8;
- rgba |= uint16_t(CLAMP(p_color.a * 15.0, 0, 15)) << 12;
+ rgba = uint16_t(CLAMP(p_color.r * 15.0, 0, 15)) << 12;
+ rgba |= uint16_t(CLAMP(p_color.g * 15.0, 0, 15)) << 8;
+ rgba |= uint16_t(CLAMP(p_color.b * 15.0, 0, 15)) << 4;
+ rgba |= uint16_t(CLAMP(p_color.a * 15.0, 0, 15));
((uint16_t *)ptr)[ofs] = rgba;
@@ -2570,10 +2570,10 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
uint16_t rgba = 0;
- rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31));
- rgba |= uint16_t(CLAMP(p_color.g * 31.0, 0, 31)) << 5;
- rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 10;
- rgba |= uint16_t(p_color.a > 0.5 ? 1 : 0) << 15;
+ rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)) << 11;
+ rgba |= uint16_t(CLAMP(p_color.g * 31.0, 0, 31)) << 6;
+ rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 1;
+ rgba |= uint16_t(p_color.a > 0.5 ? 1 : 0);
((uint16_t *)ptr)[ofs] = rgba;
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index aaa7eb64c9..2708cb8c01 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -139,6 +139,9 @@ void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_pee
if (p_peer == network_peer) return; // Nothing to do
+ ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED,
+ "Supplied NetworkedMultiplayerPeer must be connecting or connected.");
+
if (network_peer.is_valid()) {
network_peer->disconnect("peer_connected", this, "_add_peer");
network_peer->disconnect("peer_disconnected", this, "_del_peer");
@@ -150,8 +153,6 @@ void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_pee
network_peer = p_peer;
- ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED, "Supplied NetworkedNetworkPeer must be connecting or connected.");
-
if (network_peer.is_valid()) {
network_peer->connect("peer_connected", this, "_add_peer");
network_peer->connect("peer_disconnected", this, "_del_peer");
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index c65c6252d6..a30967dcca 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -107,6 +107,10 @@ String ProjectSettings::localize_path(const String &p_path) const {
if (plocal == "") {
return "";
};
+ // Only strip the starting '/' from 'path' if its parent ('plocal') ends with '/'
+ if (plocal[plocal.length() - 1] == '/') {
+ sep += 1;
+ }
return plocal + path.substr(sep, path.size() - sep);
};
}
diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml
index b4288bbfaa..79ec0f0a47 100644
--- a/doc/classes/AnimationNode.xml
+++ b/doc/classes/AnimationNode.xml
@@ -204,7 +204,7 @@
</methods>
<members>
<member name="filter_enabled" type="bool" setter="set_filter_enabled" getter="is_filter_enabled">
- Returns whether filtering is enabled.
+ If [code]true[/code], filtering is enabled.
</member>
</members>
<signals>
diff --git a/doc/classes/DynamicFontData.xml b/doc/classes/DynamicFontData.xml
index ecdab32e80..399e103930 100644
--- a/doc/classes/DynamicFontData.xml
+++ b/doc/classes/DynamicFontData.xml
@@ -12,13 +12,13 @@
</methods>
<members>
<member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true">
- Controls whether the font should be rendered with anti-aliasing.
+ If [code]true[/code], the font is rendered with anti-aliasing.
</member>
<member name="font_path" type="String" setter="set_font_path" getter="get_font_path" default="&quot;&quot;">
The path to the vector font file.
</member>
<member name="hinting" type="int" setter="set_hinting" getter="get_hinting" enum="DynamicFontData.Hinting" default="2">
- The font hinting mode used by FreeType.
+ The font hinting mode used by FreeType. See [enum Hinting] for options.
</member>
</members>
<constants>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 193cfeb0ff..e3f1165c55 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -129,6 +129,7 @@
child_node.get_parent().remove_child(child_node)
add_child(child_node)
[/codeblock]
+ [b]Note:[/b] If you want a child to be persisted to a [PackedScene], you must set [member owner] in addition to calling [method add_child]. This is typically relevant for [url=https://godot.readthedocs.io/en/latest/tutorials/misc/running_code_in_the_editor.html]tool scripts[/url] and [url=https://godot.readthedocs.io/en/latest/tutorials/plugins/editor/index.html]editor plugins[/url]. If [method add_child] is called without setting [member owner], the newly added [Node] will not be visible in the scene tree, though it will be visible in the 2D/3D view.
</description>
</method>
<method name="add_child_below_node">
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 265e87eba3..22f4dc2d83 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -906,6 +906,7 @@
</member>
<member name="exit_code" type="int" setter="set_exit_code" getter="get_exit_code" default="0">
The exit code passed to the OS when the main loop exits. By convention, an exit code of [code]0[/code] indicates success whereas a non-zero exit code indicates an error. For portability reasons, the exit code should be set between 0 and 125 (inclusive).
+ [b]Note:[/b] This value will be ignored if using [method SceneTree.quit] with an [code]exit_code[/code] argument passed.
</member>
<member name="keep_screen_on" type="bool" setter="set_keep_screen_on" getter="is_keep_screen_on" default="true">
If [code]true[/code], the engine tries to keep the screen on while the game is running. Useful on mobile.
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index bdb6ca84ee..c920b52df6 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -334,7 +334,7 @@
<return type="bool">
</return>
<description>
- Returns whether the popup will be hidden when the window loses focus or not.
+ Returns [code]true[/code] if the popup will be hidden when the window loses focus or not.
</description>
</method>
<method name="is_item_checkable" qualifiers="const">
@@ -391,7 +391,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Returns whether the shortcut of the specified item [code]idx[/code] is disabled or not.
+ Returns [code]true[/code] if the specified item's shortcut is disabled.
</description>
</method>
<method name="remove_item">
@@ -477,7 +477,7 @@
<argument index="1" name="disabled" type="bool">
</argument>
<description>
- Sets whether the item at index [code]idx[/code] is disabled or not. When it is disabled, it can't be selected and its action can't be invoked.
+ Enables/disables the item at index [code]idx[/code]. When it is disabled, it can't be selected and its action can't be invoked.
</description>
</method>
<method name="set_item_icon">
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index 0635dd8935..6a4105ca2f 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -185,8 +185,10 @@
<method name="quit">
<return type="void">
</return>
+ <argument index="0" name="exit_code" type="int" default="-1">
+ </argument>
<description>
- Quits the application.
+ Quits the application. A process [code]exit_code[/code] can optionally be passed as an argument. If this argument is [code]0[/code] or greater, it will override the [member OS.exit_code] defined before quitting the application.
</description>
</method>
<method name="reload_current_scene">
diff --git a/doc/classes/SphereMesh.xml b/doc/classes/SphereMesh.xml
index 6d81d8ff82..43f19f9f4e 100644
--- a/doc/classes/SphereMesh.xml
+++ b/doc/classes/SphereMesh.xml
@@ -15,7 +15,7 @@
Full height of the sphere.
</member>
<member name="is_hemisphere" type="bool" setter="set_is_hemisphere" getter="get_is_hemisphere" default="false">
- Determines whether a full sphere or a hemisphere is created.
+ If [code]true[/code], a hemisphere is created rather than a full sphere.
[b]Note:[/b] To get a regular hemisphere, the height and radius of the sphere must be equal.
</member>
<member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments" default="64">
diff --git a/doc/classes/SplitContainer.xml b/doc/classes/SplitContainer.xml
index d756c17cef..71731f685a 100644
--- a/doc/classes/SplitContainer.xml
+++ b/doc/classes/SplitContainer.xml
@@ -20,7 +20,7 @@
<member name="collapsed" type="bool" setter="set_collapsed" getter="is_collapsed" default="false">
</member>
<member name="dragger_visibility" type="int" setter="set_dragger_visibility" getter="get_dragger_visibility" enum="SplitContainer.DraggerVisibility" default="0">
- Determines whether the dragger is visible.
+ Determines the dragger's visibility. See [enum DraggerVisibility] for options.
</member>
<member name="split_offset" type="int" setter="set_split_offset" getter="get_split_offset" default="0">
</member>
diff --git a/doc/classes/TextureProgress.xml b/doc/classes/TextureProgress.xml
index 479ab865ba..c16d6f58bc 100644
--- a/doc/classes/TextureProgress.xml
+++ b/doc/classes/TextureProgress.xml
@@ -86,7 +86,7 @@
The [member texture_progress] fills from right to left.
</constant>
<constant name="FILL_TOP_TO_BOTTOM" value="2" enum="FillMode">
- The [member texture_progress] fills from top to bototm.
+ The [member texture_progress] fills from top to bottom.
</constant>
<constant name="FILL_BOTTOM_TO_TOP" value="3" enum="FillMode">
The [member texture_progress] fills from bottom to top.
diff --git a/doc/classes/Timer.xml b/doc/classes/Timer.xml
index 4f455fb377..3e4b68d91d 100644
--- a/doc/classes/Timer.xml
+++ b/doc/classes/Timer.xml
@@ -49,7 +49,7 @@
</member>
<member name="time_left" type="float" setter="" getter="get_time_left">
The timer's remaining time in seconds. Returns 0 if the timer is inactive.
- [b]Note:[/b] You cannot set this value. To change the timer's remaining time, use [member wait_time].
+ [b]Note:[/b] You cannot set this value. To change the timer's remaining time, use [method start].
</member>
<member name="wait_time" type="float" setter="set_wait_time" getter="get_wait_time" default="1.0">
Wait time in seconds.
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index f804e32c4b..a216d4b7b3 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -422,6 +422,8 @@
</argument>
<argument index="10" name="antialiased" type="bool" default="false">
</argument>
+ <argument index="11" name="antialiasing_use_indices" type="bool" default="false">
+ </argument>
<description>
Adds a triangle array to the [CanvasItem]'s draw commands.
</description>
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 45c9e66c73..10c9846fde 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -1033,7 +1033,11 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
#ifdef GLES_OVER_GL
if (polygon->antialiased) {
glEnable(GL_LINE_SMOOTH);
- _draw_generic_indices(GL_LINE_STRIP, polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+ if (polygon->antialiasing_use_indices) {
+ _draw_generic_indices(GL_LINE_STRIP, polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+ } else {
+ _draw_generic(GL_LINE_LOOP, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+ }
glDisable(GL_LINE_SMOOTH);
}
#endif
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index c6067e7f58..55a38c917f 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -901,7 +901,11 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
#ifdef GLES_OVER_GL
if (polygon->antialiased) {
glEnable(GL_LINE_SMOOTH);
- _draw_generic_indices(GL_LINE_STRIP, polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+ if (polygon->antialiasing_use_indices) {
+ _draw_generic_indices(GL_LINE_STRIP, polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+ } else {
+ _draw_generic(GL_LINE_LOOP, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+ }
glDisable(GL_LINE_SMOOTH);
}
#endif
@@ -1413,7 +1417,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
}
if (skeleton) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
glBindTexture(GL_TEXTURE_2D, skeleton->texture);
state.using_skeleton = true;
} else {
@@ -1677,7 +1681,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
bool light_rebind = state.canvas_shader.bind();
if (light_rebind) {
-
state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate);
state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform);
state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, Transform2D());
@@ -1686,6 +1689,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
} else {
state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0));
}
+ if (state.using_skeleton) {
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform);
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse);
+ }
}
glBindBufferBase(GL_UNIFORM_BUFFER, 1, static_cast<LightInternal *>(light->light_internal.get_data())->ubo);
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index ec18c83df3..07ee9cd010 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -55,7 +55,7 @@ out highp vec2 pixel_size_interp;
#endif
#ifdef USE_SKELETON
-uniform mediump sampler2D skeleton_texture; // texunit:-1
+uniform mediump sampler2D skeleton_texture; // texunit:-4
uniform highp mat4 skeleton_transform;
uniform highp mat4 skeleton_transform_inverse;
#endif
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 3426e58543..92e3f61ca5 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -456,7 +456,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/appearance/show_info_gutter", true);
_initial_set("text_editor/appearance/code_folding", true);
_initial_set("text_editor/appearance/word_wrap", false);
- _initial_set("text_editor/appearance/show_line_length_guideline", false);
+ _initial_set("text_editor/appearance/show_line_length_guideline", true);
_initial_set("text_editor/appearance/line_length_guideline_column", 80);
hints["text_editor/appearance/line_length_guideline_column"] = PropertyInfo(Variant::INT, "text_editor/appearance/line_length_guideline_column", PROPERTY_HINT_RANGE, "20, 160, 1");
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 4949d1a4e5..f5128103f3 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -1479,9 +1479,16 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
if (d.has("alphaMode")) {
const String &am = d["alphaMode"];
- if (am != "OPAQUE") {
+ if (am == "BLEND") {
material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
material->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ } else if (am == "MASK") {
+ material->set_flag(SpatialMaterial::FLAG_USE_ALPHA_SCISSOR, true);
+ if (d.has("alphaCutoff")) {
+ material->set_alpha_scissor_threshold(d["alphaCutoff"]);
+ } else {
+ material->set_alpha_scissor_threshold(0.5f);
+ }
}
}
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 29b6c12b23..3ea5272ebf 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -736,11 +736,11 @@ void EditorSpatialGizmo::set_plugin(EditorSpatialGizmoPlugin *p_plugin) {
void EditorSpatialGizmo::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_lines", "lines", "material", "billboard"), &EditorSpatialGizmo::add_lines, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_lines", "lines", "material", "billboard"), &EditorSpatialGizmo::add_lines, DEFVAL(false), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "billboard", "skeleton", "material"), &EditorSpatialGizmo::add_mesh, DEFVAL(false), DEFVAL(Ref<SkinReference>()), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("add_collision_segments", "segments"), &EditorSpatialGizmo::add_collision_segments);
ClassDB::bind_method(D_METHOD("add_collision_triangles", "triangles"), &EditorSpatialGizmo::add_collision_triangles);
- ClassDB::bind_method(D_METHOD("add_unscaled_billboard", "material", "default_scale"), &EditorSpatialGizmo::add_unscaled_billboard, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("add_unscaled_billboard", "material", "default_scale"), &EditorSpatialGizmo::add_unscaled_billboard, DEFVAL(1), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "billboard", "secondary"), &EditorSpatialGizmo::add_handles, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_spatial_node", "node"), &EditorSpatialGizmo::_set_spatial_node);
ClassDB::bind_method(D_METHOD("get_spatial_node"), &EditorSpatialGizmo::get_spatial_node);
diff --git a/methods.py b/methods.py
index 84074db0eb..23d66f7f1e 100644
--- a/methods.py
+++ b/methods.py
@@ -1,9 +1,7 @@
import os
import os.path
-import sys
import re
import glob
-import string
import subprocess
from compat import iteritems, isbasestring, decode_utf8
diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp
index 7cd5e2eb12..f0b95c893d 100644
--- a/modules/etc/image_etc.cpp
+++ b/modules/etc/image_etc.cpp
@@ -139,6 +139,13 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f
return;
}
+ if (img_format >= Image::FORMAT_RGBA8 && force_etc1_format) {
+ // If VRAM compression is using ETC, but image has alpha, convert to RGBA4444
+ // This saves space while maintaining the alpha channel
+ p_img->convert(Image::FORMAT_RGBA4444);
+ return;
+ }
+
uint32_t imgw = p_img->get_width(), imgh = p_img->get_height();
Image::Format etc_format = force_etc1_format ? Image::FORMAT_ETC : _get_etc2_mode(detected_channels);
diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp
index 174ef14ec2..6ef1f2f4b9 100644
--- a/modules/gdnative/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative/gdnative.cpp
@@ -170,6 +170,19 @@ bool GDAPI godot_is_instance_valid(const godot_object *p_object) {
return ObjectDB::instance_validate((Object *)p_object);
}
+void *godot_get_class_tag(const godot_string_name *p_class) {
+ StringName class_name = *(StringName *)p_class;
+ ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(class_name);
+ return class_info ? class_info->class_ptr : NULL;
+}
+
+godot_object *godot_object_cast_to(const godot_object *p_object, void *p_class_tag) {
+ if (!p_object) return NULL;
+ Object *o = (Object *)p_object;
+
+ return o->is_class_ptr(p_class_tag) ? (godot_object *)o : NULL;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 9e5295a936..7e2ca49f8d 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -140,6 +140,21 @@
"arguments": [
["const godot_pool_color_array *", "p_self"]
]
+ },
+ {
+ "name": "godot_get_class_tag",
+ "return_type": "void *",
+ "arguments": [
+ ["const godot_string_name *", "p_class"]
+ ]
+ },
+ {
+ "name": "godot_object_cast_to",
+ "return_type": "godot_object *",
+ "arguments": [
+ ["const godot_object *", "p_object"],
+ ["void *", "p_class_tag"]
+ ]
}
]
},
diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index 5a6333e814..2fe59b8a73 100644
--- a/modules/gdnative/include/gdnative/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -286,6 +286,10 @@ void GDAPI godot_print(const godot_string *p_message);
bool GDAPI godot_is_instance_valid(const godot_object *p_object);
+//tags used for safe dynamic casting
+void GDAPI *godot_get_class_tag(const godot_string_name *p_class);
+godot_object GDAPI *godot_object_cast_to(const godot_object *p_object, void *p_class_tag);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 220168ad7c..112569a8d6 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -4045,7 +4045,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
- tokenizer->advance();
+#define _ADVANCE_AND_CONSUME_NEWLINES \
+ do { \
+ tokenizer->advance(); \
+ } while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE)
+
+ _ADVANCE_AND_CONSUME_NEWLINES;
+ parenthesis++;
String hint_prefix = "";
bool is_arrayed = false;
@@ -4075,11 +4081,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.type = type;
current_export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
// hint expected next!
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
switch (type) {
@@ -4087,7 +4093,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
WARN_DEPRECATED_MSG("Exporting bit flags hint requires string constants.");
@@ -4099,7 +4105,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.hint = PROPERTY_HINT_FLAGS;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
bool first = true;
while (true) {
@@ -4118,7 +4124,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
current_export.hint_string += c.xml_escape();
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4127,7 +4133,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Expected \")\" or \",\" in the named bit flags hint.");
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
break;
@@ -4135,7 +4141,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_RENDER") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the layers 2D render hint.");
return;
@@ -4146,7 +4152,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_PHYSICS") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the layers 2D physics hint.");
return;
@@ -4157,7 +4163,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_RENDER") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the layers 3D render hint.");
return;
@@ -4168,7 +4174,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_PHYSICS") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the layers 3D physics hint.");
return;
@@ -4198,7 +4204,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
current_export.hint_string += c.xml_escape();
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4208,7 +4214,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
break;
@@ -4220,7 +4226,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EASE") {
current_export.hint = PROPERTY_HINT_EXP_EASING;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the hint.");
return;
@@ -4232,7 +4238,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EXP") {
current_export.hint = PROPERTY_HINT_EXP_RANGE;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4240,7 +4246,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Expected \")\" or \",\" in the exponential range hint.");
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
} else
current_export.hint = PROPERTY_HINT_RANGE;
@@ -4248,7 +4254,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
@@ -4258,7 +4264,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.hint_string = rtos(sign * double(tokenizer->get_token_constant()));
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
current_export.hint_string = "0," + current_export.hint_string;
@@ -4272,12 +4278,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
sign = 1.0;
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
@@ -4288,7 +4294,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.hint_string += "," + rtos(sign * double(tokenizer->get_token_constant()));
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4300,11 +4306,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
sign = 1.0;
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB) {
sign = -1;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
@@ -4315,7 +4321,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
current_export.hint_string += "," + rtos(sign * double(tokenizer->get_token_constant()));
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
} break;
case Variant::STRING: {
@@ -4340,7 +4346,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
first = false;
current_export.hint_string += c.xml_escape();
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
@@ -4349,7 +4355,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Expected \")\" or \",\" in the enumeration hint.");
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
break;
@@ -4357,13 +4363,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "DIR") {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
current_export.hint = PROPERTY_HINT_DIR;
else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER || !(tokenizer->get_token_identifier() == "GLOBAL")) {
_set_error("Expected \"GLOBAL\" after comma in the directory hint.");
@@ -4374,7 +4380,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
current_export.hint = PROPERTY_HINT_GLOBAL_DIR;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the hint.");
@@ -4390,11 +4396,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FILE") {
current_export.hint = PROPERTY_HINT_FILE;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "GLOBAL") {
@@ -4403,12 +4409,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
current_export.hint = PROPERTY_HINT_GLOBAL_FILE;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA)
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
else {
_set_error("Expected \")\" or \",\" in the hint.");
return;
@@ -4424,7 +4430,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
current_export.hint_string = tokenizer->get_token_constant();
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
@@ -4437,7 +4443,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "MULTILINE") {
current_export.hint = PROPERTY_HINT_MULTILINE_TEXT;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected \")\" in the hint.");
return;
@@ -4464,7 +4470,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Color type hint expects RGB or RGBA as hints.");
return;
}
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
} break;
default: {
@@ -4515,11 +4521,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
bool is_flags = false;
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") {
is_flags = true;
- tokenizer->advance();
+ _ADVANCE_AND_CONSUME_NEWLINES;
} else {
current_export = PropertyInfo();
_set_error("Expected \"FLAGS\" after comma.");
@@ -4563,6 +4569,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
+ tokenizer->advance();
+ parenthesis--;
+
if (is_arrayed) {
hint_prefix += itos(current_export.type);
if (current_export.hint) {
@@ -4572,8 +4581,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
current_export.hint = PROPERTY_HINT_TYPE_STRING;
current_export.type = Variant::ARRAY;
}
-
- tokenizer->advance();
+#undef _ADVANCE_AND_CONSUME_NEWLINES
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPET && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPETSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE) {
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index cb5802181b..9beadb1778 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -1602,7 +1602,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Apparently the name attribute must not include the @
String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name;
- default_args_doc.append(INDENT2 "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + def_arg + "</param>\n");
+ default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + def_arg + "</param>");
} else {
icall_params += arg_type->cs_in.empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
}
@@ -1621,7 +1621,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
String xml_summary = bbcode_to_xml(fix_doc_description(p_imethod.method_doc->description), &p_itype);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
- if (summary_lines.size() || default_args_doc.get_string_length()) {
+ if (summary_lines.size()) {
p_output.append(MEMBER_BEGIN "/// <summary>\n");
for (int i = 0; i < summary_lines.size(); i++) {
@@ -1630,11 +1630,14 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
p_output.append("\n");
}
- p_output.append(default_args_doc.as_string());
p_output.append(INDENT2 "/// </summary>");
}
}
+ if (default_args_doc.get_string_length()) {
+ p_output.append(default_args_doc.as_string());
+ }
+
if (!p_imethod.is_internal) {
p_output.append(MEMBER_BEGIN "[GodotMethod(\"");
p_output.append(p_imethod.name);
@@ -2066,9 +2069,11 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
p_output.append(", total_length, vcall_error);\n");
- // See the comment on the C_LOCAL_VARARG_RET declaration
- if (return_type->cname != name_cache.type_Variant) {
- p_output.append("\t" C_LOCAL_RET " = " C_LOCAL_VARARG_RET ";\n");
+ if (!ret_void) {
+ // See the comment on the C_LOCAL_VARARG_RET declaration
+ if (return_type->cname != name_cache.type_Variant) {
+ p_output.append("\t" C_LOCAL_RET " = " C_LOCAL_VARARG_RET ";\n");
+ }
}
} else {
p_output.append("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", ");
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
index 54821fe790..ddfed180b5 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
@@ -266,12 +266,14 @@ namespace Godot
public static int Sign(int s)
{
+ if (s == 0) return 0;
return s < 0 ? -1 : 1;
}
- public static real_t Sign(real_t s)
+ public static int Sign(real_t s)
{
- return s < 0f ? -1f : 1f;
+ if (s == 0) return 0;
+ return s < 0 ? -1 : 1;
}
public static real_t Sin(real_t s)
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 7f25face15..4a022f0a9c 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -316,7 +316,7 @@ void Line2D::_draw() {
lb.colors,
lb.uvs, Vector<int>(), Vector<float>(),
texture_rid, -1, RID(),
- _antialiased);
+ _antialiased, true);
// DEBUG
// Draw wireframe
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index bbc81afe3d..289dc0ba07 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -390,10 +390,9 @@ Vector3 Camera::project_position(const Point2 &p_point, float p_z_depth) const {
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene.");
- if (p_z_depth == 0) {
+ if (p_z_depth == 0 && mode != PROJECTION_ORTHOGONAL) {
return get_global_transform().origin;
}
-
Size2 viewport_size = get_viewport()->get_visible_rect().size;
CameraMatrix cm;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index e6333a6179..87f17838cf 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -309,6 +309,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
bool was_during_grabbed_click = during_grabbed_click;
during_grabbed_click = false;
+ initial_button_mask = 0;
int over = _get_mouse_over(b->get_position());
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 3cf17bd210..964f376dbd 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2745,9 +2745,13 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid()) {
- double prev_value = v_scroll->get_value();
+ double prev_v = v_scroll->get_value();
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
- if (v_scroll->get_value() != prev_value) {
+
+ double prev_h = h_scroll->get_value();
+ h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
+
+ if (v_scroll->get_value() != prev_v || h_scroll->get_value() != prev_h) {
accept_event();
}
}
@@ -3455,30 +3459,48 @@ int Tree::get_item_offset(TreeItem *p_item) const {
}
void Tree::ensure_cursor_is_visible() {
-
- if (!is_inside_tree())
+ if (!is_inside_tree()) {
return;
+ }
+ if (!selected_item || (selected_col == -1)) {
+ return; // Nothing under cursor.
+ }
- TreeItem *selected = get_selected();
- if (!selected)
- return;
- int ofs = get_item_offset(selected);
- if (ofs == -1)
- return;
+ const Size2 area_size = get_size() - cache.bg->get_minimum_size();
- const int tbh = _get_title_button_height();
- ofs -= tbh;
+ int y_offset = get_item_offset(selected_item);
+ if (y_offset != -1) {
+ const int tbh = _get_title_button_height();
+ y_offset -= tbh;
- const int marginh = cache.bg->get_margin(MARGIN_TOP) + cache.bg->get_margin(MARGIN_BOTTOM);
- int h = compute_item_height(selected) + cache.vseparation;
- int screenh = get_size().height - h_scroll->get_combined_minimum_size().height - marginh - tbh;
+ const int cell_h = compute_item_height(selected_item) + cache.vseparation;
+ const int screen_h = area_size.height - h_scroll->get_combined_minimum_size().height - tbh;
- if (h > screenh) { //screen size is too small, maybe it was not resized yet.
- v_scroll->set_value(ofs);
- } else if (ofs + h > v_scroll->get_value() + screenh) {
- v_scroll->call_deferred("set_value", ofs - screenh + h);
- } else if (ofs < v_scroll->get_value()) {
- v_scroll->set_value(ofs);
+ if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
+ v_scroll->set_value(y_offset);
+ } else if (y_offset + cell_h > v_scroll->get_value() + screen_h) {
+ v_scroll->call_deferred("set_value", y_offset - screen_h + cell_h);
+ } else if (y_offset < v_scroll->get_value()) {
+ v_scroll->set_value(y_offset);
+ }
+ }
+
+ if (select_mode != SELECT_ROW) { // Cursor always at col 0 in this mode.
+ int x_offset = 0;
+ for (int i = 0; i < selected_col; i++) {
+ x_offset += get_column_width(i);
+ }
+
+ const int cell_w = get_column_width(selected_col);
+ const int screen_w = area_size.width - v_scroll->get_combined_minimum_size().width;
+
+ if (cell_w > screen_w) {
+ h_scroll->set_value(x_offset);
+ } else if (x_offset + cell_w > h_scroll->get_value() + screen_w) {
+ h_scroll->call_deferred("set_value", x_offset - screen_w + cell_w);
+ } else if (x_offset < h_scroll->get_value()) {
+ h_scroll->set_value(x_offset);
+ }
}
}
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 09b001b377..da147e7112 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -631,7 +631,13 @@ void SceneTree::finish() {
timers.clear();
}
-void SceneTree::quit() {
+void SceneTree::quit(int p_exit_code) {
+
+ if (p_exit_code >= 0) {
+ // Override the exit code if a positive argument is given (the default is `-1`).
+ // This is a shorthand for calling `set_exit_code()` on the OS singleton then quitting.
+ OS::get_singleton()->set_exit_code(p_exit_code);
+ }
_quit = true;
}
@@ -1812,8 +1818,6 @@ bool SceneTree::is_refusing_new_network_connections() const {
void SceneTree::_bind_methods() {
- //ClassDB::bind_method(D_METHOD("call_group","call_flags","group","method","arg1","arg2"),&SceneMainLoop::_call_group,DEFVAL(Variant()),DEFVAL(Variant()));
-
ClassDB::bind_method(D_METHOD("get_root"), &SceneTree::get_root);
ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group);
@@ -1837,7 +1841,7 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count);
ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);
- ClassDB::bind_method(D_METHOD("quit"), &SceneTree::quit);
+ ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "shrink"), &SceneTree::set_screen_stretch, DEFVAL(1));
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 9bb24238f2..55304fb12d 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -303,7 +303,7 @@ public:
void set_auto_accept_quit(bool p_enable);
void set_quit_on_go_back(bool p_enable);
- void quit();
+ void quit(int p_exit_code = -1);
void set_input_as_handled();
bool is_input_handled();
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index c1f09cda21..74741a946c 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -782,6 +782,7 @@ public:
RID normal_map;
int count;
bool antialiased;
+ bool antialiasing_use_indices;
CommandPolygon() {
type = TYPE_POLYGON;
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index d4fba708b1..e07e188ec6 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -778,12 +778,13 @@ void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2
polygon->indices = indices;
polygon->count = indices.size();
polygon->antialiased = p_antialiased;
+ polygon->antialiasing_use_indices = false;
canvas_item->rect_dirty = true;
canvas_item->commands.push_back(polygon);
}
-void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count, RID p_normal_map, bool p_antialiased) {
+void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count, RID p_normal_map, bool p_antialiased, bool p_antialiasing_use_indices) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -823,6 +824,7 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector
polygon->indices = indices;
polygon->count = count;
polygon->antialiased = p_antialiased;
+ polygon->antialiasing_use_indices = p_antialiasing_use_indices;
canvas_item->rect_dirty = true;
canvas_item->commands.push_back(polygon);
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 366ec4d689..a2c641ce76 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -200,7 +200,7 @@ public:
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, VS::NinePatchAxisMode p_x_axis_mode = VS::NINE_PATCH_STRETCH, VS::NinePatchAxisMode p_y_axis_mode = VS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID());
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID());
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false);
- void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), bool p_antialiased = false);
+ void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), bool p_antialiased = false, bool p_antialiasing_use_indices = false);
void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal);
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 51521446cd..54c46b1812 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -602,7 +602,7 @@ public:
BIND11(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID)
BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
BIND7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)
- BIND11(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, bool)
+ BIND12(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, bool, bool)
BIND6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID)
BIND4(canvas_item_add_multimesh, RID, RID, RID, RID)
BIND4(canvas_item_add_particles, RID, RID, RID, RID)
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index c218c47b43..f5875f4fad 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -520,7 +520,7 @@ public:
FUNC11(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID)
FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)
- FUNC11(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, bool)
+ FUNC12(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, bool, bool)
FUNC6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID)
FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID)
FUNC4(canvas_item_add_particles, RID, RID, RID, RID)
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 8ba2b42b4b..1f72848b15 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -1974,7 +1974,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate", "normal_map"), &VisualServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &VisualServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &VisualServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map", "antialiased"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map", "antialiased", "antialiasing_use_indices"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture", "normal_map"), &VisualServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map"), &VisualServer::canvas_item_add_particles);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 80c2142458..9aeee731b3 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -903,7 +903,7 @@ public:
virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false) = 0;
- virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), bool p_antialiased = false, bool p_antialiasing_use_indices = false) = 0;
virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map) = 0;