summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/string/ustring.cpp2
-rw-r--r--doc/classes/CodeEdit.xml2
-rw-r--r--doc/classes/TextEdit.xml23
-rw-r--r--doc/classes/TileData.xml2
-rw-r--r--editor/code_editor.cpp34
-rw-r--r--editor/code_editor.h1
-rw-r--r--editor/editor_inspector.cpp8
-rw-r--r--editor/editor_log.cpp4
-rw-r--r--editor/editor_themes.cpp1
-rw-r--r--editor/icons/GuiChecked.svg2
-rw-r--r--editor/import/scene_importer_mesh.cpp105
-rw-r--r--editor/import/scene_importer_mesh.h1
-rw-r--r--editor/plugins/script_text_editor.cpp65
-rw-r--r--editor/plugins/script_text_editor.h2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp63
-rw-r--r--editor/plugins/shader_editor_plugin.h2
-rw-r--r--editor/plugins/text_editor.cpp53
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp17
-rw-r--r--editor/plugins/tiles/tile_data_editors.h7
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp7
-rw-r--r--editor/plugins/tiles/tile_set_editor.h2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp5
-rw-r--r--modules/meshoptimizer/register_types.cpp1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs6
-rw-r--r--platform/uwp/app.cpp2
-rw-r--r--scene/3d/collision_object_3d.cpp5
-rw-r--r--scene/gui/text_edit.cpp38
-rw-r--r--scene/gui/text_edit.h15
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
-rw-r--r--scene/resources/surface_tool.cpp1
-rw-r--r--scene/resources/surface_tool.h2
-rw-r--r--scene/resources/tile_set.cpp22
-rw-r--r--scene/resources/tile_set.h6
-rw-r--r--thirdparty/README.md3
-rw-r--r--thirdparty/meshoptimizer/meshoptimizer.h5
-rw-r--r--thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch262
-rw-r--r--thirdparty/meshoptimizer/simplifier.cpp152
38 files changed, 679 insertions, 253 deletions
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 3c1afc7f2c..49cf171f2b 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -939,7 +939,7 @@ const char32_t *String::get_data() const {
}
void String::erase(int p_pos, int p_chars) {
- *this = left(p_pos) + substr(p_pos + p_chars, length() - ((p_pos + p_chars)));
+ *this = left(MAX(p_pos, 0)) + substr(p_pos + p_chars, length() - ((p_pos + p_chars)));
}
String String::capitalize() const {
diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml
index 81795abcdd..42a6df866f 100644
--- a/doc/classes/CodeEdit.xml
+++ b/doc/classes/CodeEdit.xml
@@ -193,8 +193,6 @@
</theme_item>
<theme_item name="line_spacing" type="int" default="4">
</theme_item>
- <theme_item name="mark_color" type="Color" default="Color( 1, 0.4, 0.4, 0.4 )">
- </theme_item>
<theme_item name="normal" type="StyleBox">
</theme_item>
<theme_item name="outline_size" type="int" default="0">
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index b97728ccd4..29067b5534 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -167,6 +167,15 @@
Returns the text of a specific line.
</description>
</method>
+ <method name="get_line_background_color">
+ <return type="Color">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <description>
+ Returns the current background color of the line. [code]Color(0, 0, 0, 0)[/code] is returned if no color is set.
+ </description>
+ </method>
<method name="get_line_count" qualifiers="const">
<return type="int">
</return>
@@ -548,6 +557,17 @@
If [code]true[/code], hides the line of the specified index.
</description>
</method>
+ <method name="set_line_background_color">
+ <return type="void">
+ </return>
+ <argument index="0" name="line" type="int">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ Sets the current background color of the line. Set to [code]Color(0, 0, 0, 0)[/code] for no color.
+ </description>
+ </method>
<method name="set_line_gutter_clickable">
<return type="void">
</return>
@@ -987,9 +1007,6 @@
<theme_item name="line_spacing" type="int" default="4">
Sets the spacing between the lines.
</theme_item>
- <theme_item name="mark_color" type="Color" default="Color( 1, 0.4, 0.4, 0.4 )">
- Sets the [Color] of marked text.
- </theme_item>
<theme_item name="normal" type="StyleBox">
Sets the [StyleBox] of this [TextEdit].
</theme_item>
diff --git a/doc/classes/TileData.xml b/doc/classes/TileData.xml
index e3bc910ab6..efcbdf2e95 100644
--- a/doc/classes/TileData.xml
+++ b/doc/classes/TileData.xml
@@ -229,7 +229,7 @@
</member>
<member name="transpose" type="bool" setter="set_transpose" getter="get_transpose" default="false">
</member>
- <member name="y_sort_origin" type="Vector2i" setter="set_y_sort_origin" getter="get_y_sort_origin" default="Vector2i( 0, 0 )">
+ <member name="y_sort_origin" type="int" setter="set_y_sort_origin" getter="get_y_sort_origin" default="0">
</member>
<member name="z_index" type="int" setter="set_z_index" getter="get_z_index" default="0">
</member>
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 12e78c3120..87ac16fdcf 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1474,6 +1474,34 @@ void CodeTextEditor::goto_error() {
}
}
+void CodeTextEditor::_update_text_editor_theme() {
+ text_editor->add_theme_color_override("background_color", EDITOR_GET("text_editor/highlighting/background_color"));
+ text_editor->add_theme_color_override("completion_background_color", EDITOR_GET("text_editor/highlighting/completion_background_color"));
+ text_editor->add_theme_color_override("completion_selected_color", EDITOR_GET("text_editor/highlighting/completion_selected_color"));
+ text_editor->add_theme_color_override("completion_existing_color", EDITOR_GET("text_editor/highlighting/completion_existing_color"));
+ text_editor->add_theme_color_override("completion_scroll_color", EDITOR_GET("text_editor/highlighting/completion_scroll_color"));
+ text_editor->add_theme_color_override("completion_font_color", EDITOR_GET("text_editor/highlighting/completion_font_color"));
+ text_editor->add_theme_color_override("font_color", EDITOR_GET("text_editor/highlighting/text_color"));
+ text_editor->add_theme_color_override("line_number_color", EDITOR_GET("text_editor/highlighting/line_number_color"));
+ text_editor->add_theme_color_override("caret_color", EDITOR_GET("text_editor/highlighting/caret_color"));
+ text_editor->add_theme_color_override("caret_background_color", EDITOR_GET("text_editor/highlighting/caret_background_color"));
+ text_editor->add_theme_color_override("font_selected_color", EDITOR_GET("text_editor/highlighting/text_selected_color"));
+ text_editor->add_theme_color_override("selection_color", EDITOR_GET("text_editor/highlighting/selection_color"));
+ text_editor->add_theme_color_override("brace_mismatch_color", EDITOR_GET("text_editor/highlighting/brace_mismatch_color"));
+ text_editor->add_theme_color_override("current_line_color", EDITOR_GET("text_editor/highlighting/current_line_color"));
+ text_editor->add_theme_color_override("line_length_guideline_color", EDITOR_GET("text_editor/highlighting/line_length_guideline_color"));
+ text_editor->add_theme_color_override("word_highlighted_color", EDITOR_GET("text_editor/highlighting/word_highlighted_color"));
+ text_editor->add_theme_color_override("bookmark_color", EDITOR_GET("text_editor/highlighting/bookmark_color"));
+ text_editor->add_theme_color_override("breakpoint_color", EDITOR_GET("text_editor/highlighting/breakpoint_color"));
+ text_editor->add_theme_color_override("executing_line_color", EDITOR_GET("text_editor/highlighting/executing_line_color"));
+ text_editor->add_theme_color_override("code_folding_color", EDITOR_GET("text_editor/highlighting/code_folding_color"));
+ text_editor->add_theme_color_override("search_result_color", EDITOR_GET("text_editor/highlighting/search_result_color"));
+ text_editor->add_theme_color_override("search_result_border_color", EDITOR_GET("text_editor/highlighting/search_result_border_color"));
+ text_editor->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
+ emit_signal("load_theme_settings");
+ _load_theme_settings();
+}
+
void CodeTextEditor::_update_font() {
text_editor->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
text_editor->add_theme_font_size_override("font_size", get_theme_font_size("source_size", "EditorFonts"));
@@ -1497,6 +1525,7 @@ void CodeTextEditor::_update_font() {
}
void CodeTextEditor::_on_settings_change() {
+ _update_text_editor_theme();
_update_font();
font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size");
@@ -1583,14 +1612,11 @@ void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) {
void CodeTextEditor::_notification(int p_what) {
switch (p_what) {
- case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- _load_theme_settings();
- emit_signal("load_theme_settings");
- } break;
case NOTIFICATION_THEME_CHANGED: {
if (toggle_scripts_button->is_visible()) {
update_toggle_scripts_button();
}
+ _update_text_editor_theme();
_update_font();
} break;
case NOTIFICATION_ENTER_TREE: {
diff --git a/editor/code_editor.h b/editor/code_editor.h
index e201da446e..e6dadbd6fa 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -161,6 +161,7 @@ class CodeTextEditor : public VBoxContainer {
void _on_settings_change();
+ void _update_text_editor_theme();
void _update_font();
void _complete_request();
Ref<Texture2D> _get_completion_icon(const ScriptCodeCompletionOption &p_option);
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 29cc4c3c46..c730277069 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -1824,7 +1824,13 @@ void EditorInspector::update_tree() {
}
}
- String path = basename.left(basename.rfind("/"));
+ String path;
+ {
+ int idx = basename.rfind("/");
+ if (idx > -1) {
+ path = basename.left(idx);
+ }
+ }
if (use_filter && filter != "") {
String cat = path;
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 469fb41406..622b3fe355 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -234,7 +234,9 @@ void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) {
if (p_replace_previous) {
// Remove last line if replacing, as it will be replace by the next added line.
- log->remove_line(log->get_line_count() - 1);
+ // Why - 2? RichTextLabel is weird. When you add a line, it also adds a NEW line, which is null,
+ // but it still counts as a line. So if you remove the last line (count - 1) you are actually removing nothing...
+ log->remove_line(log->get_line_count() - 2);
log->increment_line_count();
}
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 2c4f4e2973..463989868d 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -216,6 +216,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
exceptions.insert("Sky");
exceptions.insert("EditorControlAnchor");
exceptions.insert("DefaultProjectIcon");
+ exceptions.insert("GuiChecked");
exceptions.insert("GuiCloseCustomizable");
exceptions.insert("GuiGraphNodePort");
exceptions.insert("GuiResizer");
diff --git a/editor/icons/GuiChecked.svg b/editor/icons/GuiChecked.svg
index 9bdf5dcb19..31b2995939 100644
--- a/editor/icons/GuiChecked.svg
+++ b/editor/icons/GuiChecked.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill-opacity=".188235" stroke-width="1.166667"/><path d="m11.500773 3.7343508-5.6117507 5.6117502-1.7045017-1.6814543-1.4992276 1.4992276 3.2037293 3.1806817 7.1109777-7.1109775z" stroke-width="1.060227"/></g></svg>
+<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.3333333 1c-1.2887 0-2.3333333 1.0446683-2.3333333 2.3333333v9.3333337c0 1.2887 1.0446683 2.333333 2.3333333 2.333333h9.3333337c1.2887 0 2.333333-1.044668 2.333333-2.333333v-9.3333337c0-1.2887-1.044668-2.3333333-2.333333-2.3333333z" fill="#699ce8" stroke-width="1.16667"/><path d="m11.500773 3.7343508-5.6117507 5.6117502-1.7045017-1.6814543-1.4992276 1.4992276 3.2037293 3.1806817 7.1109777-7.1109775z" fill="#fff" stroke-width="1.06023"/></svg>
diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp
index bc7e8a1626..fa1a027a8d 100644
--- a/editor/import/scene_importer_mesh.cpp
+++ b/editor/import/scene_importer_mesh.cpp
@@ -30,6 +30,7 @@
#include "scene_importer_mesh.h"
+#include "core/math/math_defs.h"
#include "scene/resources/surface_tool.h"
void EditorSceneImporterMesh::add_blend_shape(const String &p_name) {
@@ -141,6 +142,18 @@ void EditorSceneImporterMesh::set_surface_material(int p_surface, const Ref<Mate
surfaces.write[p_surface].material = p_material;
}
+Basis EditorSceneImporterMesh::compute_rotation_matrix_from_ortho_6d(Vector3 p_x_raw, Vector3 p_y_raw) {
+ Vector3 x = p_x_raw.normalized();
+ Vector3 z = x.cross(p_y_raw);
+ z = z.normalized();
+ Vector3 y = z.cross(x);
+ Basis basis;
+ basis.set_axis(Vector3::AXIS_X, x);
+ basis.set_axis(Vector3::AXIS_Y, y);
+ basis.set_axis(Vector3::AXIS_Z, z);
+ return basis;
+}
+
void EditorSceneImporterMesh::generate_lods() {
if (!SurfaceTool::simplify_func) {
return;
@@ -151,6 +164,9 @@ void EditorSceneImporterMesh::generate_lods() {
if (!SurfaceTool::simplify_sloppy_func) {
return;
}
+ if (!SurfaceTool::simplify_with_attrib_func) {
+ return;
+ }
for (int i = 0; i < surfaces.size(); i++) {
if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) {
@@ -163,59 +179,62 @@ void EditorSceneImporterMesh::generate_lods() {
if (indices.size() == 0) {
continue; //no lods if no indices
}
+ Vector<Vector3> normals = surfaces[i].arrays[RS::ARRAY_NORMAL];
uint32_t vertex_count = vertices.size();
const Vector3 *vertices_ptr = vertices.ptr();
-
- int min_indices = 10;
- int index_target = indices.size() / 2;
- print_line("Total indices: " + itos(indices.size()));
- float mesh_scale = SurfaceTool::simplify_scale_func((const float *)vertices_ptr, vertex_count, sizeof(Vector3));
- const float target_error = 1e-3f;
- float abs_target_error = target_error / mesh_scale;
+ Vector<float> attributes;
+ Vector<float> normal_weights;
+ int32_t attribute_count = 6;
+ if (normals.size()) {
+ attributes.resize(normals.size() * attribute_count);
+ for (int32_t normal_i = 0; normal_i < normals.size(); normal_i++) {
+ Basis basis;
+ basis.set_euler(normals[normal_i]);
+ Vector3 basis_x = basis.get_axis(0);
+ Vector3 basis_y = basis.get_axis(1);
+ basis = compute_rotation_matrix_from_ortho_6d(basis_x, basis_y);
+ basis_x = basis.get_axis(0);
+ basis_y = basis.get_axis(1);
+ attributes.write[normal_i * attribute_count + 0] = basis_x.x;
+ attributes.write[normal_i * attribute_count + 1] = basis_x.y;
+ attributes.write[normal_i * attribute_count + 2] = basis_x.z;
+ attributes.write[normal_i * attribute_count + 3] = basis_y.x;
+ attributes.write[normal_i * attribute_count + 4] = basis_y.y;
+ attributes.write[normal_i * attribute_count + 5] = basis_y.z;
+ }
+ normal_weights.resize(vertex_count);
+ for (int32_t weight_i = 0; weight_i < normal_weights.size(); weight_i++) {
+ normal_weights.write[weight_i] = 1.0;
+ }
+ } else {
+ attribute_count = 0;
+ }
+ const int min_indices = 10;
+ const float error_tolerance = 1.44224'95703; // Cube root of 3
+ const float threshold = 1.0 / error_tolerance;
+ int index_target = indices.size() * threshold;
+ float max_mesh_error_percentage = 1e0f;
+ float mesh_error = 0.0f;
while (index_target > min_indices) {
- float error;
Vector<int> new_indices;
new_indices.resize(indices.size());
- size_t new_len = SurfaceTool::simplify_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, abs_target_error, &error);
- if ((int)new_len > (index_target * 120 / 100)) {
- // Attribute discontinuities break normals.
- bool is_sloppy = false;
- if (is_sloppy) {
- abs_target_error = target_error / mesh_scale;
- index_target = new_len;
- while (index_target > min_indices) {
- Vector<int> sloppy_new_indices;
- sloppy_new_indices.resize(indices.size());
- new_len = SurfaceTool::simplify_sloppy_func((unsigned int *)sloppy_new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, abs_target_error, &error);
- if ((int)new_len > (index_target * 120 / 100)) {
- break; // 20 percent tolerance
- }
- sloppy_new_indices.resize(new_len);
- Surface::LOD lod;
- lod.distance = error * mesh_scale;
- abs_target_error = lod.distance;
- if (Math::is_equal_approx(abs_target_error, 0.0f)) {
- return;
- }
- lod.indices = sloppy_new_indices;
- print_line("Lod " + itos(surfaces.write[i].lods.size()) + " shoot for " + itos(index_target / 3) + " triangles, got " + itos(new_len / 3) + " triangles. Distance " + rtos(lod.distance) + ". Use simplify sloppy.");
- surfaces.write[i].lods.push_back(lod);
- index_target /= 2;
- }
- }
- break; // 20 percent tolerance
+ size_t new_len = SurfaceTool::simplify_with_attrib_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, max_mesh_error_percentage, &mesh_error, (float *)attributes.ptrw(), normal_weights.ptrw(), attribute_count);
+ if ((int)new_len > (index_target * error_tolerance)) {
+ break;
}
- new_indices.resize(new_len);
Surface::LOD lod;
- lod.distance = error * mesh_scale;
- abs_target_error = lod.distance;
- if (Math::is_equal_approx(abs_target_error, 0.0f)) {
- return;
+ lod.distance = mesh_error;
+ if (Math::is_equal_approx(mesh_error, 0.0f)) {
+ break;
+ }
+ if (new_len <= 0) {
+ break;
}
+ new_indices.resize(new_len);
lod.indices = new_indices;
- print_line("Lod " + itos(surfaces.write[i].lods.size()) + " shoot for " + itos(index_target / 3) + " triangles, got " + itos(new_len / 3) + " triangles. Distance " + rtos(lod.distance));
+ print_line("Lod " + itos(surfaces.write[i].lods.size()) + " begin with " + itos(indices.size() / 3) + " triangles and shoot for " + itos(index_target / 3) + " triangles. Got " + itos(new_len / 3) + " triangles. Lod screen ratio " + rtos(lod.distance));
surfaces.write[i].lods.push_back(lod);
- index_target /= 2;
+ index_target *= threshold;
}
}
}
diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h
index b3e8137e0a..c00339a620 100644
--- a/editor/import/scene_importer_mesh.h
+++ b/editor/import/scene_importer_mesh.h
@@ -67,6 +67,7 @@ class EditorSceneImporterMesh : public Resource {
Ref<EditorSceneImporterMesh> shadow_mesh;
Size2i lightmap_size_hint;
+ Basis compute_rotation_matrix_from_ortho_6d(Vector3 p_x_raw, Vector3 y_raw);
protected:
void _set_data(const Dictionary &p_data);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 25755cc6cc..abb7a2d8a3 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -170,66 +170,25 @@ void ScriptTextEditor::_load_theme_settings() {
CodeEdit *text_edit = code_editor->get_text_editor();
text_edit->clear_keywords();
+ Color updated_marked_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
Color updated_safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color");
- if (updated_safe_line_number_color != safe_line_number_color) {
+
+ bool safe_line_number_color_updated = updated_safe_line_number_color != safe_line_number_color;
+ bool marked_line_color_updated = updated_marked_line_color != marked_line_color;
+ if (safe_line_number_color_updated || marked_line_color_updated) {
safe_line_number_color = updated_safe_line_number_color;
for (int i = 0; i < text_edit->get_line_count(); i++) {
- if (text_edit->get_line_gutter_item_color(i, line_number_gutter) != default_line_number_color) {
+ if (marked_line_color_updated && text_edit->get_line_background_color(i) == marked_line_color) {
+ text_edit->set_line_background_color(i, updated_marked_line_color);
+ }
+
+ if (safe_line_number_color_updated && text_edit->get_line_gutter_item_color(i, line_number_gutter) != default_line_number_color) {
text_edit->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
}
}
+ marked_line_color = updated_marked_line_color;
}
- Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
- Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
- Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
- Color completion_existing_color = EDITOR_GET("text_editor/highlighting/completion_existing_color");
- Color completion_scroll_color = EDITOR_GET("text_editor/highlighting/completion_scroll_color");
- Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
- Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
- Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
- Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
- Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
- Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
- Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
- Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
- Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
- Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
- Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
- Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
- Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
- Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
- Color executing_line_color = EDITOR_GET("text_editor/highlighting/executing_line_color");
- Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
- Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
- Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
-
- text_edit->add_theme_color_override("background_color", background_color);
- text_edit->add_theme_color_override("completion_background_color", completion_background_color);
- text_edit->add_theme_color_override("completion_selected_color", completion_selected_color);
- text_edit->add_theme_color_override("completion_existing_color", completion_existing_color);
- text_edit->add_theme_color_override("completion_scroll_color", completion_scroll_color);
- text_edit->add_theme_color_override("completion_font_color", completion_font_color);
- text_edit->add_theme_color_override("font_color", text_color);
- text_edit->add_theme_color_override("line_number_color", line_number_color);
- text_edit->add_theme_color_override("caret_color", caret_color);
- text_edit->add_theme_color_override("caret_background_color", caret_background_color);
- text_edit->add_theme_color_override("font_selected_color", text_selected_color);
- text_edit->add_theme_color_override("selection_color", selection_color);
- text_edit->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
- text_edit->add_theme_color_override("current_line_color", current_line_color);
- text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
- text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
- text_edit->add_theme_color_override("bookmark_color", bookmark_color);
- text_edit->add_theme_color_override("breakpoint_color", breakpoint_color);
- text_edit->add_theme_color_override("executing_line_color", executing_line_color);
- text_edit->add_theme_color_override("mark_color", mark_color);
- text_edit->add_theme_color_override("code_folding_color", code_folding_color);
- text_edit->add_theme_color_override("search_result_color", search_result_color);
- text_edit->add_theme_color_override("search_result_border_color", search_result_border_color);
-
- text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
-
theme_loaded = true;
if (!script.is_null()) {
_set_theme_for_script();
@@ -546,7 +505,7 @@ void ScriptTextEditor::_validate_script() {
bool highlight_safe = EDITOR_DEF("text_editor/highlighting/highlight_type_safe_lines", true);
bool last_is_safe = false;
for (int i = 0; i < te->get_line_count(); i++) {
- te->set_line_as_marked(i, line == i);
+ te->set_line_background_color(i, (line == i) ? marked_line_color : Color(0, 0, 0, 0));
if (highlight_safe) {
if (safe_lines.has(i + 1)) {
te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index f79abc60ab..f784bbe1f8 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -89,6 +89,8 @@ class ScriptTextEditor : public ScriptEditorBase {
Color default_line_number_color = Color(1, 1, 1);
Color safe_line_number_color = Color(1, 1, 1);
+ Color marked_line_color = Color(1, 1, 1);
+
PopupPanel *color_panel = nullptr;
ColorPicker *color_picker = nullptr;
Vector2 color_position;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 3cdba9cf16..3e950eaccb 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -83,53 +83,16 @@ void ShaderTextEditor::reload_text() {
}
void ShaderTextEditor::_load_theme_settings() {
- Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
- Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
- Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
- Color completion_existing_color = EDITOR_GET("text_editor/highlighting/completion_existing_color");
- Color completion_scroll_color = EDITOR_GET("text_editor/highlighting/completion_scroll_color");
- Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
- Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
- Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
- Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
- Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
- Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
- Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
- Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
- Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
- Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
- Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
- Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
- Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
- Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
- Color executing_line_color = EDITOR_GET("text_editor/highlighting/executing_line_color");
- Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
- Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
- Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
-
- get_text_editor()->add_theme_color_override("background_color", background_color);
- get_text_editor()->add_theme_color_override("completion_background_color", completion_background_color);
- get_text_editor()->add_theme_color_override("completion_selected_color", completion_selected_color);
- get_text_editor()->add_theme_color_override("completion_existing_color", completion_existing_color);
- get_text_editor()->add_theme_color_override("completion_scroll_color", completion_scroll_color);
- get_text_editor()->add_theme_color_override("completion_font_color", completion_font_color);
- get_text_editor()->add_theme_color_override("font_color", text_color);
- get_text_editor()->add_theme_color_override("line_number_color", line_number_color);
- get_text_editor()->add_theme_color_override("caret_color", caret_color);
- get_text_editor()->add_theme_color_override("caret_background_color", caret_background_color);
- get_text_editor()->add_theme_color_override("font_selected_color", text_selected_color);
- get_text_editor()->add_theme_color_override("selection_color", selection_color);
- get_text_editor()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
- get_text_editor()->add_theme_color_override("current_line_color", current_line_color);
- get_text_editor()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
- get_text_editor()->add_theme_color_override("word_highlighted_color", word_highlighted_color);
- get_text_editor()->add_theme_color_override("mark_color", mark_color);
- get_text_editor()->add_theme_color_override("bookmark_color", bookmark_color);
- get_text_editor()->add_theme_color_override("breakpoint_color", breakpoint_color);
- get_text_editor()->add_theme_color_override("executing_line_color", executing_line_color);
- get_text_editor()->add_theme_color_override("code_folding_color", code_folding_color);
- get_text_editor()->add_theme_color_override("search_result_color", search_result_color);
- get_text_editor()->add_theme_color_override("search_result_border_color", search_result_border_color);
+ CodeEdit *text_editor = get_text_editor();
+ Color updated_marked_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
+ if (updated_marked_line_color != marked_line_color) {
+ for (int i = 0; i < text_editor->get_line_count(); i++) {
+ if (text_editor->get_line_background_color(i) == marked_line_color) {
+ text_editor->set_line_background_color(i, updated_marked_line_color);
+ }
+ }
+ marked_line_color = updated_marked_line_color;
+ }
syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color"));
syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color"));
@@ -231,13 +194,13 @@ void ShaderTextEditor::_validate_script() {
set_error(error_text);
set_error_pos(sl.get_error_line() - 1, 0);
for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
- get_text_editor()->set_line_as_marked(i, false);
+ get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0));
}
- get_text_editor()->set_line_as_marked(sl.get_error_line() - 1, true);
+ get_text_editor()->set_line_background_color(sl.get_error_line() - 1, marked_line_color);
} else {
for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
- get_text_editor()->set_line_as_marked(i, false);
+ get_text_editor()->set_line_background_color(i, Color(0, 0, 0, 0));
}
set_error("");
}
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index 731c0a5b7e..28e993027a 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -44,6 +44,8 @@
class ShaderTextEditor : public CodeTextEditor {
GDCLASS(ShaderTextEditor, CodeTextEditor);
+ Color marked_line_color = Color(1, 1, 1);
+
Ref<CodeHighlighter> syntax_highlighter;
Ref<Shader> shader;
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index e6fb2710ae..1edcbd2cc9 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -59,58 +59,7 @@ void TextEditor::_change_syntax_highlighter(int p_idx) {
}
void TextEditor::_load_theme_settings() {
- CodeEdit *text_edit = code_editor->get_text_editor();
- text_edit->get_syntax_highlighter()->update_cache();
-
- Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
- Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
- Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
- Color completion_existing_color = EDITOR_GET("text_editor/highlighting/completion_existing_color");
- Color completion_scroll_color = EDITOR_GET("text_editor/highlighting/completion_scroll_color");
- Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
- Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
- Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
- Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
- Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
- Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
- Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
- Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
- Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
- Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
- Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
- Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
- Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
- Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
- Color executing_line_color = EDITOR_GET("text_editor/highlighting/executing_line_color");
- Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
- Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
- Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
-
- text_edit->add_theme_color_override("background_color", background_color);
- text_edit->add_theme_color_override("completion_background_color", completion_background_color);
- text_edit->add_theme_color_override("completion_selected_color", completion_selected_color);
- text_edit->add_theme_color_override("completion_existing_color", completion_existing_color);
- text_edit->add_theme_color_override("completion_scroll_color", completion_scroll_color);
- text_edit->add_theme_color_override("completion_font_color", completion_font_color);
- text_edit->add_theme_color_override("font_color", text_color);
- text_edit->add_theme_color_override("line_number_color", line_number_color);
- text_edit->add_theme_color_override("caret_color", caret_color);
- text_edit->add_theme_color_override("caret_background_color", caret_background_color);
- text_edit->add_theme_color_override("font_selected_color", text_selected_color);
- text_edit->add_theme_color_override("selection_color", selection_color);
- text_edit->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
- text_edit->add_theme_color_override("current_line_color", current_line_color);
- text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
- text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
- text_edit->add_theme_color_override("breakpoint_color", breakpoint_color);
- text_edit->add_theme_color_override("executing_line_color", executing_line_color);
- text_edit->add_theme_color_override("mark_color", mark_color);
- text_edit->add_theme_color_override("bookmark_color", bookmark_color);
- text_edit->add_theme_color_override("code_folding_color", code_folding_color);
- text_edit->add_theme_color_override("search_result_color", search_result_color);
- text_edit->add_theme_color_override("search_result_border_color", search_result_border_color);
-
- text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
+ code_editor->get_text_editor()->get_syntax_highlighter()->update_cache();
}
String TextEditor::get_name() {
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index d2665a3a2b..61457e3e59 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -113,7 +113,22 @@ void TileDataPositionEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform
ERR_FAIL_COND(value.get_type() != Variant::VECTOR2I && value.get_type() != Variant::VECTOR2);
Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon("EditorPosition", "EditorIcons");
- p_canvas_item->draw_texture(position_icon, p_transform.get_origin() + Vector2(value) - position_icon->get_size() / 2);
+ p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(value)) - position_icon->get_size() / 2);
+}
+
+void TileDataYSortEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
+ TileData *tile_data = _get_tile_data(p_tile_set, p_atlas_source_id, p_atlas_coords, p_alternative_tile);
+ ERR_FAIL_COND(!tile_data);
+
+ bool valid;
+ Variant value = tile_data->get(p_property, &valid);
+ if (!valid) {
+ return;
+ }
+ ERR_FAIL_COND(value.get_type() != Variant::INT);
+
+ Ref<Texture2D> position_icon = TileSetEditor::get_singleton()->get_theme_icon("EditorPosition", "EditorIcons");
+ p_canvas_item->draw_texture(position_icon, p_transform.xform(Vector2(0, value)) - position_icon->get_size() / 2);
}
void TileDataOcclusionShapeEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) {
diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h
index f4f9c25157..b82189e1ee 100644
--- a/editor/plugins/tiles/tile_data_editors.h
+++ b/editor/plugins/tiles/tile_data_editors.h
@@ -79,6 +79,13 @@ public:
virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
};
+class TileDataYSortEditor : public TileDataEditor {
+ GDCLASS(TileDataYSortEditor, TileDataEditor);
+
+public:
+ virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileSet *p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, String p_property) override;
+};
+
class TileDataOcclusionShapeEditor : public TileDataEditor {
GDCLASS(TileDataOcclusionShapeEditor, TileDataEditor);
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 05ebe408a5..6078c986cb 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -298,6 +298,9 @@ void TileSetEditor::_notification(int p_what) {
break;
case NOTIFICATION_INTERNAL_PROCESS:
if (tile_set_changed_needs_update) {
+ if (tile_set.is_valid()) {
+ tile_set->set_edited(true);
+ }
_update_atlas_sources_list();
tile_set_changed_needs_update = false;
}
@@ -445,7 +448,7 @@ TileDataEditor *TileSetEditor::get_tile_data_editor(String p_property) {
} else if (p_property == "probability") {
return tile_data_float_editor;
} else if (p_property == "y_sort_origin") {
- return tile_data_position_editor;
+ return tile_data_y_sort_editor;
} else if (p_property == "texture_offset") {
return tile_data_texture_offset_editor;
} else if (components.size() >= 1 && components[0].begins_with("occlusion_layer_")) {
@@ -575,7 +578,7 @@ TileSetEditor::~TileSetEditor() {
// Delete tile data editors.
memdelete(tile_data_texture_offset_editor);
- memdelete(tile_data_position_editor);
+ memdelete(tile_data_y_sort_editor);
memdelete(tile_data_integer_editor);
memdelete(tile_data_float_editor);
memdelete(tile_data_occlusion_shape_editor);
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index d508c04319..f584c043cc 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -56,7 +56,7 @@ private:
// List of tile data editors.
TileDataTextureOffsetEditor *tile_data_texture_offset_editor = memnew(TileDataTextureOffsetEditor);
- TileDataPositionEditor *tile_data_position_editor = memnew(TileDataPositionEditor);
+ TileDataYSortEditor *tile_data_y_sort_editor = memnew(TileDataYSortEditor);
TileDataIntegerEditor *tile_data_integer_editor = memnew(TileDataIntegerEditor);
TileDataFloatEditor *tile_data_float_editor = memnew(TileDataFloatEditor);
TileDataOcclusionShapeEditor *tile_data_occlusion_shape_editor = memnew(TileDataOcclusionShapeEditor);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 18a1e7f693..1225b7dd1f 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -3429,10 +3429,11 @@ void VisualShaderEditor::_update_preview() {
Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type);
for (int i = 0; i < preview_text->get_line_count(); i++) {
- preview_text->set_line_as_marked(i, false);
+ preview_text->set_line_background_color(i, Color(0, 0, 0, 0));
}
if (err != OK) {
- preview_text->set_line_as_marked(sl.get_error_line() - 1, true);
+ Color error_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
+ preview_text->set_line_background_color(sl.get_error_line() - 1, error_line_color);
error_text->set_visible(true);
String text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
diff --git a/modules/meshoptimizer/register_types.cpp b/modules/meshoptimizer/register_types.cpp
index a03310f518..77cc82a4e2 100644
--- a/modules/meshoptimizer/register_types.cpp
+++ b/modules/meshoptimizer/register_types.cpp
@@ -35,6 +35,7 @@
void register_meshoptimizer_types() {
SurfaceTool::optimize_vertex_cache_func = meshopt_optimizeVertexCache;
SurfaceTool::simplify_func = meshopt_simplify;
+ SurfaceTool::simplify_with_attrib_func = meshopt_simplifyWithAttributes;
SurfaceTool::simplify_scale_func = meshopt_simplifyScale;
SurfaceTool::simplify_sloppy_func = meshopt_simplifySloppy;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 6279ea1ace..ebfe70aa82 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -519,7 +519,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Perpendicular()
+ public Vector2 Orthogonal()
{
return new Vector2(y, -x);
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
index 8dd9ab2f0d..f605ba8fd0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
@@ -248,13 +248,13 @@ namespace Godot
}
/// <summary>
- /// Returns a vector rotated 90 degrees counter-clockwise
+ /// Returns a perpendicular vector rotated 90 degrees counter-clockwise
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Perpendicular()
+ public Vector2i Orthogonal()
{
- return new Vector2(y, -x);
+ return new Vector2i(y, -x);
}
// Constants
diff --git a/platform/uwp/app.cpp b/platform/uwp/app.cpp
index b7e4361831..9d6ff10483 100644
--- a/platform/uwp/app.cpp
+++ b/platform/uwp/app.cpp
@@ -383,7 +383,7 @@ void App::key_event(Windows::UI::Core::CoreWindow ^ sender, bool p_pressed, Wind
ke.type = OS_UWP::KeyEvent::MessageType::KEY_EVENT_MESSAGE;
ke.unicode = 0;
ke.keycode = KeyMappingWindows::get_keysym((unsigned int)key_args->VirtualKey);
- ke.physical_keycode = KeyMappingWindows::get_scansym((unsigned int)key_args->KeyStatus.ScanCode);
+ ke.physical_keycode = KeyMappingWindows::get_scansym((unsigned int)key_args->KeyStatus.ScanCode, key_args->KeyStatus.IsExtendedKey);
ke.echo = (!p_pressed && !key_args->KeyStatus.IsKeyReleased) || (p_pressed && key_args->KeyStatus.WasKeyDown);
} else {
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index 914b3ad816..cba769a8f8 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -215,6 +215,11 @@ void CollisionObject3D::_shape_changed(const Ref<Shape3D> &p_shape) {
}
void CollisionObject3D::_update_debug_shapes() {
+ if (!is_inside_tree()) {
+ debug_shapes_to_update.clear();
+ return;
+ }
+
for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) {
if (shapes.has(shapedata_idx->get())) {
ShapeData &shapedata = shapes[shapedata_idx->get()];
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index e305c6210d..053af39701 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -253,7 +253,6 @@ void TextEdit::Text::set(int p_line, const String &p_text, const Vector<Vector2i
void TextEdit::Text::insert(int p_at, const String &p_text, const Vector<Vector2i> &p_bidi_override) {
Line line;
line.gutters.resize(gutter_count);
- line.marked = false;
line.hidden = false;
line.data = p_text;
line.bidi_override = p_bidi_override;
@@ -867,6 +866,8 @@ void TextEdit::_notification(int p_what) {
Dictionary color_map = _get_line_syntax_highlighting(minimap_line);
+ Color line_background_color = text.get_line_background_color(minimap_line);
+ line_background_color.a *= 0.6;
Color current_color = cache.font_color;
if (readonly) {
current_color = cache.font_readonly_color;
@@ -901,6 +902,12 @@ void TextEdit::_notification(int p_what) {
} else {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, cache.minimap_width, 2), cache.current_line_color);
}
+ } else if (line_background_color != Color(0, 0, 0, 0)) {
+ if (rtl) {
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - cache.minimap_width, i * 3, cache.minimap_width, 2), line_background_color);
+ } else {
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, cache.minimap_width, 2), line_background_color);
+ }
}
Color previous_color;
@@ -1048,11 +1055,11 @@ void TextEdit::_notification(int p_what) {
break;
}
- if (text.is_marked(line)) {
+ if (text.get_line_background_color(line) != Color(0, 0, 0, 0)) {
if (rtl) {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), cache.mark_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line));
} else {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, row_height), cache.mark_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line));
}
}
@@ -4789,7 +4796,6 @@ void TextEdit::_update_caches() {
cache.font_selected_color = get_theme_color("font_selected_color");
cache.font_readonly_color = get_theme_color("font_readonly_color");
cache.selection_color = get_theme_color("selection_color");
- cache.mark_color = get_theme_color("mark_color");
cache.current_line_color = get_theme_color("current_line_color");
cache.line_length_guideline_color = get_theme_color("line_length_guideline_color");
cache.code_folding_color = get_theme_color("code_folding_color");
@@ -5019,6 +5025,18 @@ bool TextEdit::is_line_gutter_clickable(int p_line, int p_gutter) const {
return text.is_line_gutter_clickable(p_line, p_gutter);
}
+// Line style
+void TextEdit::set_line_background_color(int p_line, const Color &p_color) {
+ ERR_FAIL_INDEX(p_line, text.size());
+ text.set_line_background_color(p_line, p_color);
+ update();
+}
+
+Color TextEdit::get_line_background_color(int p_line) {
+ ERR_FAIL_INDEX_V(p_line, text.size(), Color());
+ return text.get_line_background_color(p_line);
+}
+
void TextEdit::add_keyword(const String &p_keyword) {
keywords.insert(p_keyword);
}
@@ -5437,12 +5455,6 @@ void TextEdit::_text_changed_emit() {
text_changed_dirty = false;
}
-void TextEdit::set_line_as_marked(int p_line, bool p_marked) {
- ERR_FAIL_INDEX(p_line, text.size());
- text.set_marked(p_line, p_marked);
- update();
-}
-
void TextEdit::set_line_as_hidden(int p_line, bool p_hidden) {
ERR_FAIL_INDEX(p_line, text.size());
if (is_hiding_enabled() || !p_hidden) {
@@ -6980,6 +6992,10 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_line_gutter_clickable", "line", "gutter", "clickable"), &TextEdit::set_line_gutter_clickable);
ClassDB::bind_method(D_METHOD("is_line_gutter_clickable", "line", "gutter"), &TextEdit::is_line_gutter_clickable);
+ // Line style
+ ClassDB::bind_method(D_METHOD("set_line_background_color", "line", "color"), &TextEdit::set_line_background_color);
+ ClassDB::bind_method(D_METHOD("get_line_background_color", "line"), &TextEdit::get_line_background_color);
+
ClassDB::bind_method(D_METHOD("set_highlight_current_line", "enabled"), &TextEdit::set_highlight_current_line);
ClassDB::bind_method(D_METHOD("is_highlight_current_line_enabled"), &TextEdit::is_highlight_current_line_enabled);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index b0c7314c65..93214a5197 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -92,7 +92,7 @@ private:
Vector<Vector2i> bidi_override;
Ref<TextParagraph> data_buf;
- bool marked = false;
+ Color background_color = Color(0, 0, 0, 0);
bool hidden = false;
Line() {
@@ -129,12 +129,11 @@ private:
void set_width(float p_width);
int get_line_wrap_amount(int p_line) const;
+
Vector<Vector2i> get_line_wrap_ranges(int p_line) const;
const Ref<TextParagraph> get_line_data(int p_line) const;
void set(int p_line, const String &p_text, const Vector<Vector2i> &p_bidi_override);
- void set_marked(int p_line, bool p_marked) { text.write[p_line].marked = p_marked; }
- bool is_marked(int p_line) const { return text[p_line].marked; }
void set_hidden(int p_line, bool p_hidden) { text.write[p_line].hidden = p_hidden; }
bool is_hidden(int p_line) const { return text[p_line].hidden; }
void insert(int p_at, const String &p_text, const Vector<Vector2i> &p_bidi_override);
@@ -167,6 +166,10 @@ private:
void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable) { text.write[p_line].gutters.write[p_gutter].clickable = p_clickable; }
bool is_line_gutter_clickable(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].clickable; }
+
+ /* Line style. */
+ void set_line_background_color(int p_line, const Color &p_color) { text.write[p_line].background_color = p_color; }
+ const Color get_line_background_color(int p_line) const { return text[p_line].background_color; }
};
struct Cursor {
@@ -484,7 +487,6 @@ protected:
Color font_selected_color;
Color font_readonly_color;
Color selection_color;
- Color mark_color;
Color code_folding_color;
Color current_line_color;
Color line_length_guideline_color;
@@ -561,6 +563,10 @@ public:
void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable);
bool is_line_gutter_clickable(int p_line, int p_gutter) const;
+ // Line style
+ void set_line_background_color(int p_line, const Color &p_color);
+ Color get_line_background_color(int p_line);
+
enum MenuItems {
MENU_CUT,
MENU_COPY,
@@ -637,7 +643,6 @@ public:
void insert_text_at_cursor(const String &p_text);
void insert_at(const String &p_text, int at);
int get_line_count() const;
- void set_line_as_marked(int p_line, bool p_marked);
void set_line_as_hidden(int p_line, bool p_hidden);
bool is_line_hidden(int p_line) const;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index b671ee4644..6e67daf15f 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -451,7 +451,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_readonly_color", "TextEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
theme->set_color("font_outline_color", "TextEdit", Color(1, 1, 1));
theme->set_color("selection_color", "TextEdit", control_selection_color);
- theme->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4));
theme->set_color("code_folding_color", "TextEdit", Color(0.8, 0.8, 0.8, 0.8));
theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8));
theme->set_color("caret_color", "TextEdit", control_font_color);
@@ -494,7 +493,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_readonly_color", "CodeEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
theme->set_color("font_outline_color", "CodeEdit", Color(1, 1, 1));
theme->set_color("selection_color", "CodeEdit", control_selection_color);
- theme->set_color("mark_color", "CodeEdit", Color(1.0, 0.4, 0.4, 0.4));
theme->set_color("bookmark_color", "CodeEdit", Color(0.5, 0.64, 1, 0.8));
theme->set_color("breakpoint_color", "CodeEdit", Color(0.9, 0.29, 0.3));
theme->set_color("executing_line_color", "CodeEdit", Color(0.98, 0.89, 0.27));
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index ff682a40f4..f2143e683d 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -35,6 +35,7 @@
SurfaceTool::OptimizeVertexCacheFunc SurfaceTool::optimize_vertex_cache_func = nullptr;
SurfaceTool::SimplifyFunc SurfaceTool::simplify_func = nullptr;
+SurfaceTool::SimplifyWithAttribFunc SurfaceTool::simplify_with_attrib_func = nullptr;
SurfaceTool::SimplifyScaleFunc SurfaceTool::simplify_scale_func = nullptr;
SurfaceTool::SimplifySloppyFunc SurfaceTool::simplify_sloppy_func = nullptr;
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index 28addf2245..f5f3a95b14 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -78,6 +78,8 @@ public:
static OptimizeVertexCacheFunc optimize_vertex_cache_func;
typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_error);
static SimplifyFunc simplify_func;
+ typedef size_t (*SimplifyWithAttribFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float *result_error, const float *attributes, const float *attribute_weights, size_t attribute_count);
+ static SimplifyWithAttribFunc simplify_with_attrib_func;
typedef float (*SimplifyScaleFunc)(const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
static SimplifyScaleFunc simplify_scale_func;
typedef size_t (*SimplifySloppyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *out_result_error);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 3f6f5bb5fe..9db7acb263 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -2351,11 +2351,11 @@ int TileData::get_z_index() const {
return z_index;
}
-void TileData::set_y_sort_origin(Vector2i p_y_sort_origin) {
+void TileData::set_y_sort_origin(int p_y_sort_origin) {
y_sort_origin = p_y_sort_origin;
emit_signal("changed");
}
-Vector2i TileData::get_y_sort_origin() const {
+int TileData::get_y_sort_origin() const {
return y_sort_origin;
}
@@ -3020,7 +3020,7 @@ void TileData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "texture_offset"), "set_texture_offset", "get_texture_offset");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index"), "set_z_index", "get_z_index");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "y_sort_origin"), "set_y_sort_origin", "get_y_sort_origin");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "y_sort_origin"), "set_y_sort_origin", "get_y_sort_origin");
ADD_GROUP("Terrains", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "terrain_set"), "set_terrain_set", "get_terrain_set");
@@ -3866,6 +3866,12 @@ void TileSetPluginAtlasRendering::tilemap_notification(TileMap *p_tile_map, int
}
}
} break;
+ case CanvasItem::NOTIFICATION_DRAW: {
+ Ref<TileSet> tile_set = p_tile_map->get_tileset();
+ if (tile_set.is_valid()) {
+ RenderingServer::get_singleton()->canvas_item_set_sort_children_by_y(p_tile_map->get_canvas_item(), tile_set->is_y_sorting());
+ }
+ } break;
}
}
@@ -3978,7 +3984,11 @@ void TileSetPluginAtlasRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
int z_index = tile_data->get_z_index();
// Quandrant pos.
- Vector2 position = p_tile_map->map_to_world(q.coords * p_tile_map->get_effective_quadrant_size()) - tile_set->get_tile_size() / 2;
+ Vector2 position = p_tile_map->map_to_world(q.coords * p_tile_map->get_effective_quadrant_size());
+ if (tile_set->is_y_sorting()) {
+ // When Y-sorting, the quandrant size is sure to be 1, we can thus offset the CanvasItem.
+ position.y += tile_data->get_y_sort_origin();
+ }
// --- CanvasItems ---
// Create two canvas items, for rendering and debug.
@@ -3986,16 +3996,18 @@ void TileSetPluginAtlasRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
// Check if the material or the z_index changed.
if (prev_canvas_item == RID() || prev_material != mat || prev_z_index != z_index) {
+ // If so, create a new CanvasItem.
canvas_item = rs->canvas_item_create();
if (mat.is_valid()) {
rs->canvas_item_set_material(canvas_item, mat->get_rid());
}
rs->canvas_item_set_parent(canvas_item, p_tile_map->get_canvas_item());
rs->canvas_item_set_use_parent_material(canvas_item, p_tile_map->get_use_parent_material() || p_tile_map->get_material().is_valid());
+
Transform2D xform;
xform.set_origin(position);
-
rs->canvas_item_set_transform(canvas_item, xform);
+
rs->canvas_item_set_light_mask(canvas_item, p_tile_map->get_light_mask());
rs->canvas_item_set_z_index(canvas_item, z_index);
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index ae80299d85..6cf4198f30 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -504,7 +504,7 @@ private:
Ref<ShaderMaterial> material = Ref<ShaderMaterial>();
Color modulate = Color(1.0, 1.0, 1.0, 1.0);
int z_index = 0;
- Vector2i y_sort_origin = Vector2i();
+ int y_sort_origin = 0;
Vector<Ref<OccluderPolygon2D>> occluders;
// Physics
@@ -563,8 +563,8 @@ public:
Color get_modulate() const;
void set_z_index(int p_z_index);
int get_z_index() const;
- void set_y_sort_origin(Vector2i p_y_sort_origin);
- Vector2i get_y_sort_origin() const;
+ void set_y_sort_origin(int p_y_sort_origin);
+ int get_y_sort_origin() const;
void set_occluder(int p_layer_id, Ref<OccluderPolygon2D> p_occluder_polygon);
Ref<OccluderPolygon2D> get_occluder(int p_layer_id) const;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 7cedd1a2cb..d3599fd195 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -375,6 +375,9 @@ Files extracted from upstream repository:
- All files in `src/`.
- `LICENSE.md`.
+An [experimental upstream feature](https://github.com/zeux/meshoptimizer/tree/simplify-attr),
+has been backported, see patch in `patches` directory.
+
## miniupnpc
diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h
index fe8d349731..e44b99ce52 100644
--- a/thirdparty/meshoptimizer/meshoptimizer.h
+++ b/thirdparty/meshoptimizer/meshoptimizer.h
@@ -299,6 +299,11 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t ver
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error);
/**
+ * Experimental: Mesh simplifier with attribute metric; attributes follow xyz position data atm (vertex data must contain 3 + attribute_count floats per vertex)
+ */
+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count);
+
+/**
* Experimental: Mesh simplifier (sloppy)
* Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance
* The algorithm doesn't preserve mesh topology but can stop short of the target goal based on target error.
diff --git a/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch
new file mode 100644
index 0000000000..cf648b0da3
--- /dev/null
+++ b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch
@@ -0,0 +1,262 @@
+diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h
+index fe8d349731..e44b99ce52 100644
+--- a/thirdparty/meshoptimizer/meshoptimizer.h
++++ b/thirdparty/meshoptimizer/meshoptimizer.h
+@@ -298,6 +298,11 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t ver
+ */
+ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error);
+
++/**
++ * Experimental: Mesh simplifier with attribute metric; attributes follow xyz position data atm (vertex data must contain 3 + attribute_count floats per vertex)
++ */
++MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count);
++
+ /**
+ * Experimental: Mesh simplifier (sloppy)
+ * Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance
+diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
+index b2cb589462..059cabb055 100644
+--- a/thirdparty/meshoptimizer/simplifier.cpp
++++ b/thirdparty/meshoptimizer/simplifier.cpp
+@@ -20,6 +20,8 @@
+ #define TRACESTATS(i) (void)0
+ #endif
+
++#define ATTRIBUTES 8
++
+ // This work is based on:
+ // Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
+ // Michael Garland. Quadric-based polygonal surface simplification. 1999
+@@ -358,6 +360,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
+ struct Vector3
+ {
+ float x, y, z;
++
++#if ATTRIBUTES
++ float a[ATTRIBUTES];
++#endif
+ };
+
+ static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride)
+@@ -414,6 +420,13 @@ struct Quadric
+ float a10, a20, a21;
+ float b0, b1, b2, c;
+ float w;
++
++#if ATTRIBUTES
++ float gx[ATTRIBUTES];
++ float gy[ATTRIBUTES];
++ float gz[ATTRIBUTES];
++ float gw[ATTRIBUTES];
++#endif
+ };
+
+ struct Collapse
+@@ -456,6 +469,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R)
+ Q.b2 += R.b2;
+ Q.c += R.c;
+ Q.w += R.w;
++
++#if ATTRIBUTES
++ for (int k = 0; k < ATTRIBUTES; ++k)
++ {
++ Q.gx[k] += R.gx[k];
++ Q.gy[k] += R.gy[k];
++ Q.gz[k] += R.gz[k];
++ Q.gw[k] += R.gw[k];
++ }
++#endif
+ }
+
+ static float quadricError(const Quadric& Q, const Vector3& v)
+@@ -481,6 +504,17 @@ static float quadricError(const Quadric& Q, const Vector3& v)
+ r += ry * v.y;
+ r += rz * v.z;
+
++#if ATTRIBUTES
++ // see quadricUpdateAttributes for general derivation; here we need to add the parts of (eval(pos) - attr)^2 that depend on attr
++ for (int k = 0; k < ATTRIBUTES; ++k)
++ {
++ float a = v.a[k];
++
++ r += a * a * Q.w;
++ r -= 2 * a * (v.x * Q.gx[k] + v.y * Q.gy[k] + v.z * Q.gz[k] + Q.gw[k]);
++ }
++#endif
++
+ float s = Q.w == 0.f ? 0.f : 1.f / Q.w;
+
+ return fabsf(r) * s;
+@@ -504,6 +538,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo
+ Q.b2 = c * dw;
+ Q.c = d * dw;
+ Q.w = w;
++
++#if ATTRIBUTES
++ memset(Q.gx, 0, sizeof(Q.gx));
++ memset(Q.gy, 0, sizeof(Q.gy));
++ memset(Q.gz, 0, sizeof(Q.gz));
++ memset(Q.gw, 0, sizeof(Q.gw));
++#endif
+ }
+
+ static void quadricFromPoint(Quadric& Q, float x, float y, float z, float w)
+@@ -556,6 +597,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3
+ quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight);
+ }
+
++#if ATTRIBUTES
++static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float w)
++{
++ // for each attribute we want to encode the following function into the quadric:
++ // (eval(pos) - attr)^2
++ // where eval(pos) interpolates attribute across the triangle like so:
++ // eval(pos) = pos.x * gx + pos.y * gy + pos.z * gz + gw
++ // where gx/gy/gz/gw are gradients
++ Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z};
++ Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z};
++
++ // we compute gradients using barycentric coordinates; barycentric coordinates can be computed as follows:
++ // v = (d11 * d20 - d01 * d21) / denom
++ // w = (d00 * d21 - d01 * d20) / denom
++ // u = 1 - v - w
++ // here v0, v1 are triangle edge vectors, v2 is a vector from point to triangle corner, and dij = dot(vi, vj)
++ const Vector3& v0 = p10;
++ const Vector3& v1 = p20;
++ float d00 = v0.x * v0.x + v0.y * v0.y + v0.z * v0.z;
++ float d01 = v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
++ float d11 = v1.x * v1.x + v1.y * v1.y + v1.z * v1.z;
++ float denom = d00 * d11 - d01 * d01;
++ float denomr = denom == 0 ? 0.f : 1.f / denom;
++
++ // precompute gradient factors
++ // these are derived by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w and factoring out common factors that are shared between attributes
++ float gx1 = (d11 * v0.x - d01 * v1.x) * denomr;
++ float gx2 = (d00 * v1.x - d01 * v0.x) * denomr;
++ float gy1 = (d11 * v0.y - d01 * v1.y) * denomr;
++ float gy2 = (d00 * v1.y - d01 * v0.y) * denomr;
++ float gz1 = (d11 * v0.z - d01 * v1.z) * denomr;
++ float gz2 = (d00 * v1.z - d01 * v0.z) * denomr;
++
++ for (int k = 0; k < ATTRIBUTES; ++k)
++ {
++ float a0 = p0.a[k], a1 = p1.a[k], a2 = p2.a[k];
++
++ // compute gradient of eval(pos) for x/y/z/w
++ // the formulas below are obtained by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w
++ float gx = gx1 * (a1 - a0) + gx2 * (a2 - a0);
++ float gy = gy1 * (a1 - a0) + gy2 * (a2 - a0);
++ float gz = gz1 * (a1 - a0) + gz2 * (a2 - a0);
++ float gw = a0 - p0.x * gx - p0.y * gy - p0.z * gz;
++
++ // quadric encodes (eval(pos)-attr)^2; this means that the resulting expansion needs to compute, for example, pos.x * pos.y * K
++ // since quadrics already encode factors for pos.x * pos.y, we can accumulate almost everything in basic quadric fields
++ Q.a00 += w * (gx * gx);
++ Q.a11 += w * (gy * gy);
++ Q.a22 += w * (gz * gz);
++
++ Q.a10 += w * (gy * gx);
++ Q.a20 += w * (gz * gx);
++ Q.a21 += w * (gz * gy);
++
++ Q.b0 += w * (gx * gw);
++ Q.b1 += w * (gy * gw);
++ Q.b2 += w * (gz * gw);
++
++ Q.c += w * (gw * gw);
++
++ // the only remaining sum components are ones that depend on attr; these will be addded during error evaluation, see quadricError
++ Q.gx[k] = w * gx;
++ Q.gy[k] = w * gy;
++ Q.gz[k] = w * gz;
++ Q.gw[k] = w * gw;
++
++#if TRACE > 2
++ printf("attr%d: %e %e %e\n",
++ k,
++ (gx * p0.x + gy * p0.y + gz * p0.z + gw - a0),
++ (gx * p1.x + gy * p1.y + gz * p1.z + gw - a1),
++ (gx * p2.x + gy * p2.y + gz * p2.z + gw - a2)
++ );
++#endif
++ }
++}
++#endif
++
+ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap)
+ {
+ for (size_t i = 0; i < index_count; i += 3)
+@@ -567,6 +686,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
+ Quadric Q;
+ quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f);
+
++#if ATTRIBUTES
++ quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w);
++#endif
+ quadricAdd(vertex_quadrics[remap[i0]], Q);
+ quadricAdd(vertex_quadrics[remap[i1]], Q);
+ quadricAdd(vertex_quadrics[remap[i2]], Q);
+@@ -1259,13 +1381,19 @@ unsigned int* meshopt_simplifyDebugLoopBack = 0;
+ #endif
+
+ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error)
++{
++ return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, out_result_error, 0, 0, 0);
++}
++
++size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count)
+ {
+ using namespace meshopt;
+
+ assert(index_count % 3 == 0);
+- assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
+- assert(vertex_positions_stride % sizeof(float) == 0);
++ assert(vertex_stride > 0 && vertex_stride <= 256);
++ assert(vertex_stride % sizeof(float) == 0);
+ assert(target_index_count <= index_count);
++ assert(attribute_count <= ATTRIBUTES);
+
+ meshopt_Allocator allocator;
+
+@@ -1279,7 +1407,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+ // build position remap that maps each vertex to the one with identical position
+ unsigned int* remap = allocator.allocate<unsigned int>(vertex_count);
+ unsigned int* wedge = allocator.allocate<unsigned int>(vertex_count);
+- buildPositionRemap(remap, wedge, vertex_positions_data, vertex_count, vertex_positions_stride, allocator);
++ buildPositionRemap(remap, wedge, vertex_data, vertex_count, vertex_stride, allocator);
+
+ // classify vertices; vertex kind determines collapse rules, see kCanCollapse
+ unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count);
+@@ -1303,7 +1431,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+ #endif
+
+ Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count);
+- rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride);
++ rescalePositions(vertex_positions, vertex_data, vertex_count, vertex_stride);
++
++#if ATTRIBUTES
++ for (size_t i = 0; i < vertex_count; ++i)
++ {
++ memset(vertex_positions[i].a, 0, sizeof(vertex_positions[i].a));
++
++ for (size_t k = 0; k < attribute_count; ++k)
++ {
++ float a = attributes[i * attribute_count + k];
++
++ vertex_positions[i].a[k] = a * attribute_weights[k];
++ }
++ }
++#endif
+
+ Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count);
+ memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
+@@ -1395,7 +1537,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+
+ // result_error is quadratic; we need to remap it back to linear
+ if (out_result_error)
++ {
+ *out_result_error = sqrtf(result_error);
++ }
+
+ return result_count;
+ }
diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
index b2cb589462..059cabb055 100644
--- a/thirdparty/meshoptimizer/simplifier.cpp
+++ b/thirdparty/meshoptimizer/simplifier.cpp
@@ -20,6 +20,8 @@
#define TRACESTATS(i) (void)0
#endif
+#define ATTRIBUTES 8
+
// This work is based on:
// Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
// Michael Garland. Quadric-based polygonal surface simplification. 1999
@@ -358,6 +360,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
struct Vector3
{
float x, y, z;
+
+#if ATTRIBUTES
+ float a[ATTRIBUTES];
+#endif
};
static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride)
@@ -414,6 +420,13 @@ struct Quadric
float a10, a20, a21;
float b0, b1, b2, c;
float w;
+
+#if ATTRIBUTES
+ float gx[ATTRIBUTES];
+ float gy[ATTRIBUTES];
+ float gz[ATTRIBUTES];
+ float gw[ATTRIBUTES];
+#endif
};
struct Collapse
@@ -456,6 +469,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R)
Q.b2 += R.b2;
Q.c += R.c;
Q.w += R.w;
+
+#if ATTRIBUTES
+ for (int k = 0; k < ATTRIBUTES; ++k)
+ {
+ Q.gx[k] += R.gx[k];
+ Q.gy[k] += R.gy[k];
+ Q.gz[k] += R.gz[k];
+ Q.gw[k] += R.gw[k];
+ }
+#endif
}
static float quadricError(const Quadric& Q, const Vector3& v)
@@ -481,6 +504,17 @@ static float quadricError(const Quadric& Q, const Vector3& v)
r += ry * v.y;
r += rz * v.z;
+#if ATTRIBUTES
+ // see quadricUpdateAttributes for general derivation; here we need to add the parts of (eval(pos) - attr)^2 that depend on attr
+ for (int k = 0; k < ATTRIBUTES; ++k)
+ {
+ float a = v.a[k];
+
+ r += a * a * Q.w;
+ r -= 2 * a * (v.x * Q.gx[k] + v.y * Q.gy[k] + v.z * Q.gz[k] + Q.gw[k]);
+ }
+#endif
+
float s = Q.w == 0.f ? 0.f : 1.f / Q.w;
return fabsf(r) * s;
@@ -504,6 +538,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo
Q.b2 = c * dw;
Q.c = d * dw;
Q.w = w;
+
+#if ATTRIBUTES
+ memset(Q.gx, 0, sizeof(Q.gx));
+ memset(Q.gy, 0, sizeof(Q.gy));
+ memset(Q.gz, 0, sizeof(Q.gz));
+ memset(Q.gw, 0, sizeof(Q.gw));
+#endif
}
static void quadricFromPoint(Quadric& Q, float x, float y, float z, float w)
@@ -556,6 +597,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3
quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight);
}
+#if ATTRIBUTES
+static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float w)
+{
+ // for each attribute we want to encode the following function into the quadric:
+ // (eval(pos) - attr)^2
+ // where eval(pos) interpolates attribute across the triangle like so:
+ // eval(pos) = pos.x * gx + pos.y * gy + pos.z * gz + gw
+ // where gx/gy/gz/gw are gradients
+ Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z};
+ Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z};
+
+ // we compute gradients using barycentric coordinates; barycentric coordinates can be computed as follows:
+ // v = (d11 * d20 - d01 * d21) / denom
+ // w = (d00 * d21 - d01 * d20) / denom
+ // u = 1 - v - w
+ // here v0, v1 are triangle edge vectors, v2 is a vector from point to triangle corner, and dij = dot(vi, vj)
+ const Vector3& v0 = p10;
+ const Vector3& v1 = p20;
+ float d00 = v0.x * v0.x + v0.y * v0.y + v0.z * v0.z;
+ float d01 = v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
+ float d11 = v1.x * v1.x + v1.y * v1.y + v1.z * v1.z;
+ float denom = d00 * d11 - d01 * d01;
+ float denomr = denom == 0 ? 0.f : 1.f / denom;
+
+ // precompute gradient factors
+ // these are derived by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w and factoring out common factors that are shared between attributes
+ float gx1 = (d11 * v0.x - d01 * v1.x) * denomr;
+ float gx2 = (d00 * v1.x - d01 * v0.x) * denomr;
+ float gy1 = (d11 * v0.y - d01 * v1.y) * denomr;
+ float gy2 = (d00 * v1.y - d01 * v0.y) * denomr;
+ float gz1 = (d11 * v0.z - d01 * v1.z) * denomr;
+ float gz2 = (d00 * v1.z - d01 * v0.z) * denomr;
+
+ for (int k = 0; k < ATTRIBUTES; ++k)
+ {
+ float a0 = p0.a[k], a1 = p1.a[k], a2 = p2.a[k];
+
+ // compute gradient of eval(pos) for x/y/z/w
+ // the formulas below are obtained by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w
+ float gx = gx1 * (a1 - a0) + gx2 * (a2 - a0);
+ float gy = gy1 * (a1 - a0) + gy2 * (a2 - a0);
+ float gz = gz1 * (a1 - a0) + gz2 * (a2 - a0);
+ float gw = a0 - p0.x * gx - p0.y * gy - p0.z * gz;
+
+ // quadric encodes (eval(pos)-attr)^2; this means that the resulting expansion needs to compute, for example, pos.x * pos.y * K
+ // since quadrics already encode factors for pos.x * pos.y, we can accumulate almost everything in basic quadric fields
+ Q.a00 += w * (gx * gx);
+ Q.a11 += w * (gy * gy);
+ Q.a22 += w * (gz * gz);
+
+ Q.a10 += w * (gy * gx);
+ Q.a20 += w * (gz * gx);
+ Q.a21 += w * (gz * gy);
+
+ Q.b0 += w * (gx * gw);
+ Q.b1 += w * (gy * gw);
+ Q.b2 += w * (gz * gw);
+
+ Q.c += w * (gw * gw);
+
+ // the only remaining sum components are ones that depend on attr; these will be addded during error evaluation, see quadricError
+ Q.gx[k] = w * gx;
+ Q.gy[k] = w * gy;
+ Q.gz[k] = w * gz;
+ Q.gw[k] = w * gw;
+
+#if TRACE > 2
+ printf("attr%d: %e %e %e\n",
+ k,
+ (gx * p0.x + gy * p0.y + gz * p0.z + gw - a0),
+ (gx * p1.x + gy * p1.y + gz * p1.z + gw - a1),
+ (gx * p2.x + gy * p2.y + gz * p2.z + gw - a2)
+ );
+#endif
+ }
+}
+#endif
+
static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap)
{
for (size_t i = 0; i < index_count; i += 3)
@@ -567,6 +686,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
Quadric Q;
quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f);
+#if ATTRIBUTES
+ quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w);
+#endif
quadricAdd(vertex_quadrics[remap[i0]], Q);
quadricAdd(vertex_quadrics[remap[i1]], Q);
quadricAdd(vertex_quadrics[remap[i2]], Q);
@@ -1260,12 +1382,18 @@ unsigned int* meshopt_simplifyDebugLoopBack = 0;
size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error)
{
+ return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, out_result_error, 0, 0, 0);
+}
+
+size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count)
+{
using namespace meshopt;
assert(index_count % 3 == 0);
- assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
- assert(vertex_positions_stride % sizeof(float) == 0);
+ assert(vertex_stride > 0 && vertex_stride <= 256);
+ assert(vertex_stride % sizeof(float) == 0);
assert(target_index_count <= index_count);
+ assert(attribute_count <= ATTRIBUTES);
meshopt_Allocator allocator;
@@ -1279,7 +1407,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
// build position remap that maps each vertex to the one with identical position
unsigned int* remap = allocator.allocate<unsigned int>(vertex_count);
unsigned int* wedge = allocator.allocate<unsigned int>(vertex_count);
- buildPositionRemap(remap, wedge, vertex_positions_data, vertex_count, vertex_positions_stride, allocator);
+ buildPositionRemap(remap, wedge, vertex_data, vertex_count, vertex_stride, allocator);
// classify vertices; vertex kind determines collapse rules, see kCanCollapse
unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count);
@@ -1303,7 +1431,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
#endif
Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count);
- rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride);
+ rescalePositions(vertex_positions, vertex_data, vertex_count, vertex_stride);
+
+#if ATTRIBUTES
+ for (size_t i = 0; i < vertex_count; ++i)
+ {
+ memset(vertex_positions[i].a, 0, sizeof(vertex_positions[i].a));
+
+ for (size_t k = 0; k < attribute_count; ++k)
+ {
+ float a = attributes[i * attribute_count + k];
+
+ vertex_positions[i].a[k] = a * attribute_weights[k];
+ }
+ }
+#endif
Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count);
memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
@@ -1395,7 +1537,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
// result_error is quadratic; we need to remap it back to linear
if (out_result_error)
+ {
*out_result_error = sqrtf(result_error);
+ }
return result_count;
}