summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/object/message_queue.cpp57
-rw-r--r--core/object/message_queue.h2
-rw-r--r--doc/classes/CanvasItem.xml10
-rw-r--r--doc/classes/RenderingServer.xml3
-rw-r--r--editor/editor_help.cpp16
-rw-r--r--editor/editor_help.h4
-rw-r--r--editor/editor_inspector.cpp18
-rw-r--r--editor/editor_inspector.h2
-rw-r--r--editor/editor_properties.cpp9
-rw-r--r--editor/editor_properties_array_dict.cpp16
-rw-r--r--editor/plugins/text_shader_editor.cpp5
-rw-r--r--misc/dist/html/full-size.html2
-rw-r--r--misc/extension_api_validation/4.2-stable.expected13
-rw-r--r--modules/gdscript/gdscript.cpp9
-rw-r--r--modules/gdscript/gdscript.h2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp15
-rw-r--r--modules/gdscript/gdscript_parser.h10
-rw-r--r--platform/web/export/export_plugin.cpp6
-rw-r--r--scene/main/canvas_item.compat.inc24
-rw-r--r--scene/main/canvas_item.cpp34
-rw-r--r--scene/main/canvas_item.h14
-rw-r--r--scene/resources/canvas_item_material.cpp26
-rw-r--r--scene/resources/canvas_item_material.h3
-rw-r--r--scene/resources/material.cpp34
-rw-r--r--scene/resources/material.h4
-rw-r--r--scene/resources/particle_process_material.cpp25
-rw-r--r--scene/resources/particle_process_material.h3
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp288
-rw-r--r--servers/rendering/renderer_canvas_cull.h6
-rw-r--r--servers/rendering/rendering_server_default.h6
-rw-r--r--servers/rendering_server.compat.inc15
-rw-r--r--servers/rendering_server.cpp6
-rw-r--r--servers/rendering_server.h10
-rw-r--r--tests/scene/test_curve_2d.h45
-rw-r--r--tests/scene/test_curve_3d.h20
-rw-r--r--version.py2
36 files changed, 510 insertions, 254 deletions
diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp
index 6fab934395..9351253c6f 100644
--- a/core/object/message_queue.cpp
+++ b/core/object/message_queue.cpp
@@ -224,64 +224,7 @@ void CallQueue::_call_function(const Callable &p_callable, const Variant *p_args
}
}
-Error CallQueue::_transfer_messages_to_main_queue() {
- if (pages.size() == 0) {
- return OK;
- }
-
- CallQueue *mq = MessageQueue::main_singleton;
- DEV_ASSERT(!mq->allocator_is_custom && !allocator_is_custom); // Transferring pages is only safe if using the same alloator parameters.
-
- mq->mutex.lock();
-
- // Here we're transferring the data from this queue to the main one.
- // However, it's very unlikely big amounts of messages will be queued here,
- // so PagedArray/Pool would be overkill. Also, in most cases the data will fit
- // an already existing page of the main queue.
-
- // Let's see if our first (likely only) page fits the current target queue page.
- uint32_t src_page = 0;
- {
- if (mq->pages_used) {
- uint32_t dst_page = mq->pages_used - 1;
- uint32_t dst_offset = mq->page_bytes[dst_page];
- if (dst_offset + page_bytes[0] < uint32_t(PAGE_SIZE_BYTES)) {
- memcpy(mq->pages[dst_page]->data + dst_offset, pages[0]->data, page_bytes[0]);
- mq->page_bytes[dst_page] += page_bytes[0];
- src_page++;
- }
- }
- }
-
- // Any other possibly existing source page needs to be added.
-
- if (mq->pages_used + (pages_used - src_page) > mq->max_pages) {
- fprintf(stderr, "Failed appending thread queue. Message queue out of memory. %s\n", mq->error_text.utf8().get_data());
- mq->statistics();
- mq->mutex.unlock();
- return ERR_OUT_OF_MEMORY;
- }
-
- for (; src_page < pages_used; src_page++) {
- mq->_add_page();
- memcpy(mq->pages[mq->pages_used - 1]->data, pages[src_page]->data, page_bytes[src_page]);
- mq->page_bytes[mq->pages_used - 1] = page_bytes[src_page];
- }
-
- mq->mutex.unlock();
-
- page_bytes[0] = 0;
- pages_used = 1;
-
- return OK;
-}
-
Error CallQueue::flush() {
- // Thread overrides are not meant to be flushed, but appended to the main one.
- if (unlikely(this == MessageQueue::thread_singleton)) {
- return _transfer_messages_to_main_queue();
- }
-
LOCK_MUTEX;
if (pages.size() == 0) {
diff --git a/core/object/message_queue.h b/core/object/message_queue.h
index c2f4ad1643..9f567e4dd0 100644
--- a/core/object/message_queue.h
+++ b/core/object/message_queue.h
@@ -98,8 +98,6 @@ private:
}
}
- Error _transfer_messages_to_main_queue();
-
void _add_page();
void _call_function(const Callable &p_callable, const Variant *p_args, int p_argcount, bool p_show_error);
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index bf53cb2e14..207045b065 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -84,6 +84,7 @@
Draws a circle. See also [method draw_arc], [method draw_polyline], and [method draw_polygon].
If [param filled] is [code]true[/code], the circle will be filled with the [param color] specified. If [param filled] is [code]false[/code], the circle will be drawn as a stroke with the [param color] and [param width] specified.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
[b]Note:[/b] [param width] is only effective if [param filled] is [code]false[/code].
</description>
</method>
@@ -105,9 +106,12 @@
<param index="3" name="width" type="float" default="-1.0" />
<param index="4" name="dash" type="float" default="2.0" />
<param index="5" name="aligned" type="bool" default="true" />
+ <param index="6" name="antialiased" type="bool" default="false" />
<description>
Draws a dashed line from a 2D point to another, with a given color and width. See also [method draw_multiline] and [method draw_polyline].
If [param width] is negative, then a two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the line parts will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
+ [b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_end_animation">
@@ -175,9 +179,11 @@
<param index="0" name="points" type="PackedVector2Array" />
<param index="1" name="color" type="Color" />
<param index="2" name="width" type="float" default="-1.0" />
+ <param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws multiple disconnected lines with a uniform [param width] and [param color]. Each line is defined by two consecutive points from [param points] array, i.e. i-th segment consists of [code]points[2 * i][/code], [code]points[2 * i + 1][/code] endpoints. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw interconnected lines, use [method draw_polyline] instead.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ [b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_multiline_colors">
@@ -185,9 +191,11 @@
<param index="0" name="points" type="PackedVector2Array" />
<param index="1" name="colors" type="PackedColorArray" />
<param index="2" name="width" type="float" default="-1.0" />
+ <param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws multiple disconnected lines with a uniform [param width] and segment-by-segment coloring. Each segment is defined by two consecutive points from [param points] array and a corresponding color from [param colors] array, i.e. i-th segment consists of [code]points[2 * i][/code], [code]points[2 * i + 1][/code] endpoints and has [code]colors[i][/code] color. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw interconnected lines, use [method draw_polyline_colors] instead.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ [b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_multiline_string" qualifiers="const">
@@ -283,9 +291,11 @@
<param index="1" name="color" type="Color" />
<param index="2" name="filled" type="bool" default="true" />
<param index="3" name="width" type="float" default="-1.0" />
+ <param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a rectangle. If [param filled] is [code]true[/code], the rectangle will be filled with the [param color] specified. If [param filled] is [code]false[/code], the rectangle will be drawn as a stroke with the [param color] and [param width] specified. See also [method draw_texture_rect].
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
[b]Note:[/b] [param width] is only effective if [param filled] is [code]false[/code].
[b]Note:[/b] Unfilled rectangles drawn with a negative [param width] may not display perfectly. For example, corners may be missing or brighter due to overlapping lines (for a translucent [param color]).
</description>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 110bc133ef..3ddc0d8f7b 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -214,6 +214,7 @@
<param index="1" name="pos" type="Vector2" />
<param index="2" name="radius" type="float" />
<param index="3" name="color" type="Color" />
+ <param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a circle on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_circle].
</description>
@@ -280,6 +281,7 @@
<param index="1" name="points" type="PackedVector2Array" />
<param index="2" name="colors" type="PackedColorArray" />
<param index="3" name="width" type="float" default="-1.0" />
+ <param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a 2D multiline on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_multiline] and [method CanvasItem.draw_multiline_colors].
</description>
@@ -356,6 +358,7 @@
<param index="0" name="item" type="RID" />
<param index="1" name="rect" type="Rect2" />
<param index="2" name="color" type="Color" />
+ <param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws a rectangle on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_rect].
</description>
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index d0ad0e8b11..fd728dc393 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -3760,6 +3760,14 @@ EditorHelpBit::EditorHelpBit(const String &p_symbol) {
/// EditorHelpBitTooltip ///
+void EditorHelpBitTooltip::_safe_queue_free() {
+ if (_pushing_input > 0) {
+ _need_free = true;
+ } else {
+ queue_free();
+ }
+}
+
void EditorHelpBitTooltip::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_WM_MOUSE_ENTER:
@@ -3778,7 +3786,13 @@ void EditorHelpBitTooltip::_input_from_window(const Ref<InputEvent> &p_event) {
} else {
const Ref<InputEventMouse> mouse_event = p_event;
if (mouse_event.is_null()) {
+ // GH-91652. Prevents use-after-free since `ProgressDialog` calls `Main::iteration()`.
+ _pushing_input++;
get_parent_viewport()->push_input(p_event);
+ _pushing_input--;
+ if (_pushing_input <= 0 && _need_free) {
+ queue_free();
+ }
}
}
}
@@ -3839,7 +3853,7 @@ EditorHelpBitTooltip::EditorHelpBitTooltip(Control *p_target) {
timer = memnew(Timer);
timer->set_wait_time(0.2);
- timer->connect("timeout", callable_mp(static_cast<Node *>(this), &Node::queue_free));
+ timer->connect("timeout", callable_mp(this, &EditorHelpBitTooltip::_safe_queue_free));
add_child(timer);
ERR_FAIL_NULL(p_target);
diff --git a/editor/editor_help.h b/editor/editor_help.h
index ca3a05275f..76f9e71931 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -325,6 +325,10 @@ class EditorHelpBitTooltip : public PopupPanel {
GDCLASS(EditorHelpBitTooltip, PopupPanel);
Timer *timer = nullptr;
+ int _pushing_input = 0;
+ bool _need_free = false;
+
+ void _safe_queue_free();
protected:
void _notification(int p_what);
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 266901c938..a9c5586ba2 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -50,6 +50,7 @@
#include "scene/property_utils.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/style_box_flat.h"
+#include "scene/scene_string_names.h"
bool EditorInspector::_property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style) {
if (p_property_path.containsn(p_filter)) {
@@ -390,6 +391,17 @@ void EditorProperty::_notification(int p_what) {
delete_rect = Rect2();
}
} break;
+ case NOTIFICATION_ENTER_TREE: {
+ if (has_borders) {
+ get_parent()->connect(SceneStringName(theme_changed), callable_mp(this, &EditorProperty::_update_property_bg));
+ _update_property_bg();
+ }
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ if (has_borders) {
+ get_parent()->disconnect(SceneStringName(theme_changed), callable_mp(this, &EditorProperty::_update_property_bg));
+ }
+ }
}
}
@@ -810,6 +822,9 @@ void EditorProperty::set_label_reference(Control *p_control) {
void EditorProperty::set_bottom_editor(Control *p_control) {
bottom_editor = p_control;
+ if (has_borders) {
+ _update_property_bg();
+ }
}
Variant EditorProperty::_get_cache_value(const StringName &p_prop, bool &r_valid) const {
@@ -4087,6 +4102,9 @@ void EditorInspector::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
bool needs_update = false;
+ if (EditorThemeManager::is_generated_theme_outdated() && !sub_inspector) {
+ add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
+ }
if (use_settings_name_style && EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
EditorPropertyNameProcessor::Style style = EditorPropertyNameProcessor::get_settings_style();
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index b052693524..8fe690fddf 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -136,6 +136,8 @@ private:
void _update_pin_flags();
protected:
+ bool has_borders = false;
+
void _notification(int p_what);
static void _bind_methods();
virtual void _set_read_only(bool p_read_only);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 67bfeed8be..c73bdafb1a 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -3364,8 +3364,6 @@ void EditorPropertyResource::update_property() {
EditorNode::get_singleton()->hide_unused_editors();
opened_editor = false;
}
-
- _update_property_bg();
}
}
}
@@ -3422,12 +3420,6 @@ bool EditorPropertyResource::is_colored(ColorationMode p_mode) {
void EditorPropertyResource::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_THEME_CHANGED: {
- if (EditorThemeManager::is_generated_theme_outdated()) {
- _update_property_bg();
- }
- } break;
-
case NOTIFICATION_EXIT_TREE: {
const EditorInspector *ei = get_parent_inspector();
if (ei && !ei->is_main_editor_inspector()) {
@@ -3439,6 +3431,7 @@ void EditorPropertyResource::_notification(int p_what) {
EditorPropertyResource::EditorPropertyResource() {
use_sub_inspector = bool(EDITOR_GET("interface/inspector/open_resources_in_current_inspector"));
+ has_borders = true;
}
////////////// DEFAULT PLUGIN //////////////////////
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index c3142b4cd0..e338c5c8bd 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -391,8 +391,6 @@ void EditorPropertyArray::update_property() {
paginator->connect("page_changed", callable_mp(this, &EditorPropertyArray::_page_changed));
vbox->add_child(paginator);
- _update_property_bg();
-
for (int i = 0; i < page_length; i++) {
_create_new_property_slot();
}
@@ -454,7 +452,6 @@ void EditorPropertyArray::update_property() {
memdelete(container);
button_add_item = nullptr;
container = nullptr;
- _update_property_bg();
slots.clear();
}
}
@@ -628,10 +625,6 @@ Node *EditorPropertyArray::get_base_node() {
void EditorPropertyArray::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
- if (EditorThemeManager::is_generated_theme_outdated()) {
- _update_property_bg();
- }
- [[fallthrough]];
case NOTIFICATION_ENTER_TREE: {
change_type->clear();
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
@@ -851,6 +844,7 @@ EditorPropertyArray::EditorPropertyArray() {
subtype = Variant::NIL;
subtype_hint = PROPERTY_HINT_NONE;
subtype_hint_string = "";
+ has_borders = true;
}
///////////////////// DICTIONARY ///////////////////////////
@@ -1000,7 +994,6 @@ void EditorPropertyDictionary::update_property() {
paginator = memnew(EditorPaginator);
paginator->connect("page_changed", callable_mp(this, &EditorPropertyDictionary::_page_changed));
vbox->add_child(paginator);
- _update_property_bg();
for (int i = 0; i < page_length; i++) {
_create_new_property_slot(slots.size());
@@ -1075,7 +1068,6 @@ void EditorPropertyDictionary::update_property() {
memdelete(container);
button_add_item = nullptr;
container = nullptr;
- _update_property_bg();
add_panel = nullptr;
slots.clear();
}
@@ -1089,10 +1081,6 @@ void EditorPropertyDictionary::_object_id_selected(const StringName &p_property,
void EditorPropertyDictionary::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
- if (EditorThemeManager::is_generated_theme_outdated()) {
- _update_property_bg();
- }
- [[fallthrough]];
case NOTIFICATION_ENTER_TREE: {
change_type->clear();
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
@@ -1109,6 +1097,7 @@ void EditorPropertyDictionary::_notification(int p_what) {
if (button_add_item) {
button_add_item->set_icon(get_editor_theme_icon(SNAME("Add")));
+ add_panel->add_theme_style_override(SNAME("panel"), get_theme_stylebox(SNAME("DictionaryAddItem")));
}
} break;
}
@@ -1166,6 +1155,7 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
add_child(change_type);
change_type->connect("id_pressed", callable_mp(this, &EditorPropertyDictionary::_change_type_menu));
changing_type_index = -1;
+ has_borders = true;
}
///////////////////// LOCALIZABLE STRING ///////////////////////////
diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index 1d32965b4a..f52c89e736 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -49,6 +49,11 @@ Dictionary GDShaderSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
for (const Point2i &region : disabled_branch_regions) {
if (p_line >= region.x && p_line <= region.y) {
+ // When "color_regions[0].p_start_key.length() > 2",
+ // disabled_branch_region causes color_region to break.
+ // This should be seen as a temporary solution.
+ CodeHighlighter::_get_line_syntax_highlighting_impl(p_line);
+
Dictionary highlighter_info;
highlighter_info["color"] = disabled_branch_color;
diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html
index 874fe2695e..fc34164368 100644
--- a/misc/dist/html/full-size.html
+++ b/misc/dist/html/full-size.html
@@ -38,7 +38,7 @@ body {
}
#status {
- background-color: #38363A;
+ background-color: #242424;
display: flex;
flex-direction: column;
justify-content: center;
diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected
index d7bb67cfbc..6761512c15 100644
--- a/misc/extension_api_validation/4.2-stable.expected
+++ b/misc/extension_api_validation/4.2-stable.expected
@@ -344,3 +344,16 @@ GH-91143
Validate extension JSON: Error: Field 'classes/Input/methods/vibrate_handheld/arguments': size changed value in new API, from 1 to 2.
Added optional argument. Compatibility method registered.
+
+
+GH-84523
+--------
+Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_dashed_line/arguments': size changed value in new API, from 6 to 7.
+Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_multiline/arguments': size changed value in new API, from 3 to 4.
+Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_multiline_colors/arguments': size changed value in new API, from 3 to 4.
+Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_rect/arguments': size changed value in new API, from 4 to 5.
+Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_circle/arguments': size changed value in new API, from 4 to 5.
+Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_multiline/arguments': size changed value in new API, from 4 to 5.
+Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_rect/arguments': size changed value in new API, from 3 to 4.
+
+Optional arguments added. Compatibility methods registered.
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 88383554b6..c7862e23a9 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -2919,7 +2919,7 @@ String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) con
return "";
}
-void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *r_dependencies, bool p_add_types) {
+void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_path + "'.");
@@ -2933,13 +2933,8 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S
return;
}
- GDScriptAnalyzer analyzer(&parser);
- if (OK != analyzer.analyze()) {
- return;
- }
-
for (const String &E : parser.get_dependencies()) {
- r_dependencies->push_back(E);
+ p_dependencies->push_back(E);
}
}
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index f63b0da745..728459de44 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -638,7 +638,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
- virtual void get_dependencies(const String &p_path, List<String> *r_dependencies, bool p_add_types = false) override;
+ virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override;
};
class ResourceFormatSaverGDScript : public ResourceFormatSaver {
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index ac5564cf12..46b34e4977 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -562,11 +562,6 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
class_type.native_type = result.native_type;
p_class->set_datatype(class_type);
- // Add base class to the list of dependencies.
- if (result.kind == GDScriptParser::DataType::CLASS) {
- parser->add_dependency(result.script_path);
- }
-
// Apply annotations.
for (GDScriptParser::AnnotationNode *&E : p_class->annotations) {
resolve_annotation(E);
@@ -873,11 +868,6 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
}
p_type->set_datatype(result);
-
- if (result.kind == GDScriptParser::DataType::CLASS || result.kind == GDScriptParser::DataType::SCRIPT) {
- parser->add_dependency(result.script_path);
- }
-
return result;
}
@@ -4112,7 +4102,6 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
if (ScriptServer::is_global_class(name)) {
p_identifier->set_datatype(make_global_class_meta_type(name, p_identifier));
- parser->add_dependency(p_identifier->get_datatype().script_path);
return;
}
@@ -4155,7 +4144,6 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
}
result.is_constant = true;
p_identifier->set_datatype(result);
- parser->add_dependency(autoload.path);
return;
}
}
@@ -4275,6 +4263,7 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
push_error("Preloaded path must be a constant string.", p_preload->path);
} else {
p_preload->resolved_path = p_preload->path->reduced_value;
+ // TODO: Save this as script dependency.
if (p_preload->resolved_path.is_relative_path()) {
p_preload->resolved_path = parser->script_path.get_base_dir().path_join(p_preload->resolved_path);
}
@@ -4305,8 +4294,6 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
}
}
-
- parser->add_dependency(p_preload->resolved_path);
}
}
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 1e67e2d496..4c11fa7f8b 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -1432,8 +1432,6 @@ private:
void reset_extents(Node *p_node, GDScriptTokenizer::Token p_token);
void reset_extents(Node *p_node, Node *p_from);
- HashSet<String> dependencies;
-
template <typename T>
T *alloc_node() {
T *node = memnew(T);
@@ -1577,11 +1575,9 @@ public:
bool annotation_exists(const String &p_annotation_name) const;
const List<ParserError> &get_errors() const { return errors; }
- const HashSet<String> &get_dependencies() const {
- return dependencies;
- }
- void add_dependency(const String &p_dependency) {
- dependencies.insert(p_dependency);
+ const List<String> get_dependencies() const {
+ // TODO: Keep track of deps.
+ return List<String>();
}
#ifdef DEBUG_ENABLED
const List<GDScriptWarning> &get_warnings() const { return warnings; }
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index d42303ad25..0bf3927e14 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -154,11 +154,11 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito
String head_include;
if (p_preset->get("html/export_icon")) {
- head_include += "<link id='-gd-engine-icon' rel='icon' type='image/png' href='" + p_name + ".icon.png' />\n";
- head_include += "<link rel='apple-touch-icon' href='" + p_name + ".apple-touch-icon.png'/>\n";
+ head_include += "<link id=\"-gd-engine-icon\" rel=\"icon\" type=\"image/png\" href=\"" + p_name + ".icon.png\" />\n";
+ head_include += "<link rel=\"apple-touch-icon\" href=\"" + p_name + ".apple-touch-icon.png\"/>\n";
}
if (p_preset->get("progressive_web_app/enabled")) {
- head_include += "<link rel='manifest' href='" + p_name + ".manifest.json'>\n";
+ head_include += "<link rel=\"manifest\" href=\"" + p_name + ".manifest.json\">\n";
config["serviceWorker"] = p_name + ".service.worker.js";
}
diff --git a/scene/main/canvas_item.compat.inc b/scene/main/canvas_item.compat.inc
index 7136fded15..9bc3d01a69 100644
--- a/scene/main/canvas_item.compat.inc
+++ b/scene/main/canvas_item.compat.inc
@@ -30,12 +30,32 @@
#ifndef DISABLE_DEPRECATED
-void CanvasItem::_draw_circle_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color) {
+void CanvasItem::_draw_circle_bind_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color) {
draw_circle(p_pos, p_radius, p_color, true, -1.0, false);
}
+void CanvasItem::_draw_rect_bind_compat_84523(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) {
+ draw_rect(p_rect, p_color, p_filled, p_width, false);
+}
+
+void CanvasItem::_draw_dashed_line_bind_compat_84523(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) {
+ draw_dashed_line(p_from, p_to, p_color, p_width, p_dash, p_aligned, false);
+}
+
+void CanvasItem::_draw_multiline_bind_compat_84523(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) {
+ draw_multiline(p_points, p_color, p_width, false);
+}
+
+void CanvasItem::_draw_multiline_colors_bind_compat_84523(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) {
+ draw_multiline_colors(p_points, p_colors, p_width, false);
+}
+
void CanvasItem::_bind_compatibility_methods() {
- ClassDB::bind_compatibility_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::_draw_circle_compat_84472);
+ ClassDB::bind_compatibility_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::_draw_circle_bind_compat_84472);
+ ClassDB::bind_compatibility_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::_draw_rect_bind_compat_84523, DEFVAL(true), DEFVAL(-1.0));
+ ClassDB::bind_compatibility_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned"), &CanvasItem::_draw_dashed_line_bind_compat_84523, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true));
+ ClassDB::bind_compatibility_method(D_METHOD("draw_multiline", "points", "color", "width"), &CanvasItem::_draw_multiline_bind_compat_84523, DEFVAL(-1.0));
+ ClassDB::bind_compatibility_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::_draw_multiline_colors_bind_compat_84523, DEFVAL(-1.0));
}
#endif
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 821b670cb0..dca116086d 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -609,7 +609,7 @@ bool CanvasItem::is_y_sort_enabled() const {
return y_sort_enabled;
}
-void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) {
+void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
ERR_FAIL_COND(p_dash <= 0.0);
@@ -618,7 +618,7 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons
Vector2 step = p_dash * (p_to - p_from).normalized();
if (length < p_dash || step == Vector2()) {
- RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased);
return;
}
@@ -642,7 +642,7 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons
Vector<Color> colors = { p_color };
- RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, points, colors, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, points, colors, p_width, p_antialiased);
}
void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, bool p_antialiased) {
@@ -683,22 +683,22 @@ void CanvasItem::draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_sta
draw_polyline(points, p_color, p_width, p_antialiased);
}
-void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) {
+void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
Vector<Color> colors = { p_color };
- RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width, p_antialiased);
}
-void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) {
+void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
- RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width, p_antialiased);
}
-void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) {
+void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
@@ -709,9 +709,9 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
WARN_PRINT("The draw_rect() \"width\" argument has no effect when \"filled\" is \"true\".");
}
- RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect, p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect, p_color, p_antialiased);
} else if (p_width >= rect.size.width || p_width >= rect.size.height) {
- RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect.grow(0.5f * p_width), p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect.grow(0.5f * p_width), p_color, p_antialiased);
} else {
Vector<Vector2> points;
points.resize(5);
@@ -723,7 +723,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
Vector<Color> colors = { p_color };
- RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width, p_antialiased);
}
}
@@ -736,9 +736,9 @@ void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &
WARN_PRINT("The draw_circle() \"width\" argument has no effect when \"filled\" is \"true\".");
}
- RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color);
+ RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color, p_antialiased);
} else if (p_width >= 2.0 * p_radius) {
- RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius + 0.5 * p_width, p_color);
+ RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius + 0.5 * p_width, p_color, p_antialiased);
} else {
// Tessellation count is hardcoded. Keep in sync with the same variable in `RendererCanvasCull::canvas_item_add_circle()`.
const int circle_segments = 64;
@@ -1186,13 +1186,13 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(-1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned"), &CanvasItem::draw_dashed_line, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned", "antialiased"), &CanvasItem::draw_dashed_line, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_arc, DEFVAL(-1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width"), &CanvasItem::draw_multiline, DEFVAL(-1.0));
- ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::draw_multiline_colors, DEFVAL(-1.0));
- ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(-1.0));
+ ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width", "antialiased"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color", "filled", "width", "antialiased"), &CanvasItem::draw_circle, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index ae7b195ead..028c2cb2cf 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -168,7 +168,11 @@ protected:
static void _bind_methods();
#ifndef DISABLE_DEPRECATED
- void _draw_circle_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color);
+ void _draw_circle_bind_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color);
+ void _draw_rect_bind_compat_84523(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width);
+ void _draw_dashed_line_bind_compat_84523(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned);
+ void _draw_multiline_bind_compat_84523(const Vector<Point2> &p_points, const Color &p_color, real_t p_width);
+ void _draw_multiline_colors_bind_compat_84523(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width);
static void _bind_compatibility_methods();
#endif
@@ -271,14 +275,14 @@ public:
/* DRAWING API */
- void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, real_t p_dash = 2.0, bool p_aligned = true);
+ void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, real_t p_dash = 2.0, bool p_aligned = true, bool p_antialiased = false);
void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = -1.0, bool p_antialiased = false);
void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
- void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = -1.0);
- void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = -1.0);
- void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = -1.0);
+ void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
+ void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = -1.0, bool p_antialiased = false);
+ void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = -1.0, bool p_antialiased = false);
void draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color, bool p_filled = true, real_t p_width = -1.0, bool p_antialiased = false);
void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1));
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
diff --git a/scene/resources/canvas_item_material.cpp b/scene/resources/canvas_item_material.cpp
index 31c8e68ea5..76e99aca92 100644
--- a/scene/resources/canvas_item_material.cpp
+++ b/scene/resources/canvas_item_material.cpp
@@ -33,13 +33,11 @@
#include "core/version.h"
Mutex CanvasItemMaterial::material_mutex;
-SelfList<CanvasItemMaterial>::List *CanvasItemMaterial::dirty_materials = nullptr;
+SelfList<CanvasItemMaterial>::List CanvasItemMaterial::dirty_materials;
HashMap<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData, CanvasItemMaterial::MaterialKey> CanvasItemMaterial::shader_map;
CanvasItemMaterial::ShaderNames *CanvasItemMaterial::shader_names = nullptr;
void CanvasItemMaterial::init_shaders() {
- dirty_materials = memnew(SelfList<CanvasItemMaterial>::List);
-
shader_names = memnew(ShaderNames);
shader_names->particles_anim_h_frames = "particles_anim_h_frames";
@@ -48,14 +46,13 @@ void CanvasItemMaterial::init_shaders() {
}
void CanvasItemMaterial::finish_shaders() {
- memdelete(dirty_materials);
+ dirty_materials.clear();
+
memdelete(shader_names);
- dirty_materials = nullptr;
+ shader_names = nullptr;
}
void CanvasItemMaterial::_update_shader() {
- dirty_materials->remove(&element);
-
MaterialKey mk = _compute_key();
if (mk.key == current_key.key) {
return; //no update required in the end
@@ -153,8 +150,9 @@ void CanvasItemMaterial::_update_shader() {
void CanvasItemMaterial::flush_changes() {
MutexLock lock(material_mutex);
- while (dirty_materials->first()) {
- dirty_materials->first()->self()->_update_shader();
+ while (dirty_materials.first()) {
+ dirty_materials.first()->self()->_update_shader();
+ dirty_materials.first()->remove_from_list();
}
}
@@ -162,16 +160,10 @@ void CanvasItemMaterial::_queue_shader_change() {
MutexLock lock(material_mutex);
if (_is_initialized() && !element.in_list()) {
- dirty_materials->add(&element);
+ dirty_materials.add(&element);
}
}
-bool CanvasItemMaterial::_is_shader_dirty() const {
- MutexLock lock(material_mutex);
-
- return element.in_list();
-}
-
void CanvasItemMaterial::set_blend_mode(BlendMode p_blend_mode) {
blend_mode = p_blend_mode;
_queue_shader_change();
@@ -288,7 +280,7 @@ CanvasItemMaterial::CanvasItemMaterial() :
current_key.invalid_key = 1;
- _mark_initialized(callable_mp(this, &CanvasItemMaterial::_queue_shader_change));
+ _mark_initialized(callable_mp(this, &CanvasItemMaterial::_queue_shader_change), callable_mp(this, &CanvasItemMaterial::_update_shader));
}
CanvasItemMaterial::~CanvasItemMaterial() {
diff --git a/scene/resources/canvas_item_material.h b/scene/resources/canvas_item_material.h
index 7dddd74a31..ef498c2ff6 100644
--- a/scene/resources/canvas_item_material.h
+++ b/scene/resources/canvas_item_material.h
@@ -98,12 +98,11 @@ private:
}
static Mutex material_mutex;
- static SelfList<CanvasItemMaterial>::List *dirty_materials;
+ static SelfList<CanvasItemMaterial>::List dirty_materials;
SelfList<CanvasItemMaterial> element;
void _update_shader();
_FORCE_INLINE_ void _queue_shader_change();
- _FORCE_INLINE_ bool _is_shader_dirty() const;
BlendMode blend_mode = BLEND_MODE_MIX;
LightMode light_mode = LIGHT_MODE_NORMAL;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 15b40e776c..3784aa3da0 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -82,24 +82,25 @@ void Material::_validate_property(PropertyInfo &p_property) const {
}
}
-void Material::_mark_initialized(const Callable &p_queue_shader_change_callable) {
+void Material::_mark_ready() {
+ init_state = INIT_STATE_INITIALIZING;
+}
+
+void Material::_mark_initialized(const Callable &p_add_to_dirty_list, const Callable &p_update_shader) {
// If this is happening as part of resource loading, it is not safe to queue the update
- // as an addition to the dirty list, unless the load is happening on the main thread.
- if (ResourceLoader::is_within_load() && Thread::get_caller_id() != Thread::get_main_id()) {
+ // as an addition to the dirty list. It would be if the load is happening on the main thread,
+ // but even so we'd rather perform the update directly instead of using the dirty list.
+ if (ResourceLoader::is_within_load()) {
DEV_ASSERT(init_state != INIT_STATE_READY);
if (init_state == INIT_STATE_UNINITIALIZED) { // Prevent queueing twice.
- // Let's mark this material as being initialized.
init_state = INIT_STATE_INITIALIZING;
- // Knowing that the ResourceLoader will eventually feed deferred calls into the main message queue, let's do these:
- // 1. Queue setting the init state to INIT_STATE_READY finally.
- callable_mp(this, &Material::_mark_initialized).bind(p_queue_shader_change_callable).call_deferred();
- // 2. Queue an individual update of this material.
- p_queue_shader_change_callable.call_deferred();
+ callable_mp(this, &Material::_mark_ready).call_deferred();
+ p_update_shader.call_deferred();
}
} else {
// Straightforward conditions.
init_state = INIT_STATE_READY;
- p_queue_shader_change_callable.callv(Array());
+ p_add_to_dirty_list.call();
}
}
@@ -603,8 +604,6 @@ void BaseMaterial3D::finish_shaders() {
}
void BaseMaterial3D::_update_shader() {
- dirty_materials.remove(&element);
-
MaterialKey mk = _compute_key();
if (mk == current_key) {
return; //no update required in the end
@@ -1855,6 +1854,7 @@ void BaseMaterial3D::flush_changes() {
while (dirty_materials.first()) {
dirty_materials.first()->self()->_update_shader();
+ dirty_materials.first()->remove_from_list();
}
}
@@ -1866,12 +1866,6 @@ void BaseMaterial3D::_queue_shader_change() {
}
}
-bool BaseMaterial3D::_is_shader_dirty() const {
- MutexLock lock(material_mutex);
-
- return element.in_list();
-}
-
void BaseMaterial3D::set_albedo(const Color &p_albedo) {
albedo = p_albedo;
@@ -2824,7 +2818,7 @@ BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const {
RID BaseMaterial3D::get_shader_rid() const {
MutexLock lock(material_mutex);
- if (element.in_list()) { // _is_shader_dirty() would create anoder mutex lock
+ if (element.in_list()) {
((BaseMaterial3D *)this)->_update_shader();
}
ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
@@ -3412,7 +3406,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
current_key.invalid_key = 1;
- _mark_initialized(callable_mp(this, &BaseMaterial3D::_queue_shader_change));
+ _mark_initialized(callable_mp(this, &BaseMaterial3D::_queue_shader_change), callable_mp(this, &BaseMaterial3D::_update_shader));
}
BaseMaterial3D::~BaseMaterial3D() {
diff --git a/scene/resources/material.h b/scene/resources/material.h
index ecf79c581b..50a774e961 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -62,7 +62,8 @@ protected:
void _validate_property(PropertyInfo &p_property) const;
- void _mark_initialized(const Callable &p_queue_shader_change_callable);
+ void _mark_ready();
+ void _mark_initialized(const Callable &p_add_to_dirty_list, const Callable &p_update_shader);
bool _is_initialized() { return init_state == INIT_STATE_READY; }
GDVIRTUAL0RC(RID, _get_shader_rid)
@@ -466,7 +467,6 @@ private:
void _update_shader();
_FORCE_INLINE_ void _queue_shader_change();
- _FORCE_INLINE_ bool _is_shader_dirty() const;
bool orm;
diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp
index 0b65b33240..81476eaa0f 100644
--- a/scene/resources/particle_process_material.cpp
+++ b/scene/resources/particle_process_material.cpp
@@ -33,14 +33,12 @@
#include "core/version.h"
Mutex ParticleProcessMaterial::material_mutex;
-SelfList<ParticleProcessMaterial>::List *ParticleProcessMaterial::dirty_materials = nullptr;
+SelfList<ParticleProcessMaterial>::List ParticleProcessMaterial::dirty_materials;
HashMap<ParticleProcessMaterial::MaterialKey, ParticleProcessMaterial::ShaderData, ParticleProcessMaterial::MaterialKey> ParticleProcessMaterial::shader_map;
RBSet<String> ParticleProcessMaterial::min_max_properties;
ParticleProcessMaterial::ShaderNames *ParticleProcessMaterial::shader_names = nullptr;
void ParticleProcessMaterial::init_shaders() {
- dirty_materials = memnew(SelfList<ParticleProcessMaterial>::List);
-
shader_names = memnew(ShaderNames);
shader_names->direction = "direction";
@@ -140,15 +138,13 @@ void ParticleProcessMaterial::init_shaders() {
}
void ParticleProcessMaterial::finish_shaders() {
- memdelete(dirty_materials);
- dirty_materials = nullptr;
+ dirty_materials.clear();
memdelete(shader_names);
+ shader_names = nullptr;
}
void ParticleProcessMaterial::_update_shader() {
- dirty_materials->remove(&element);
-
MaterialKey mk = _compute_key();
if (mk == current_key) {
return; //no update required in the end
@@ -1170,8 +1166,9 @@ void ParticleProcessMaterial::_update_shader() {
void ParticleProcessMaterial::flush_changes() {
MutexLock lock(material_mutex);
- while (dirty_materials->first()) {
- dirty_materials->first()->self()->_update_shader();
+ while (dirty_materials.first()) {
+ dirty_materials.first()->self()->_update_shader();
+ dirty_materials.first()->remove_from_list();
}
}
@@ -1179,16 +1176,10 @@ void ParticleProcessMaterial::_queue_shader_change() {
MutexLock lock(material_mutex);
if (_is_initialized() && !element.in_list()) {
- dirty_materials->add(&element);
+ dirty_materials.add(&element);
}
}
-bool ParticleProcessMaterial::_is_shader_dirty() const {
- MutexLock lock(material_mutex);
-
- return element.in_list();
-}
-
bool ParticleProcessMaterial::has_min_max_property(const String &p_name) {
return min_max_properties.has(p_name);
}
@@ -2330,7 +2321,7 @@ ParticleProcessMaterial::ParticleProcessMaterial() :
current_key.invalid_key = 1;
- _mark_initialized(callable_mp(this, &ParticleProcessMaterial::_queue_shader_change));
+ _mark_initialized(callable_mp(this, &ParticleProcessMaterial::_queue_shader_change), callable_mp(this, &ParticleProcessMaterial::_update_shader));
}
ParticleProcessMaterial::~ParticleProcessMaterial() {
diff --git a/scene/resources/particle_process_material.h b/scene/resources/particle_process_material.h
index 94b2009654..25046b51cd 100644
--- a/scene/resources/particle_process_material.h
+++ b/scene/resources/particle_process_material.h
@@ -186,7 +186,7 @@ private:
}
static Mutex material_mutex;
- static SelfList<ParticleProcessMaterial>::List *dirty_materials;
+ static SelfList<ParticleProcessMaterial>::List dirty_materials;
struct ShaderNames {
StringName direction;
@@ -293,7 +293,6 @@ private:
void _update_shader();
_FORCE_INLINE_ void _queue_shader_change();
- _FORCE_INLINE_ bool _is_shader_dirty() const;
Vector3 direction;
float spread = 0.0f;
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index e48c72cec7..42de831e7a 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -38,6 +38,12 @@
#include "rendering_server_globals.h"
#include "servers/rendering/storage/texture_storage.h"
+// Use the same antialiasing feather size as StyleBoxFlat's default
+// (but doubled, as it's specified for both sides here).
+// This value is empirically determined to provide good antialiasing quality
+// while not making lines appear too soft.
+const static float FEATHER_SIZE = 1.25f;
+
void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) {
RENDER_TIMESTAMP("Cull CanvasItem Tree");
@@ -638,11 +644,8 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
}
if (p_antialiased) {
- // Use the same antialiasing feather size as StyleBoxFlat's default
- // (but doubled, as it's specified for both sides here).
- // This value is empirically determined to provide good antialiasing quality
- // while not making lines appear too soft.
- float border_size = 1.25f;
+ float border_size = FEATHER_SIZE;
+
if (0.0f <= p_width && p_width < 1.0f) {
border_size *= p_width;
}
@@ -651,7 +654,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
Vector2 border = dir * border_size;
Vector2 border2 = dir2 * border_size;
- Color transparent = Color(p_color.r, p_color.g, p_color.b, 0.0);
+ Color transparent = Color(p_color, 0.0);
{
Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
@@ -903,11 +906,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color *colors_ptr = colors.ptrw();
if (p_antialiased) {
- // Use the same antialiasing feather size as StyleBoxFlat's default
- // (but doubled, as it's specified for both sides here).
- // This value is empirically determined to provide good antialiasing quality
- // while not making lines appear too soft.
- float border_size = 1.25f;
+ float border_size = FEATHER_SIZE;
if (p_width < 1.0f) {
border_size *= p_width;
}
@@ -1094,12 +1093,15 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
pline->polygon.create(indices, points, colors);
}
-void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
+void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
ERR_FAIL_COND(p_points.is_empty() || p_points.size() % 2 != 0);
ERR_FAIL_COND(p_colors.size() != 1 && p_colors.size() * 2 != p_points.size());
// TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out.
if (p_width < 0) {
+ if (p_antialiased) {
+ WARN_PRINT("Antialiasing is not supported for thin multilines drawn using line strips (`p_width < 0`).");
+ }
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
@@ -1127,7 +1129,7 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
Vector2 from = p_points[i * 2 + 0];
Vector2 to = p_points[i * 2 + 1];
- canvas_item_add_line(p_item, from, to, color, p_width);
+ canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased);
}
} else { //} else if (p_colors.size() << 1 == p_points.size()) {
for (int i = 0; i < p_colors.size(); i++) {
@@ -1135,13 +1137,13 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
Vector2 from = p_points[i * 2 + 0];
Vector2 to = p_points[i * 2 + 1];
- canvas_item_add_line(p_item, from, to, color, p_width);
+ canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased);
}
}
}
}
-void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) {
+void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
@@ -1149,45 +1151,251 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
ERR_FAIL_NULL(rect);
rect->modulate = p_color;
rect->rect = p_rect;
+
+ // Add feathers.
+ if (p_antialiased) {
+ float border_size = FEATHER_SIZE;
+
+ const real_t size = MIN(p_rect.size.width, p_rect.size.height);
+ if (0.0f <= size && size < 1.0f) {
+ border_size *= size;
+ }
+
+ const Vector2 vec_down = Vector2(0.0f, p_rect.size.height);
+ const Vector2 vec_right = Vector2(p_rect.size.width, 0.0f);
+
+ const Vector2 begin_left = p_rect.position;
+ const Vector2 begin_right = p_rect.position + vec_down;
+ const Vector2 end_left = p_rect.position + vec_right;
+ const Vector2 end_right = p_rect.position + p_rect.size;
+
+ const Vector2 dir = Vector2(0.0f, -1.0f);
+ const Vector2 dir2 = Vector2(-1.0f, 0.0f);
+ const Vector2 border = dir * border_size;
+ const Vector2 border2 = dir2 * border_size;
+
+ Color transparent = Color(p_color, 0.0);
+
+ {
+ Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(left_border);
+
+ left_border->points[0] = begin_left;
+ left_border->points[1] = begin_left + border;
+ left_border->points[2] = end_left + border;
+ left_border->points[3] = end_left;
+
+ left_border->colors[0] = p_color;
+ left_border->colors[1] = transparent;
+ left_border->colors[2] = transparent;
+ left_border->colors[3] = p_color;
+
+ left_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(right_border);
+
+ right_border->points[0] = begin_right;
+ right_border->points[1] = begin_right - border;
+ right_border->points[2] = end_right - border;
+ right_border->points[3] = end_right;
+
+ right_border->colors[0] = p_color;
+ right_border->colors[1] = transparent;
+ right_border->colors[2] = transparent;
+ right_border->colors[3] = p_color;
+
+ right_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_border);
+
+ top_border->points[0] = begin_left;
+ top_border->points[1] = begin_left + border2;
+ top_border->points[2] = begin_right + border2;
+ top_border->points[3] = begin_right;
+
+ top_border->colors[0] = p_color;
+ top_border->colors[1] = transparent;
+ top_border->colors[2] = transparent;
+ top_border->colors[3] = p_color;
+
+ top_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_border);
+
+ bottom_border->points[0] = end_left;
+ bottom_border->points[1] = end_left - border2;
+ bottom_border->points[2] = end_right - border2;
+ bottom_border->points[3] = end_right;
+
+ bottom_border->colors[0] = p_color;
+ bottom_border->colors[1] = transparent;
+ bottom_border->colors[2] = transparent;
+ bottom_border->colors[3] = p_color;
+
+ bottom_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_left_corner);
+
+ top_left_corner->points[0] = begin_left;
+ top_left_corner->points[1] = begin_left + border2;
+ top_left_corner->points[2] = begin_left + border + border2;
+ top_left_corner->points[3] = begin_left + border;
+
+ top_left_corner->colors[0] = p_color;
+ top_left_corner->colors[1] = transparent;
+ top_left_corner->colors[2] = transparent;
+ top_left_corner->colors[3] = transparent;
+
+ top_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_right_corner);
+
+ top_right_corner->points[0] = begin_right;
+ top_right_corner->points[1] = begin_right + border2;
+ top_right_corner->points[2] = begin_right - border + border2;
+ top_right_corner->points[3] = begin_right - border;
+
+ top_right_corner->colors[0] = p_color;
+ top_right_corner->colors[1] = transparent;
+ top_right_corner->colors[2] = transparent;
+ top_right_corner->colors[3] = transparent;
+
+ top_right_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_left_corner);
+
+ bottom_left_corner->points[0] = end_left;
+ bottom_left_corner->points[1] = end_left - border2;
+ bottom_left_corner->points[2] = end_left + border - border2;
+ bottom_left_corner->points[3] = end_left + border;
+
+ bottom_left_corner->colors[0] = p_color;
+ bottom_left_corner->colors[1] = transparent;
+ bottom_left_corner->colors[2] = transparent;
+ bottom_left_corner->colors[3] = transparent;
+
+ bottom_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_right_corner);
+
+ bottom_right_corner->points[0] = end_right;
+ bottom_right_corner->points[1] = end_right - border2;
+ bottom_right_corner->points[2] = end_right - border - border2;
+ bottom_right_corner->points[3] = end_right - border;
+
+ bottom_right_corner->colors[0] = p_color;
+ bottom_right_corner->colors[1] = transparent;
+ bottom_right_corner->colors[2] = transparent;
+ bottom_right_corner->colors[3] = transparent;
+
+ bottom_right_corner->point_count = 4;
+ }
+ }
}
-void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) {
+void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
- Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>();
- ERR_FAIL_NULL(circle);
+ static const int circle_segments = 64;
- circle->primitive = RS::PRIMITIVE_TRIANGLES;
+ {
+ Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_NULL(circle);
- Vector<int> indices;
- Vector<Vector2> points;
+ circle->primitive = RS::PRIMITIVE_TRIANGLES;
- static const int circle_points = 64;
+ Vector<int> indices;
+ Vector<Vector2> points;
- points.resize(circle_points);
- Vector2 *points_ptr = points.ptrw();
- const real_t circle_point_step = Math_TAU / circle_points;
+ points.resize(circle_segments + 2);
+ Vector2 *points_ptr = points.ptrw();
- for (int i = 0; i < circle_points; i++) {
- float angle = i * circle_point_step;
- points_ptr[i].x = Math::cos(angle) * p_radius;
- points_ptr[i].y = Math::sin(angle) * p_radius;
- points_ptr[i] += p_pos;
- }
+ // Store circle center in the last point.
+ points_ptr[circle_segments + 1] = p_pos;
- indices.resize((circle_points - 2) * 3);
- int *indices_ptr = indices.ptrw();
+ const real_t circle_point_step = Math_TAU / circle_segments;
+
+ for (int i = 0; i < circle_segments + 1; i++) {
+ float angle = i * circle_point_step;
+ points_ptr[i].x = Math::cos(angle) * p_radius;
+ points_ptr[i].y = Math::sin(angle) * p_radius;
+ points_ptr[i] += p_pos;
+ }
- for (int i = 0; i < circle_points - 2; i++) {
- indices_ptr[i * 3 + 0] = 0;
- indices_ptr[i * 3 + 1] = i + 1;
- indices_ptr[i * 3 + 2] = i + 2;
+ indices.resize(circle_segments * 3);
+ int *indices_ptr = indices.ptrw();
+
+ for (int i = 0; i < circle_segments; i++) {
+ indices_ptr[i * 3 + 0] = circle_segments + 1;
+ indices_ptr[i * 3 + 1] = i;
+ indices_ptr[i * 3 + 2] = i + 1;
+ }
+
+ Vector<Color> color;
+ color.push_back(p_color);
+ circle->polygon.create(indices, points, color);
}
- Vector<Color> color;
- color.push_back(p_color);
- circle->polygon.create(indices, points, color);
+ if (p_antialiased) {
+ float border_size = FEATHER_SIZE;
+
+ const float diameter = p_radius * 2.0f;
+ if (0.0f <= diameter && diameter < 1.0f) {
+ border_size *= p_radius;
+ }
+
+ Item::CommandPolygon *feather = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_NULL(feather);
+ feather->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+
+ Color transparent = Color(p_color, 0.0);
+
+ Vector<int> indices;
+ Vector<Color> colors;
+ Vector<Vector2> points;
+
+ points.resize(2 * circle_segments + 2);
+ colors.resize(2 * circle_segments + 2);
+
+ const real_t circle_point_step = Math_TAU / circle_segments;
+
+ Vector2 *points_ptr = points.ptrw();
+ Color *colors_ptr = colors.ptrw();
+
+ for (int i = 0; i < circle_segments + 1; i++) {
+ const float angle = i * circle_point_step;
+ const float c = Math::cos(angle);
+ const float s = Math::sin(angle);
+
+ points_ptr[i * 2].x = c * p_radius;
+ points_ptr[i * 2].y = s * p_radius;
+ points_ptr[i * 2] += p_pos;
+
+ points_ptr[i * 2 + 1].x = c * (p_radius + border_size);
+ points_ptr[i * 2 + 1].y = s * (p_radius + border_size);
+ points_ptr[i * 2 + 1] += p_pos;
+
+ colors_ptr[i * 2] = p_color;
+ colors_ptr[i * 2 + 1] = transparent;
+ }
+
+ feather->polygon.create(indices, points, colors);
+ }
}
void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) {
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 961506ca28..9f8cbea2e9 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -233,9 +233,9 @@ public:
void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false);
void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
- void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0);
- void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
- void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
+ void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
+ void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased);
+ void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0);
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index d0b6bc492d..164ec3cc09 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -885,9 +885,9 @@ public:
FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
- FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
- FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
- FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
+ FUNC5(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
+ FUNC4(canvas_item_add_rect, RID, const Rect2 &, const Color &, bool)
+ FUNC5(canvas_item_add_circle, RID, const Point2 &, float, const Color &, bool)
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float)
diff --git a/servers/rendering_server.compat.inc b/servers/rendering_server.compat.inc
index 0cef3c906c..99f2de9a9a 100644
--- a/servers/rendering_server.compat.inc
+++ b/servers/rendering_server.compat.inc
@@ -34,8 +34,23 @@ void RenderingServer::_environment_set_fog_bind_compat_84792(RID p_env, bool p_e
environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL);
}
+void RenderingServer::_canvas_item_add_multiline_bind_compat_84523(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
+ canvas_item_add_multiline(p_item, p_points, p_colors, p_width, false);
+}
+
+void RenderingServer::_canvas_item_add_rect_bind_compat_84523(RID p_item, const Rect2 &p_rect, const Color &p_color) {
+ canvas_item_add_rect(p_item, p_rect, p_color, false);
+}
+
+void RenderingServer::_canvas_item_add_circle_bind_compat_84523(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) {
+ canvas_item_add_circle(p_item, p_pos, p_radius, p_color, false);
+}
+
void RenderingServer::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::_environment_set_fog_bind_compat_84792);
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::_canvas_item_add_multiline_bind_compat_84523, DEFVAL(-1.0));
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::_canvas_item_add_rect_bind_compat_84523);
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::_canvas_item_add_circle_bind_compat_84523);
}
#endif
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index ab82e42f43..5cfd8d3cd2 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -3229,9 +3229,9 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(-1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::canvas_item_add_multiline, DEFVAL(-1.0));
- ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
- ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_multiline, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color", "antialiased"), &RenderingServer::canvas_item_add_rect, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color", "antialiased"), &RenderingServer::canvas_item_add_circle, DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range", "scale"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 5bc028dfdd..e15dba4353 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -99,6 +99,10 @@ protected:
#ifndef DISABLE_DEPRECATED
void _environment_set_fog_bind_compat_84792(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect);
+ void _canvas_item_add_multiline_bind_compat_84523(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0);
+ void _canvas_item_add_rect_bind_compat_84523(RID p_item, const Rect2 &p_rect, const Color &p_color);
+ void _canvas_item_add_circle_bind_compat_84523(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
+
static void _bind_compatibility_methods();
#endif
@@ -1465,9 +1469,9 @@ public:
virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0;
- virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0) = 0;
- virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;
- virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
+ virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased = false) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0;
virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0) = 0;
diff --git a/tests/scene/test_curve_2d.h b/tests/scene/test_curve_2d.h
index 099f6fefa9..1248632630 100644
--- a/tests/scene/test_curve_2d.h
+++ b/tests/scene/test_curve_2d.h
@@ -147,13 +147,19 @@ TEST_CASE("[Curve2D] Sampling") {
CHECK(curve->samplef(1) == Vector2(0, 50));
}
- SUBCASE("sample_baked") {
+ SUBCASE("sample_baked, cubic = false") {
CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 0))) == Vector2(0, 0));
CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 25))) == Vector2(0, 25));
CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 50))) == Vector2(0, 50));
}
- SUBCASE("sample_baked_with_rotation") {
+ SUBCASE("sample_baked, cubic = true") {
+ CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 0)), true) == Vector2(0, 0));
+ CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 25)), true) == Vector2(0, 25));
+ CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 50)), true) == Vector2(0, 50));
+ }
+
+ SUBCASE("sample_baked_with_rotation, cubic = false") {
const real_t pi = 3.14159;
const real_t half_pi = pi * 0.5;
Ref<Curve2D> rot_curve = memnew(Curve2D);
@@ -188,6 +194,41 @@ TEST_CASE("[Curve2D] Sampling") {
CHECK(Math::is_equal_approx(t.get_rotation(), -half_pi));
}
+ SUBCASE("sample_baked_with_rotation, cubic = true") {
+ const real_t pi = 3.14159;
+ const real_t half_pi = pi * 0.5;
+ Ref<Curve2D> rot_curve = memnew(Curve2D);
+ Transform2D t;
+
+ rot_curve->clear_points();
+ rot_curve->add_point(Vector2());
+ rot_curve->add_point(Vector2(50, 0));
+ t = rot_curve->sample_baked_with_rotation(25, true);
+ CHECK(t.get_origin() == Vector2(25, 0));
+ CHECK(Math::is_equal_approx(t.get_rotation(), 0));
+
+ rot_curve->clear_points();
+ rot_curve->add_point(Vector2());
+ rot_curve->add_point(Vector2(0, 50));
+ t = rot_curve->sample_baked_with_rotation(25, true);
+ CHECK(t.get_origin() == Vector2(0, 25));
+ CHECK(Math::is_equal_approx(t.get_rotation(), half_pi));
+
+ rot_curve->clear_points();
+ rot_curve->add_point(Vector2());
+ rot_curve->add_point(Vector2(-50, 0));
+ t = rot_curve->sample_baked_with_rotation(25, true);
+ CHECK(t.get_origin() == Vector2(-25, 0));
+ CHECK(Math::is_equal_approx(t.get_rotation(), pi));
+
+ rot_curve->clear_points();
+ rot_curve->add_point(Vector2());
+ rot_curve->add_point(Vector2(0, -50));
+ t = rot_curve->sample_baked_with_rotation(25, true);
+ CHECK(t.get_origin() == Vector2(0, -25));
+ CHECK(Math::is_equal_approx(t.get_rotation(), -half_pi));
+ }
+
SUBCASE("get_closest_point") {
CHECK(curve->get_closest_point(Vector2(0, 0)) == Vector2(0, 0));
CHECK(curve->get_closest_point(Vector2(0, 25)) == Vector2(0, 25));
diff --git a/tests/scene/test_curve_3d.h b/tests/scene/test_curve_3d.h
index d73bb1ad35..2e60a9c6e6 100644
--- a/tests/scene/test_curve_3d.h
+++ b/tests/scene/test_curve_3d.h
@@ -177,12 +177,30 @@ TEST_CASE("[Curve3D] Sampling") {
CHECK(curve->sample_baked(curve->get_closest_offset(Vector3(0, 50, 0)), true) == Vector3(0, 50, 0));
}
- SUBCASE("sample_baked_with_rotation") {
+ SUBCASE("sample_baked_with_rotation, cubic = false, p_apply_tilt = false") {
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
}
+ SUBCASE("sample_baked_with_rotation, cubic = false, p_apply_tilt = true") {
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0)), false, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0)), false, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0)), false, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
+ }
+
+ SUBCASE("sample_baked_with_rotation, cubic = true, p_apply_tilt = false") {
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0)), true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0)), true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0)), true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
+ }
+
+ SUBCASE("sample_baked_with_rotation, cubic = true, p_apply_tilt = true") {
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0)), true, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0)), true, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0)), true, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
+ }
+
SUBCASE("sample_baked_tilt") {
CHECK(curve->sample_baked_tilt(curve->get_closest_offset(Vector3(0, 0, 0))) == 0);
CHECK(curve->sample_baked_tilt(curve->get_closest_offset(Vector3(0, 25, 0))) == 0);
diff --git a/version.py b/version.py
index e915a6e530..d5ea5cfd91 100644
--- a/version.py
+++ b/version.py
@@ -3,7 +3,7 @@ name = "Godot Engine"
major = 4
minor = 3
patch = 0
-status = "dev"
+status = "beta"
module_config = ""
website = "https://godotengine.org"
docs = "latest"