summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/register_core_types.cpp2
-rw-r--r--doc/classes/Directory.xml10
-rw-r--r--drivers/unix/dir_access_unix.cpp16
-rw-r--r--drivers/unix/dir_access_unix.h1
-rw-r--r--editor/editor_spin_slider.cpp2
-rw-r--r--editor/plugins/theme_editor_plugin.cpp37
-rw-r--r--editor/plugins/theme_editor_plugin.h7
-rw-r--r--modules/text_server_adv/text_server_adv.cpp200
-rw-r--r--modules/text_server_adv/text_server_adv.h1
-rw-r--r--modules/text_server_fb/text_server_fb.cpp33
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.cpp11
-rw-r--r--scene/resources/material.cpp6
-rw-r--r--servers/rendering/shader_language.cpp112
-rw-r--r--servers/rendering/shader_language.h10
14 files changed, 276 insertions, 172 deletions
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index e33c21cc00..5479041b29 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -199,7 +199,7 @@ void register_core_types() {
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
GDREGISTER_VIRTUAL_CLASS(MultiplayerPeer);
- GDREGISTER_VIRTUAL_CLASS(MultiplayerPeerExtension);
+ GDREGISTER_CLASS(MultiplayerPeerExtension);
GDREGISTER_VIRTUAL_CLASS(MultiplayerReplicator);
GDREGISTER_CLASS(MultiplayerAPI);
GDREGISTER_CLASS(MainLoop);
diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml
index dbf5e31da4..3f0a5610b1 100644
--- a/doc/classes/Directory.xml
+++ b/doc/classes/Directory.xml
@@ -119,13 +119,19 @@
<return type="String" />
<argument index="0" name="idx" type="int" />
<description>
- On Windows, returns the name of the drive (partition) passed as an argument (e.g. [code]C:[/code]). On other platforms, or if the requested drive does not exist, the method returns an empty String.
+ On Windows, returns the name of the drive (partition) passed as an argument (e.g. [code]C:[/code]).
+ On macOS, returns the path to the mounted volume passed as an argument.
+ On Linux, returns the path to the mounted volume or GTK 3 bookmark passed as an argument.
+ On other platforms, or if the requested drive does not exist, the method returns an empty String.
</description>
</method>
<method name="get_drive_count">
<return type="int" />
<description>
- On Windows, returns the number of drives (partitions) mounted on the current filesystem. On other platforms, the method returns 0.
+ On Windows, returns the number of drives (partitions) mounted on the current filesystem.
+ On macOS, returns the number of mounted volumes.
+ On Linux, returns the number of mounted volumes and GTK 3 bookmarks.
+ On other platforms, the method returns 0.
</description>
</method>
<method name="get_files">
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index be993b88e5..f263a8b62b 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -216,6 +216,8 @@ static bool _filter_drive(struct mntent *mnt) {
#endif
static void _get_drives(List<String> *list) {
+ list->push_back("/");
+
#if defined(HAVE_MNTENT) && defined(X11_ENABLED)
// Check /etc/mtab for the list of mounted partitions
FILE *mtab = setmntent("/etc/mtab", "r");
@@ -286,6 +288,20 @@ String DirAccessUnix::get_drive(int p_drive) {
return list[p_drive];
}
+int DirAccessUnix::get_current_drive() {
+ int drive = 0;
+ int max_length = -1;
+ const String path = get_current_dir().to_lower();
+ for (int i = 0; i < get_drive_count(); i++) {
+ const String d = get_drive(i).to_lower();
+ if (max_length < d.length() && path.begins_with(d)) {
+ max_length = d.length();
+ drive = i;
+ }
+ }
+ return drive;
+}
+
bool DirAccessUnix::drives_are_shortcuts() {
return true;
}
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 8b19308967..327707de00 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -63,6 +63,7 @@ public:
virtual int get_drive_count();
virtual String get_drive(int p_drive);
+ virtual int get_current_drive();
virtual bool drives_are_shortcuts();
virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index ce33f54243..111c8c699e 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -388,7 +388,7 @@ void EditorSpinSlider::_draw_spin_slider() {
// Draw the horizontal slider's grabber.
c.a = 0.9;
- const Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE);
+ const Rect2 grabber_rect = Rect2(ofs + gofs, svofs, grabber_w, 4 * EDSCALE);
draw_rect(grabber_rect, c);
grabbing_spinner_mouse_pos = get_global_position() + grabber_rect.get_center();
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 89016b8758..b5d2b571f5 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -1996,7 +1996,7 @@ void ThemeTypeDialog::_dialog_about_to_show() {
}
void ThemeTypeDialog::ok_pressed() {
- emit_signal(SNAME("type_selected"), add_type_filter->get_text().strip_edges());
+ _add_type_selected(add_type_filter->get_text().strip_edges());
}
void ThemeTypeDialog::_update_add_type_options(const String &p_filter) {
@@ -2042,12 +2042,25 @@ void ThemeTypeDialog::_add_type_options_cbk(int p_index) {
}
void ThemeTypeDialog::_add_type_dialog_entered(const String &p_value) {
- emit_signal(SNAME("type_selected"), p_value.strip_edges());
- hide();
+ _add_type_selected(p_value.strip_edges());
}
void ThemeTypeDialog::_add_type_dialog_activated(int p_index) {
- emit_signal(SNAME("type_selected"), add_type_options->get_item_text(p_index));
+ _add_type_selected(add_type_options->get_item_text(p_index));
+}
+
+void ThemeTypeDialog::_add_type_selected(const String &p_type_name) {
+ pre_submitted_value = p_type_name;
+ if (p_type_name.is_empty()) {
+ add_type_confirmation->popup_centered();
+ return;
+ }
+
+ _add_type_confirmed();
+}
+
+void ThemeTypeDialog::_add_type_confirmed() {
+ emit_signal(SNAME("type_selected"), pre_submitted_value);
hide();
}
@@ -2082,11 +2095,13 @@ void ThemeTypeDialog::set_include_own_types(bool p_enable) {
}
ThemeTypeDialog::ThemeTypeDialog() {
+ set_hide_on_ok(false);
+
VBoxContainer *add_type_vb = memnew(VBoxContainer);
add_child(add_type_vb);
Label *add_type_filter_label = memnew(Label);
- add_type_filter_label->set_text(TTR("Name:"));
+ add_type_filter_label->set_text(TTR("Filter the list of types or create a new custom type:"));
add_type_vb->add_child(add_type_filter_label);
add_type_filter = memnew(LineEdit);
@@ -2095,7 +2110,7 @@ ThemeTypeDialog::ThemeTypeDialog() {
add_type_filter->connect("text_submitted", callable_mp(this, &ThemeTypeDialog::_add_type_dialog_entered));
Label *add_type_options_label = memnew(Label);
- add_type_options_label->set_text(TTR("Node Types:"));
+ add_type_options_label->set_text(TTR("Available Node-based types:"));
add_type_vb->add_child(add_type_options_label);
add_type_options = memnew(ItemList);
@@ -2103,6 +2118,12 @@ ThemeTypeDialog::ThemeTypeDialog() {
add_type_vb->add_child(add_type_options);
add_type_options->connect("item_selected", callable_mp(this, &ThemeTypeDialog::_add_type_options_cbk));
add_type_options->connect("item_activated", callable_mp(this, &ThemeTypeDialog::_add_type_dialog_activated));
+
+ add_type_confirmation = memnew(ConfirmationDialog);
+ add_type_confirmation->set_title(TTR("Type name is empty!"));
+ add_type_confirmation->set_text(TTR("Are you sure you want to create an empty type?"));
+ add_type_confirmation->connect("confirmed", callable_mp(this, &ThemeTypeDialog::_add_type_confirmed));
+ add_child(add_type_confirmation);
}
VBoxContainer *ThemeTypeEditor::_create_item_list(Theme::DataType p_data_type) {
@@ -2603,6 +2624,7 @@ void ThemeTypeEditor::_list_type_selected(int p_index) {
void ThemeTypeEditor::_add_type_button_cbk() {
add_type_mode = ADD_THEME_TYPE;
add_type_dialog->set_title(TTR("Add Item Type"));
+ add_type_dialog->get_ok_button()->set_text(TTR("Add Type"));
add_type_dialog->set_include_own_types(false);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
}
@@ -2969,7 +2991,8 @@ void ThemeTypeEditor::_type_variation_changed(const String p_value) {
void ThemeTypeEditor::_add_type_variation_cbk() {
add_type_mode = ADD_VARIATION_BASE;
- add_type_dialog->set_title(TTR("Add Variation Base Type"));
+ add_type_dialog->set_title(TTR("Set Variation Base Type"));
+ add_type_dialog->get_ok_button()->set_text(TTR("Set Base Type"));
add_type_dialog->set_include_own_types(true);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
}
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index f5ad577aff..bd1bf216e1 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef THEME_EDITOR_PLUGIN_H
#define THEME_EDITOR_PLUGIN_H
+#include "scene/gui/dialogs.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/option_button.h"
#include "scene/gui/scroll_container.h"
@@ -270,8 +271,11 @@ class ThemeTypeDialog : public ConfirmationDialog {
Ref<Theme> edited_theme;
bool include_own_types = false;
+ String pre_submitted_value;
+
LineEdit *add_type_filter;
ItemList *add_type_options;
+ ConfirmationDialog *add_type_confirmation;
void _dialog_about_to_show();
void ok_pressed() override;
@@ -283,6 +287,9 @@ class ThemeTypeDialog : public ConfirmationDialog {
void _add_type_dialog_entered(const String &p_value);
void _add_type_dialog_activated(int p_index);
+ void _add_type_selected(const String &p_type_name);
+ void _add_type_confirmed();
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index e2908a8a66..cfab021e24 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -942,7 +942,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
FontGlyph chr;
chr.found = true;
- chr.advance = advance.round();
+ chr.advance = advance;
if (shape.validate() && shape.contours.size() > 0) {
int w = (bounds.r - bounds.l);
@@ -1095,12 +1095,12 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
}
FontGlyph chr;
- chr.advance = (advance * p_data->scale / p_data->oversampling).round();
+ chr.advance = advance * p_data->scale / p_data->oversampling;
chr.texture_idx = tex_pos.index;
chr.found = true;
chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h);
- chr.rect.position = (Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling).round();
+ chr.rect.position = Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling;
chr.rect.size = chr.uv_rect.size * p_data->scale / p_data->oversampling;
return chr;
}
@@ -1270,7 +1270,8 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
}
FT_Select_Size(fd->face, best_match);
} else {
- FT_Set_Pixel_Sizes(fd->face, 0, fd->size.x * fd->oversampling);
+ FT_Set_Pixel_Sizes(fd->face, 0, float(fd->size.x * fd->oversampling));
+ fd->scale = ((float)fd->size.x * fd->oversampling) / (float)fd->face->size->metrics.y_ppem;
}
fd->hb_handle = hb_ft_font_create(fd->face, nullptr);
@@ -2670,7 +2671,7 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
Vector2i size = _get_size(fd, p_size);
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
if (!_ensure_glyph(fd, size, p_index)) {
- return; // // Invalid or non graphicl glyph, do not display errors, nothing to draw.
+ return; // Invalid or non-graphical glyph, do not display errors, nothing to draw.
}
const FontGlyph &gl = fd->cache[size]->glyph_map[p_index];
@@ -2692,9 +2693,9 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
} else {
- Point2i cpos = p_pos;
+ Point2 cpos = p_pos.floor();
cpos += gl.rect.position;
- Size2i csize = gl.rect.size;
+ Size2 csize = gl.rect.size;
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
}
}
@@ -2710,7 +2711,7 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
Vector2i size = _get_size_outline(fd, Vector2i(p_size, p_outline_size));
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
if (!_ensure_glyph(fd, size, p_index)) {
- return; // // Invalid or non graphicl glyph, do not display errors, nothing to draw.
+ return; // Invalid or non-graphical glyph, do not display errors, nothing to draw.
}
const FontGlyph &gl = fd->cache[size]->glyph_map[p_index];
@@ -2732,9 +2733,9 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
} else {
- Point2i cpos = p_pos;
+ Point2 cpos = p_pos.floor();
cpos += gl.rect.position;
- Size2i csize = gl.rect.size;
+ Size2 csize = gl.rect.size;
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
}
}
@@ -3156,7 +3157,7 @@ bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, con
}
ShapedTextDataAdvanced::Span span;
- span.start = sd->text.length();
+ span.start = sd->start + sd->text.length();
span.end = span.start + p_length;
span.embedded_key = p_key;
@@ -3322,60 +3323,72 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
ERR_FAIL_COND_V(sd->end < p_start + p_length, RID());
ShapedTextDataAdvanced *new_sd = memnew(ShapedTextDataAdvanced);
-
- new_sd->hb_buffer = hb_buffer_create();
new_sd->parent = p_shaped;
new_sd->start = p_start;
new_sd->end = p_start + p_length;
-
new_sd->orientation = sd->orientation;
new_sd->direction = sd->direction;
new_sd->custom_punct = sd->custom_punct;
new_sd->para_direction = sd->para_direction;
- new_sd->line_breaks_valid = sd->line_breaks_valid;
- new_sd->justification_ops_valid = sd->justification_ops_valid;
- new_sd->sort_valid = false;
- new_sd->upos = sd->upos;
- new_sd->uthk = sd->uthk;
+
+ if (!_shape_substr(new_sd, sd, p_start, p_length)) {
+ memdelete(new_sd);
+ return RID();
+ }
+ return shaped_owner.make_rid(new_sd);
+}
+
+bool TextServerAdvanced::_shape_substr(ShapedTextDataAdvanced *p_new_sd, const ShapedTextDataAdvanced *p_sd, int p_start, int p_length) const {
+ if (p_new_sd->valid) {
+ return true;
+ }
+
+ p_new_sd->hb_buffer = hb_buffer_create();
+
+ p_new_sd->line_breaks_valid = p_sd->line_breaks_valid;
+ p_new_sd->justification_ops_valid = p_sd->justification_ops_valid;
+ p_new_sd->sort_valid = false;
+ p_new_sd->upos = p_sd->upos;
+ p_new_sd->uthk = p_sd->uthk;
if (p_length > 0) {
- new_sd->text = sd->text.substr(p_start, p_length);
- new_sd->utf16 = new_sd->text.utf16();
- new_sd->script_iter = memnew(ScriptIterator(new_sd->text, 0, new_sd->text.length()));
+ p_new_sd->text = p_sd->text.substr(p_start - p_sd->start, p_length);
+ p_new_sd->utf16 = p_new_sd->text.utf16();
+ p_new_sd->script_iter = memnew(ScriptIterator(p_new_sd->text, 0, p_new_sd->text.length()));
- int sd_size = sd->glyphs.size();
- const Glyph *sd_glyphs = sd->glyphs.ptr();
- for (int ov = 0; ov < sd->bidi_override.size(); ov++) {
+ int sd_size = p_sd->glyphs.size();
+ const Glyph *sd_glyphs = p_sd->glyphs.ptr();
+ for (int ov = 0; ov < p_sd->bidi_override.size(); ov++) {
UErrorCode err = U_ZERO_ERROR;
- if (sd->bidi_override[ov].x >= p_start + p_length || sd->bidi_override[ov].y <= p_start) {
+ if (p_sd->bidi_override[ov].x >= p_start + p_length || p_sd->bidi_override[ov].y <= p_start) {
continue;
}
- int start = _convert_pos_inv(sd, MAX(0, p_start - sd->bidi_override[ov].x));
- int end = _convert_pos_inv(sd, MIN(p_start + p_length, sd->bidi_override[ov].y) - sd->bidi_override[ov].x);
+ int start = _convert_pos_inv(p_sd, MAX(0, p_start - p_sd->bidi_override[ov].x));
+ int end = _convert_pos_inv(p_sd, MIN(p_start + p_length, p_sd->bidi_override[ov].y) - p_sd->bidi_override[ov].x);
- ERR_FAIL_COND_V_MSG((start < 0 || end - start > new_sd->utf16.length()), RID(), "Invalid BiDi override range.");
+ ERR_FAIL_COND_V_MSG((start < 0 || end - start > p_new_sd->utf16.length()), false, "Invalid BiDi override range.");
// Create temporary line bidi & shape.
UBiDi *bidi_iter = ubidi_openSized(end - start, 0, &err);
- ERR_FAIL_COND_V_MSG(U_FAILURE(err), RID(), u_errorName(err));
- ubidi_setLine(sd->bidi_iter[ov], start, end, bidi_iter, &err);
+ ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err));
+ ubidi_setLine(p_sd->bidi_iter[ov], start, end, bidi_iter, &err);
if (U_FAILURE(err)) {
ubidi_close(bidi_iter);
- ERR_FAIL_V_MSG(RID(), u_errorName(err));
+ ERR_FAIL_V_MSG(false, u_errorName(err));
}
- new_sd->bidi_iter.push_back(bidi_iter);
+ p_new_sd->bidi_iter.push_back(bidi_iter);
err = U_ZERO_ERROR;
int bidi_run_count = ubidi_countRuns(bidi_iter, &err);
- ERR_FAIL_COND_V_MSG(U_FAILURE(err), RID(), u_errorName(err));
+ ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err));
for (int i = 0; i < bidi_run_count; i++) {
int32_t _bidi_run_start = 0;
int32_t _bidi_run_length = 0;
ubidi_getVisualRun(bidi_iter, i, &_bidi_run_start, &_bidi_run_length);
- int32_t bidi_run_start = _convert_pos(sd, sd->bidi_override[ov].x + start + _bidi_run_start);
- int32_t bidi_run_end = _convert_pos(sd, sd->bidi_override[ov].x + start + _bidi_run_start + _bidi_run_length);
+ int32_t bidi_run_start = _convert_pos(p_sd, p_sd->bidi_override[ov].x + start + _bidi_run_start);
+ int32_t bidi_run_end = _convert_pos(p_sd, p_sd->bidi_override[ov].x + start + _bidi_run_start + _bidi_run_length);
for (int j = 0; j < sd_size; j++) {
if ((sd_glyphs[j].start >= bidi_run_start) && (sd_glyphs[j].end <= bidi_run_end)) {
@@ -3384,67 +3397,67 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
Variant key;
bool find_embedded = false;
if (gl.count == 1) {
- for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
+ for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : p_sd->objects) {
if (E.value.pos == gl.start) {
find_embedded = true;
key = E.key;
- new_sd->objects[key] = E.value;
+ p_new_sd->objects[key] = E.value;
break;
}
}
}
if (find_embedded) {
- if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
- new_sd->objects[key].rect.position.x = new_sd->width;
- new_sd->width += new_sd->objects[key].rect.size.x;
+ if (p_new_sd->orientation == ORIENTATION_HORIZONTAL) {
+ p_new_sd->objects[key].rect.position.x = p_new_sd->width;
+ p_new_sd->width += p_new_sd->objects[key].rect.size.x;
} else {
- new_sd->objects[key].rect.position.y = new_sd->width;
- new_sd->width += new_sd->objects[key].rect.size.y;
+ p_new_sd->objects[key].rect.position.y = p_new_sd->width;
+ p_new_sd->width += p_new_sd->objects[key].rect.size.y;
}
} else {
if (gl.font_rid.is_valid()) {
- if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
- new_sd->ascent = MAX(new_sd->ascent, MAX(font_get_ascent(gl.font_rid, gl.font_size), -gl.y_off));
- new_sd->descent = MAX(new_sd->descent, MAX(font_get_descent(gl.font_rid, gl.font_size), gl.y_off));
+ if (p_new_sd->orientation == ORIENTATION_HORIZONTAL) {
+ p_new_sd->ascent = MAX(p_new_sd->ascent, MAX(font_get_ascent(gl.font_rid, gl.font_size), -gl.y_off));
+ p_new_sd->descent = MAX(p_new_sd->descent, MAX(font_get_descent(gl.font_rid, gl.font_size), gl.y_off));
} else {
- new_sd->ascent = MAX(new_sd->ascent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));
- new_sd->descent = MAX(new_sd->descent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));
+ p_new_sd->ascent = MAX(p_new_sd->ascent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));
+ p_new_sd->descent = MAX(p_new_sd->descent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));
}
- } else if (new_sd->preserve_invalid || (new_sd->preserve_control && is_control(gl.index))) {
+ } else if (p_new_sd->preserve_invalid || (p_new_sd->preserve_control && is_control(gl.index))) {
// Glyph not found, replace with hex code box.
- if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
- new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
+ if (p_new_sd->orientation == ORIENTATION_HORIZONTAL) {
+ p_new_sd->ascent = MAX(p_new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
} else {
- new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
- new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
+ p_new_sd->ascent = MAX(p_new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
+ p_new_sd->descent = MAX(p_new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
}
}
- new_sd->width += gl.advance * gl.repeat;
+ p_new_sd->width += gl.advance * gl.repeat;
}
- new_sd->glyphs.push_back(gl);
+ p_new_sd->glyphs.push_back(gl);
}
}
}
}
// Align embedded objects to baseline.
- float full_ascent = new_sd->ascent;
- float full_descent = new_sd->descent;
- for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) {
- if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) {
- if (sd->orientation == ORIENTATION_HORIZONTAL) {
+ float full_ascent = p_new_sd->ascent;
+ float full_descent = p_new_sd->descent;
+ for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : p_new_sd->objects) {
+ if ((E.value.pos >= p_new_sd->start) && (E.value.pos < p_new_sd->end)) {
+ if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) {
case INLINE_ALIGNMENT_TO_TOP: {
- E.value.rect.position.y = -new_sd->ascent;
+ E.value.rect.position.y = -p_new_sd->ascent;
} break;
case INLINE_ALIGNMENT_TO_CENTER: {
- E.value.rect.position.y = (-new_sd->ascent + new_sd->descent) / 2;
+ E.value.rect.position.y = (-p_new_sd->ascent + p_new_sd->descent) / 2;
} break;
case INLINE_ALIGNMENT_TO_BASELINE: {
E.value.rect.position.y = 0;
} break;
case INLINE_ALIGNMENT_TO_BOTTOM: {
- E.value.rect.position.y = new_sd->descent;
+ E.value.rect.position.y = p_new_sd->descent;
} break;
}
switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) {
@@ -3463,16 +3476,16 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
} else {
switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) {
case INLINE_ALIGNMENT_TO_TOP: {
- E.value.rect.position.x = -new_sd->ascent;
+ E.value.rect.position.x = -p_new_sd->ascent;
} break;
case INLINE_ALIGNMENT_TO_CENTER: {
- E.value.rect.position.x = (-new_sd->ascent + new_sd->descent) / 2;
+ E.value.rect.position.x = (-p_new_sd->ascent + p_new_sd->descent) / 2;
} break;
case INLINE_ALIGNMENT_TO_BASELINE: {
E.value.rect.position.x = 0;
} break;
case INLINE_ALIGNMENT_TO_BOTTOM: {
- E.value.rect.position.x = new_sd->descent;
+ E.value.rect.position.x = p_new_sd->descent;
} break;
}
switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) {
@@ -3491,12 +3504,12 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
}
}
}
- new_sd->ascent = full_ascent;
- new_sd->descent = full_descent;
+ p_new_sd->ascent = full_ascent;
+ p_new_sd->descent = full_descent;
}
- new_sd->valid = true;
+ p_new_sd->valid = true;
- return shaped_owner.make_rid(new_sd);
+ return true;
}
RID TextServerAdvanced::shaped_text_get_parent(RID p_shaped) const {
@@ -4225,8 +4238,8 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
for (int i = p_start; i < p_end; i++) {
if (p_sd->preserve_invalid || (p_sd->preserve_control && is_control(p_sd->text[i]))) {
Glyph gl;
- gl.start = i;
- gl.end = i + 1;
+ gl.start = i + p_sd->start;
+ gl.end = i + 1 + p_sd->start;
gl.count = 1;
gl.index = p_sd->text[i];
gl.font_size = fs;
@@ -4252,6 +4265,9 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
RID f = p_fonts[p_fb_index];
hb_font_t *hb_font = _font_get_hb_handle(f, fs);
+ float scale = font_get_scale(f, fs);
+ float sp_sp = font_get_spacing(f, fs, SPACING_SPACE);
+ float sp_gl = font_get_spacing(f, fs, SPACING_GLYPH);
ERR_FAIL_COND(hb_font == nullptr);
hb_buffer_clear_contents(p_sd->hb_buffer);
@@ -4335,7 +4351,6 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
gl.index = glyph_info[i].codepoint;
if (gl.index != 0) {
- float scale = font_get_scale(f, fs);
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale));
} else {
@@ -4344,10 +4359,10 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
gl.x_off = Math::round(glyph_pos[i].x_offset / (64.0 / scale));
gl.y_off = -Math::round(glyph_pos[i].y_offset / (64.0 / scale));
}
- if (font_get_spacing(f, fs, SPACING_SPACE) && is_whitespace(p_sd->text[glyph_info[i].cluster])) {
- gl.advance += font_get_spacing(f, fs, SPACING_SPACE);
+ if (sp_sp && is_whitespace(p_sd->text[glyph_info[i].cluster])) {
+ gl.advance += sp_sp;
} else {
- gl.advance += font_get_spacing(f, fs, SPACING_GLYPH);
+ gl.advance += sp_gl;
}
if (p_sd->preserve_control) {
@@ -4385,10 +4400,13 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
p_sd->ascent = MAX(p_sd->ascent, -w[i + j].y_off);
p_sd->descent = MAX(p_sd->descent, w[i + j].y_off);
} else {
- p_sd->ascent = MAX(p_sd->ascent, Math::round(font_get_glyph_advance(f, fs, w[i + j].index).x * 0.5));
- p_sd->descent = MAX(p_sd->descent, Math::round(font_get_glyph_advance(f, fs, w[i + j].index).x * 0.5));
+ float gla = Math::round(font_get_glyph_advance(f, fs, w[i + j].index).x * 0.5);
+ p_sd->ascent = MAX(p_sd->ascent, gla);
+ p_sd->descent = MAX(p_sd->descent, gla);
}
p_sd->width += w[i + j].advance;
+ w[i + j].start += p_sd->start;
+ w[i + j].end += p_sd->start;
p_sd->glyphs.push_back(w[i + j]);
}
} else {
@@ -4421,10 +4439,14 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
return true;
}
+ invalidate(sd);
if (sd->parent != RID()) {
- full_copy(sd);
+ shaped_text_shape(sd->parent);
+ ShapedTextDataAdvanced *parent_sd = shaped_owner.get_or_null(sd->parent);
+ ERR_FAIL_COND_V(!parent_sd->valid, false);
+ ERR_FAIL_COND_V(!_shape_substr(sd, parent_sd, sd->start, sd->end - sd->start), false);
+ return true;
}
- invalidate(sd);
if (sd->text.length() == 0) {
sd->valid = true;
@@ -4440,15 +4462,17 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
}
if (sd->bidi_override.is_empty()) {
- sd->bidi_override.push_back(Vector2i(0, sd->end));
+ sd->bidi_override.push_back(Vector2i(sd->start, sd->end));
}
for (int ov = 0; ov < sd->bidi_override.size(); ov++) {
// Create BiDi iterator.
- int start = _convert_pos_inv(sd, sd->bidi_override[ov].x);
- int end = _convert_pos_inv(sd, sd->bidi_override[ov].y);
+ int start = _convert_pos_inv(sd, sd->bidi_override[ov].x - sd->start);
+ int end = _convert_pos_inv(sd, sd->bidi_override[ov].y - sd->start);
- ERR_FAIL_COND_V_MSG((start < 0 || end - start > sd->utf16.length()), false, "Invalid BiDi override range.");
+ if (start < 0 || end - start > sd->utf16.length()) {
+ continue;
+ }
UErrorCode err = U_ZERO_ERROR;
UBiDi *bidi_iter = ubidi_openSized(end, 0, &err);
@@ -4502,8 +4526,8 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
}
}
- int32_t bidi_run_start = _convert_pos(sd, sd->bidi_override[ov].x + _bidi_run_start);
- int32_t bidi_run_end = _convert_pos(sd, sd->bidi_override[ov].x + _bidi_run_start + _bidi_run_length);
+ int32_t bidi_run_start = _convert_pos(sd, sd->bidi_override[ov].x - sd->start + _bidi_run_start);
+ int32_t bidi_run_end = _convert_pos(sd, sd->bidi_override[ov].x - sd->start + _bidi_run_start + _bidi_run_length);
// Shape runs.
@@ -4525,7 +4549,7 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
for (int k = spn_from; k != spn_to; k += spn_delta) {
const ShapedTextDataAdvanced::Span &span = sd->spans[k];
- if (span.start >= script_run_end || span.end <= script_run_start) {
+ if (span.start - sd->start >= script_run_end || span.end - sd->start <= script_run_start) {
continue;
}
if (span.embedded_key != Variant()) {
@@ -4566,7 +4590,7 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
}
fonts.append_array(fonts_scr_only);
fonts.append_array(fonts_no_match);
- _shape_run(sd, MAX(sd->spans[k].start, script_run_start), MIN(sd->spans[k].end, script_run_end), sd->script_iter->script_ranges[j].script, bidi_run_direction, fonts, k, 0);
+ _shape_run(sd, MAX(sd->spans[k].start - sd->start, script_run_start), MIN(sd->spans[k].end - sd->start, script_run_end), sd->script_iter->script_ranges[j].script, bidi_run_direction, fonts, k, 0);
}
}
}
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 414db8c7ea..9a22180f39 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -269,6 +269,7 @@ class TextServerAdvanced : public TextServer {
int _convert_pos(const ShapedTextDataAdvanced *p_sd, int p_pos) const;
int _convert_pos_inv(const ShapedTextDataAdvanced *p_sd, int p_pos) const;
+ bool _shape_substr(ShapedTextDataAdvanced *p_new_sd, const ShapedTextDataAdvanced *p_sd, int p_start, int p_length) const;
void _shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_start, int32_t p_end, hb_script_t p_script, hb_direction_t p_direction, Vector<RID> p_fonts, int p_span, int p_fb_index);
Glyph _shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size);
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 97a53143cf..8979d9ff4c 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -399,7 +399,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
FontGlyph chr;
chr.found = true;
- chr.advance = advance.round();
+ chr.advance = advance;
if (shape.validate() && shape.contours.size() > 0) {
int w = (bounds.r - bounds.l);
@@ -552,12 +552,12 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
}
FontGlyph chr;
- chr.advance = (advance * p_data->scale / p_data->oversampling).round();
+ chr.advance = advance * p_data->scale / p_data->oversampling;
chr.texture_idx = tex_pos.index;
chr.found = true;
chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h);
- chr.rect.position = (Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling).round();
+ chr.rect.position = Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling;
chr.rect.size = chr.uv_rect.size * p_data->scale / p_data->oversampling;
return chr;
}
@@ -729,7 +729,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
}
FT_Select_Size(fd->face, best_match);
} else {
- FT_Set_Pixel_Sizes(fd->face, 0, fd->size.x * fd->oversampling);
+ FT_Set_Pixel_Sizes(fd->face, 0, Math::round(fd->size.x * fd->oversampling));
+ fd->scale = ((float)fd->size.x * fd->oversampling) / (float)fd->face->size->metrics.y_ppem;
}
fd->ascent = (fd->face->size->metrics.ascender / 64.0) / fd->oversampling * fd->scale;
@@ -1824,7 +1825,7 @@ void TextServerFallback::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
Vector2i size = _get_size(fd, p_size);
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
if (!_ensure_glyph(fd, size, p_index)) {
- return; // // Invalid or non graphicl glyph, do not display errors, nothing to draw.
+ return; // Invalid or non-graphical glyph, do not display errors, nothing to draw.
}
const FontGlyph &gl = fd->cache[size]->glyph_map[p_index];
@@ -1846,9 +1847,9 @@ void TextServerFallback::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
} else {
- Point2i cpos = p_pos;
+ Point2 cpos = p_pos.floor();
cpos += gl.rect.position;
- Size2i csize = gl.rect.size;
+ Size2 csize = gl.rect.size;
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
}
}
@@ -1864,7 +1865,7 @@ void TextServerFallback::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
Vector2i size = _get_size_outline(fd, Vector2i(p_size, p_outline_size));
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
if (!_ensure_glyph(fd, size, p_index)) {
- return; // // Invalid or non graphicl glyph, do not display errors, nothing to draw.
+ return; // Invalid or non-graphical glyph, do not display errors, nothing to draw.
}
const FontGlyph &gl = fd->cache[size]->glyph_map[p_index];
@@ -1886,9 +1887,9 @@ void TextServerFallback::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
} else {
- Point2i cpos = p_pos;
+ Point2 cpos = p_pos.floor();
cpos += gl.rect.position;
- Size2i csize = gl.rect.size;
+ Size2 csize = gl.rect.size;
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
}
}
@@ -2260,7 +2261,7 @@ bool TextServerFallback::shaped_text_add_object(RID p_shaped, Variant p_key, con
}
ShapedTextData::Span span;
- span.start = sd->text.length();
+ span.start = sd->start + sd->text.length();
span.end = span.start + p_length;
span.embedded_key = p_key;
@@ -2441,7 +2442,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
new_sd->uthk = sd->uthk;
if (p_length > 0) {
- new_sd->text = sd->text.substr(p_start, p_length);
+ new_sd->text = sd->text.substr(p_start - sd->start, p_length);
int sd_size = sd->glyphs.size();
const Glyph *sd_glyphs = sd->glyphs.ptr();
@@ -2723,7 +2724,7 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) {
for (int i = 0; i < sd_size; i++) {
if (sd_glyphs[i].count > 0) {
- char32_t c = sd->text[sd_glyphs[i].start];
+ char32_t c = sd->text[sd_glyphs[i].start - sd->start];
if (c_punct_size == 0) {
if (is_punct(c)) {
sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION;
@@ -2980,7 +2981,7 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
gl.end = j + 1;
gl.count = 1;
gl.font_size = span.font_size;
- gl.index = (int32_t)sd->text[j]; // Use codepoint.
+ gl.index = (int32_t)sd->text[j - sd->start]; // Use codepoint.
if (gl.index == 0x0009 || gl.index == 0x000b) {
gl.index = 0x0020;
}
@@ -2996,7 +2997,7 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
}
if (gl.font_rid.is_valid()) {
- if (sd->text[j] != 0 && !is_linebreak(sd->text[j])) {
+ if (sd->text[j - sd->start] != 0 && !is_linebreak(sd->text[j - sd->start])) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x;
gl.x_off = 0;
@@ -3011,7 +3012,7 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
sd->descent = MAX(sd->descent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));
}
}
- if (font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_SPACE) && is_whitespace(sd->text[j])) {
+ if (font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_SPACE) && is_whitespace(sd->text[j - sd->start])) {
gl.advance += font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_SPACE);
} else {
gl.advance += font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_GLYPH);
diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp
index 133bd71ddb..20fe63bf7d 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.cpp
+++ b/modules/webrtc/webrtc_multiplayer_peer.cpp
@@ -146,6 +146,10 @@ void WebRTCMultiplayerPeer::_find_next_peer() {
}
// After last.
while (E) {
+ if (!E->get()->connected) {
+ E = E->next();
+ continue;
+ }
for (const Ref<WebRTCDataChannel> &F : E->get()->channels) {
if (F->get_available_packet_count()) {
next_packet_peer = E->key();
@@ -157,6 +161,10 @@ void WebRTCMultiplayerPeer::_find_next_peer() {
E = peer_map.front();
// Before last
while (E) {
+ if (!E->get()->connected) {
+ E = E->next();
+ continue;
+ }
for (const Ref<WebRTCDataChannel> &F : E->get()->channels) {
if (F->get_available_packet_count()) {
next_packet_peer = E->key();
@@ -378,6 +386,9 @@ int WebRTCMultiplayerPeer::get_available_packet_count() const {
}
int size = 0;
for (const KeyValue<int, Ref<ConnectedPeer>> &E : peer_map) {
+ if (!E.value->connected) {
+ continue;
+ }
for (const Ref<WebRTCDataChannel> &F : E.value->channels) {
size += F->get_available_packet_count();
}
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 87aee0aae4..50e2de91f7 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -449,10 +449,10 @@ void BaseMaterial3D::_update_shader() {
texfilter_str = "filter_linear_mipmap";
break;
case TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC:
- texfilter_str = "filter_nearest_mipmap_aniso";
+ texfilter_str = "filter_nearest_mipmap_anisotropy";
break;
case TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC:
- texfilter_str = "filter_linear_mipmap_aniso";
+ texfilter_str = "filter_linear_mipmap_anisotropy";
break;
case TEXTURE_FILTER_MAX:
break; // Internal value, skip.
@@ -2569,7 +2569,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_world_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_WORLD_TRIPLANAR);
ADD_GROUP("Sampling", "texture_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Aniso.,Linear Mipmap Aniso."), "set_texture_filter", "get_texture_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropy,Linear Mipmap Anisotropy"), "set_texture_filter", "get_texture_filter");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "texture_repeat"), "set_flag", "get_flag", FLAG_USE_TEXTURE_REPEAT);
ADD_GROUP("Shadows", "");
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index b077501a38..752e7b96be 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -214,8 +214,8 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
"FILTER_LINEAR_MIPMAP",
- "FILTER_NEAREST_MIPMAP_ANISO",
- "FILTER_LINEAR_MIPMAP_ANISO",
+ "FILTER_NEAREST_MIPMAP_ANISOTROPY",
+ "FILTER_LINEAR_MIPMAP_ANISOTROPY",
"REPEAT_ENABLE",
"REPEAT_DISABLE",
"SHADER_TYPE",
@@ -328,8 +328,8 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_FILTER_LINEAR, "filter_linear" },
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
{ TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap" },
- { TK_FILTER_NEAREST_MIPMAP_ANISO, "filter_nearest_mipmap_aniso" },
- { TK_FILTER_LINEAR_MIPMAP_ANISO, "filter_linear_mipmap_aniso" },
+ { TK_FILTER_NEAREST_MIPMAP_ANISOTROPY, "filter_nearest_mipmap_anisotropy" },
+ { TK_FILTER_LINEAR_MIPMAP_ANISOTROPY, "filter_linear_mipmap_anisotropy" },
{ TK_REPEAT_ENABLE, "repeat_enable" },
{ TK_REPEAT_DISABLE, "repeat_disable" },
{ TK_SHADER_TYPE, "shader_type" },
@@ -7648,57 +7648,71 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error("void datatype not allowed here");
return ERR_PARSE_ERROR;
}
- tk = _get_token();
-
- if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected identifier or '['.");
- return ERR_PARSE_ERROR;
- }
+ bool first = true;
+ bool fixed_array_size = false;
int array_size = 0;
- if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size, constants);
- if (error != OK) {
- return error;
- }
+ do {
tk = _get_token();
- }
- if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier!");
- return ERR_PARSE_ERROR;
- }
+ if (first) {
+ first = false;
- MemberNode *member = alloc_node<MemberNode>();
- member->precision = precision;
- member->datatype = type;
- member->struct_name = struct_name;
- member->name = tk.text;
- member->array_size = array_size;
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected identifier or '['.");
+ return ERR_PARSE_ERROR;
+ }
- if (member_names.has(member->name)) {
- _set_error("Redefinition of '" + String(member->name) + "'");
- return ERR_PARSE_ERROR;
- }
- member_names.insert(member->name);
- tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(array_size, constants);
+ if (error != OK) {
+ return error;
+ }
+ fixed_array_size = true;
+ tk = _get_token();
+ }
+ }
- if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(member->array_size, constants);
- if (error != OK) {
- return error;
+ if (tk.type != TK_IDENTIFIER) {
+ _set_error("Expected identifier!");
+ return ERR_PARSE_ERROR;
+ }
+
+ MemberNode *member = alloc_node<MemberNode>();
+ member->precision = precision;
+ member->datatype = type;
+ member->struct_name = struct_name;
+ member->name = tk.text;
+ member->array_size = array_size;
+
+ if (member_names.has(member->name)) {
+ _set_error("Redefinition of '" + String(member->name) + "'");
+ return ERR_PARSE_ERROR;
}
+ member_names.insert(member->name);
tk = _get_token();
- }
- if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
- return ERR_PARSE_ERROR;
- }
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_global_array_size(member->array_size, constants);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+ }
+
+ if (!fixed_array_size) {
+ array_size = 0;
+ }
+
+ if (tk.type != TK_SEMICOLON && tk.type != TK_COMMA) {
+ _set_error("Expected ',' or ';' after struct member.");
+ return ERR_PARSE_ERROR;
+ }
- st_node->members.push_back(member);
- member_count++;
+ st_node->members.push_back(member);
+ member_count++;
+ } while (tk.type == TK_COMMA); // another member
}
}
if (member_count == 0) {
@@ -8082,10 +8096,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.filter = FILTER_NEAREST_MIPMAP;
} else if (tk.type == TK_FILTER_LINEAR_MIPMAP) {
uniform2.filter = FILTER_LINEAR_MIPMAP;
- } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISO) {
- uniform2.filter = FILTER_NEAREST_MIPMAP_ANISO;
- } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISO) {
- uniform2.filter = FILTER_LINEAR_MIPMAP_ANISO;
+ } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISOTROPY) {
+ uniform2.filter = FILTER_NEAREST_MIPMAP_ANISOTROPY;
+ } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISOTROPY) {
+ uniform2.filter = FILTER_LINEAR_MIPMAP_ANISOTROPY;
} else if (tk.type == TK_REPEAT_DISABLE) {
uniform2.repeat = REPEAT_DISABLE;
} else if (tk.type == TK_REPEAT_ENABLE) {
@@ -9535,10 +9549,10 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (options.is_empty()) {
options.push_back("filter_linear");
options.push_back("filter_linear_mipmap");
- options.push_back("filter_linear_mipmap_aniso");
+ options.push_back("filter_linear_mipmap_anisotropy");
options.push_back("filter_nearest");
options.push_back("filter_nearest_mipmap");
- options.push_back("filter_nearest_mipmap_aniso");
+ options.push_back("filter_nearest_mipmap_anisotropy");
options.push_back("hint_albedo");
options.push_back("hint_anisotropy");
options.push_back("hint_black");
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 6681af2594..bd639a4707 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -179,8 +179,8 @@ public:
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
TK_FILTER_LINEAR_MIPMAP,
- TK_FILTER_NEAREST_MIPMAP_ANISO,
- TK_FILTER_LINEAR_MIPMAP_ANISO,
+ TK_FILTER_NEAREST_MIPMAP_ANISOTROPY,
+ TK_FILTER_LINEAR_MIPMAP_ANISOTROPY,
TK_REPEAT_ENABLE,
TK_REPEAT_DISABLE,
TK_SHADER_TYPE,
@@ -322,8 +322,8 @@ public:
FILTER_LINEAR,
FILTER_NEAREST_MIPMAP,
FILTER_LINEAR_MIPMAP,
- FILTER_NEAREST_MIPMAP_ANISO,
- FILTER_LINEAR_MIPMAP_ANISO,
+ FILTER_NEAREST_MIPMAP_ANISOTROPY,
+ FILTER_LINEAR_MIPMAP_ANISOTROPY,
FILTER_DEFAULT,
};
@@ -576,7 +576,7 @@ public:
virtual DataType get_datatype() const override { return datatype; }
virtual String get_datatype_name() const override { return String(struct_name); }
- virtual int get_array_size() const override { return array_size; }
+ virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
virtual bool is_indexed() const override { return index_expression != nullptr || call_expression != nullptr; }
MemberNode() :