diff options
-rw-r--r-- | core/io/pck_packer.cpp | 3 | ||||
-rw-r--r-- | core/io/pck_packer.h | 2 | ||||
-rw-r--r-- | doc/classes/PCKPacker.xml | 4 | ||||
-rw-r--r-- | doc/classes/TextEdit.xml | 11 | ||||
-rw-r--r-- | scene/gui/code_edit.cpp | 20 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 88 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 3 | ||||
-rw-r--r-- | scene/resources/visual_shader.cpp | 1 | ||||
-rw-r--r-- | scene/resources/visual_shader_particle_nodes.cpp | 289 | ||||
-rw-r--r-- | scene/resources/visual_shader_particle_nodes.h | 14 | ||||
-rw-r--r-- | servers/rendering/renderer_scene_cull.cpp | 3 | ||||
-rw-r--r-- | servers/rendering/renderer_scene_cull.h | 15 | ||||
-rw-r--r-- | tests/core/io/test_pck_packer.h | 29 |
13 files changed, 342 insertions, 140 deletions
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index 806a95398f..8d75581342 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -47,13 +47,14 @@ static int _get_pad(int p_alignment, int p_n) { } void PCKPacker::_bind_methods() { - ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(0), DEFVAL(String()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false)); ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false)); } Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &p_key, bool p_encrypt_directory) { ERR_FAIL_COND_V_MSG((p_key.is_empty() || !p_key.is_valid_hex_number(false) || p_key.length() != 64), ERR_CANT_CREATE, "Invalid Encryption Key (must be 64 characters long)."); + ERR_FAIL_COND_V_MSG(p_alignment <= 0, ERR_CANT_CREATE, "Invalid alignment, must be greater then 0."); String _key = p_key.to_lower(); key.resize(32); diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h index 3d2ce8f240..bd8902a01d 100644 --- a/core/io/pck_packer.h +++ b/core/io/pck_packer.h @@ -58,7 +58,7 @@ class PCKPacker : public RefCounted { Vector<File> files; public: - Error pck_start(const String &p_file, int p_alignment = 0, const String &p_key = String(), bool p_encrypt_directory = false); + Error pck_start(const String &p_file, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false); Error add_file(const String &p_file, const String &p_src, bool p_encrypt = false); Error flush(bool p_verbose = false); diff --git a/doc/classes/PCKPacker.xml b/doc/classes/PCKPacker.xml index 28508c85e0..b5e7b32225 100644 --- a/doc/classes/PCKPacker.xml +++ b/doc/classes/PCKPacker.xml @@ -43,8 +43,8 @@ <method name="pck_start"> <return type="int" enum="Error" /> <argument index="0" name="pck_name" type="String" /> - <argument index="1" name="alignment" type="int" default="0" /> - <argument index="2" name="key" type="String" default="""" /> + <argument index="1" name="alignment" type="int" default="32" /> + <argument index="2" name="key" type="String" default=""0000000000000000000000000000000000000000000000000000000000000000"" /> <argument index="3" name="encrypt_directory" type="bool" default="false" /> <description> Creates a new PCK file with the name [code]pck_name[/code]. The [code].pck[/code] file extension isn't added automatically, so it should be part of [code]pck_name[/code] (even though it's not required). diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index b8e2f7f03c..400fae4aad 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -233,8 +233,9 @@ <method name="get_line_column_at_pos" qualifiers="const"> <return type="Vector2i" /> <argument index="0" name="position" type="Vector2i" /> + <argument index="1" name="allow_out_of_bounds" type="bool" default="true" /> <description> - Returns the line and column at the given position. In the returned vector, [code]x[/code] is the column, [code]y[/code] is the line. + Returns the line and column at the given position. In the returned vector, [code]x[/code] is the column, [code]y[/code] is the line. If [code]allow_out_of_bounds[/code] is [code]false[/code] and the position is not over the text, both vector values will be set to [code]-1[/code]. </description> </method> <method name="get_line_count" qualifiers="const"> @@ -453,6 +454,14 @@ Returns the number of visible lines, including wrapped text. </description> </method> + <method name="get_visible_line_count_in_range" qualifiers="const"> + <return type="int" /> + <argument index="0" name="from_line" type="int" /> + <argument index="1" name="to_line" type="int" /> + <description> + Returns the total number of visible + wrapped lines between the two lines. + </description> + </method> <method name="get_word_at_pos" qualifiers="const"> <return type="String" /> <argument index="0" name="position" type="Vector2" /> diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 324b21c6d0..7fba94da4c 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -296,11 +296,11 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { mpos.x = get_size().x - mpos.x; } - Point2i pos = get_line_column_at_pos(mpos); + Point2i pos = get_line_column_at_pos(mpos, false); int line = pos.y; int col = pos.x; - if (mb->get_button_index() == MouseButton::LEFT) { + if (line != -1 && mb->get_button_index() == MouseButton::LEFT) { if (is_line_folded(line)) { int wrap_index = get_line_wrap_index_at_column(line, col); if (wrap_index == get_line_wrap_count(line)) { @@ -321,11 +321,13 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { mpos.x = get_size().x - mpos.x; } - Point2i pos = get_line_column_at_pos(mpos); + Point2i pos = get_line_column_at_pos(mpos, false); int line = pos.y; int col = pos.x; - emit_signal(SNAME("symbol_lookup"), symbol_lookup_word, line, col); + if (line != -1) { + emit_signal(SNAME("symbol_lookup"), symbol_lookup_word, line, col); + } return; } } @@ -536,11 +538,11 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const { return CURSOR_ARROW; } - Point2i pos = get_line_column_at_pos(p_pos); + Point2i pos = get_line_column_at_pos(p_pos, false); int line = pos.y; int col = pos.x; - if (is_line_folded(line)) { + if (line != -1 && is_line_folded(line)) { int wrap_index = get_line_wrap_index_at_column(line, col); if (wrap_index == get_line_wrap_count(line)) { int eol_icon_width = folded_eol_icon->get_width(); @@ -2016,10 +2018,14 @@ bool CodeEdit::is_symbol_lookup_on_click_enabled() const { String CodeEdit::get_text_for_symbol_lookup() { Point2i mp = get_local_mouse_pos(); - Point2i pos = get_line_column_at_pos(mp); + Point2i pos = get_line_column_at_pos(mp, false); int line = pos.y; int col = pos.x; + if (line == -1) { + return String(); + } + StringBuilder lookup_text; const int text_size = get_line_count(); for (int i = 0; i < text_size; i++) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index fbfeea5722..74268707ff 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2878,6 +2878,16 @@ Point2i TextEdit::get_next_visible_line_index_offset_from(int p_line_from, int p } } wrap_index = get_line_wrap_count(MIN(i, text.size() - 1)) - MAX(0, num_visible - p_visible_amount); + + // If we are a hidden line, then we are the last line as we cannot reach "p_visible_amount". + // This means we need to backtrack to get last visible line. + // Currently, line 0 cannot be hidden so this should always be valid. + int line = (p_line_from + num_total) - 1; + if (_is_line_hidden(line)) { + Point2i backtrack = get_next_visible_line_index_offset_from(line, 0, -1); + num_total = num_total - (backtrack.x - 1); + wrap_index = backtrack.y; + } } else { p_visible_amount = ABS(p_visible_amount); int i; @@ -3386,7 +3396,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { return String(); } -Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos) const { +Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds) const { float rows = p_pos.y; rows -= style_normal->get_margin(SIDE_TOP); rows /= get_line_height(); @@ -3398,6 +3408,7 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos) const { if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE || _is_hiding_enabled()) { Point2i f_ofs = get_next_visible_line_index_offset_from(first_vis_line, caret.wrap_ofs, rows + (1 * SIGN(rows))); wrap_index = f_ofs.y; + if (rows < 0) { row = first_vis_line - (f_ofs.x - 1); } else { @@ -3409,33 +3420,39 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos) const { row = 0; } - int col = 0; - if (row >= text.size()) { row = text.size() - 1; - col = text[row].size(); - } else { - int colx = p_pos.x - (style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); - colx += caret.x_ofs; - col = _get_char_pos_for_line(colx, row, wrap_index); - if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && wrap_index < get_line_wrap_count(row)) { - // Move back one if we are at the end of the row. - Vector<String> rows2 = get_line_wrapped_text(row); - int row_end_col = 0; - for (int i = 0; i < wrap_index + 1; i++) { - row_end_col += rows2[i].length(); - } - if (col >= row_end_col) { - col -= 1; - } + } + + int visible_lines = get_visible_line_count_in_range(first_vis_line, row); + if (rows > visible_lines) { + if (!p_allow_out_of_bounds) { + return Point2i(-1, -1); } + return Point2i(text[row].size(), row); + } - RID text_rid = text.get_line_data(row)->get_line_rid(wrap_index); - if (is_layout_rtl()) { - colx = TS->shaped_text_get_size(text_rid).x - colx; + int col = 0; + int colx = p_pos.x - (style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); + colx += caret.x_ofs; + col = _get_char_pos_for_line(colx, row, wrap_index); + if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && wrap_index < get_line_wrap_count(row)) { + // Move back one if we are at the end of the row. + Vector<String> rows2 = get_line_wrapped_text(row); + int row_end_col = 0; + for (int i = 0; i < wrap_index + 1; i++) { + row_end_col += rows2[i].length(); } - col = TS->shaped_text_hit_test_position(text_rid, colx); + if (col >= row_end_col) { + col -= 1; + } + } + + RID text_rid = text.get_line_data(row)->get_line_rid(wrap_index); + if (is_layout_rtl()) { + colx = TS->shaped_text_get_size(text_rid).x - colx; } + col = TS->shaped_text_hit_test_position(text_rid, colx); return Point2i(col, row); } @@ -4012,15 +4029,7 @@ double TextEdit::get_scroll_pos_for_line(int p_line, int p_wrap_index) const { return p_line; } - // Count the number of visible lines up to this line. - double new_line_scroll_pos = 0.0; - int to = CLAMP(p_line, 0, text.size() - 1); - for (int i = 0; i < to; i++) { - if (!text.is_hidden(i)) { - new_line_scroll_pos++; - new_line_scroll_pos += get_line_wrap_count(i); - } - } + double new_line_scroll_pos = get_visible_line_count_in_range(0, CLAMP(p_line, 0, text.size() - 1)); new_line_scroll_pos += p_wrap_index; return new_line_scroll_pos; } @@ -4077,14 +4086,18 @@ int TextEdit::get_visible_line_count() const { return _get_control_height() / get_line_height(); } -int TextEdit::get_total_visible_line_count() const { +int TextEdit::get_visible_line_count_in_range(int p_from_line, int p_to_line) const { + ERR_FAIL_INDEX_V(p_from_line, text.size(), 0); + ERR_FAIL_INDEX_V(p_to_line, text.size(), 0); + ERR_FAIL_COND_V(p_from_line > p_to_line, 0); + /* Returns the total number of (lines + wrapped - hidden). */ if (!_is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) { - return text.size(); + return p_to_line - p_from_line; } int total_rows = 0; - for (int i = 0; i < text.size(); i++) { + for (int i = p_from_line; i <= p_to_line; i++) { if (!text.is_hidden(i)) { total_rows++; total_rows += get_line_wrap_count(i); @@ -4093,6 +4106,10 @@ int TextEdit::get_total_visible_line_count() const { return total_rows; } +int TextEdit::get_total_visible_line_count() const { + return get_visible_line_count_in_range(0, text.size() - 1); +} + // Auto adjust void TextEdit::adjust_viewport_to_caret() { // Make sure Caret is visible on the screen. @@ -4683,7 +4700,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_word_at_pos", "position"), &TextEdit::get_word_at_pos); - ClassDB::bind_method(D_METHOD("get_line_column_at_pos", "position"), &TextEdit::get_line_column_at_pos); + ClassDB::bind_method(D_METHOD("get_line_column_at_pos", "position", "allow_out_of_bounds"), &TextEdit::get_line_column_at_pos, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_minimap_line_at_pos", "position"), &TextEdit::get_minimap_line_at_pos); ClassDB::bind_method(D_METHOD("is_dragging_cursor"), &TextEdit::is_dragging_cursor); @@ -4807,6 +4824,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_last_full_visible_line_wrap_index"), &TextEdit::get_last_full_visible_line_wrap_index); ClassDB::bind_method(D_METHOD("get_visible_line_count"), &TextEdit::get_visible_line_count); + ClassDB::bind_method(D_METHOD("get_visible_line_count_in_range", "from_line", "to_line"), &TextEdit::get_visible_line_count_in_range); ClassDB::bind_method(D_METHOD("get_total_visible_line_count"), &TextEdit::get_total_visible_line_count); // Auto adjust diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 1a7dc851b5..09315ae395 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -716,7 +716,7 @@ public: String get_word_at_pos(const Vector2 &p_pos) const; - Point2i get_line_column_at_pos(const Point2i &p_pos) const; + Point2i get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds = true) const; int get_minimap_line_at_pos(const Point2i &p_pos) const; bool is_dragging_cursor() const; @@ -822,6 +822,7 @@ public: int get_last_full_visible_line_wrap_index() const; int get_visible_line_count() const; + int get_visible_line_count_in_range(int p_from, int p_to) const; int get_total_visible_line_count() const; // Auto Adjust diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 0bdc81330e..87ff225de9 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1835,6 +1835,7 @@ void VisualShader::_update_shader() const { code += " float __scalar_buff1;\n"; code += " float __scalar_buff2;\n"; code += " int __scalar_ibuff;\n"; + code += " vec4 __vec4_buff;\n"; code += " vec3 __ndiff = normalize(__diff);\n\n"; } if (has_start) { diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index 7dd4eed15b..1a829968e3 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -264,7 +264,7 @@ String VisualShaderNodeParticleMeshEmitter::get_caption() const { } int VisualShaderNodeParticleMeshEmitter::get_output_port_count() const { - return 2; + return 6; } VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter::get_output_port_type(int p_port) const { @@ -273,6 +273,14 @@ VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter return PORT_TYPE_VECTOR; // position case 1: return PORT_TYPE_VECTOR; // normal + case 2: + return PORT_TYPE_VECTOR; // color + case 3: + return PORT_TYPE_SCALAR; // alpha + case 4: + return PORT_TYPE_VECTOR; // uv + case 5: + return PORT_TYPE_VECTOR; // uv2 } return PORT_TYPE_SCALAR; } @@ -283,6 +291,14 @@ String VisualShaderNodeParticleMeshEmitter::get_output_port_name(int p_port) con return "position"; case 1: return "normal"; + case 2: + return "color"; + case 3: + return "alpha"; + case 4: + return "uv"; + case 5: + return "uv2"; } return String(); } @@ -299,135 +315,263 @@ String VisualShaderNodeParticleMeshEmitter::get_input_port_name(int p_port) cons return String(); } -String VisualShaderNodeParticleMeshEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { +String VisualShaderNodeParticleMeshEmitter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code; if (mesh.is_valid()) { - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n"; - code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n"; + if (is_output_port_connected(0)) { // position + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n"; + } + + if (is_output_port_connected(1)) { // normal + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n"; + } + + if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n"; + } + + if (is_output_port_connected(4)) { // uv + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n"; + } + + if (is_output_port_connected(5)) { // uv2 + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n"; + } } return code; } -String VisualShaderNodeParticleMeshEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { +String VisualShaderNodeParticleMeshEmitter::_generate_code(VisualShader::Type p_type, int p_id, const String *p_output_vars, int p_index, const String &p_texture_name, bool p_ignore_mode2d) const { String code; - - code += " __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n"; - - if (position_texture->get_width() == 0) { - code += " " + p_output_vars[0] + " = vec3(0.0);\n"; - } else { - if (mode_2d) { - code += " " + p_output_vars[0] + " = vec3("; + if (is_output_port_connected(p_index)) { + if (mode_2d && !p_ignore_mode2d) { + code += " " + p_output_vars[p_index] + " = vec3("; code += "texelFetch("; - code += make_unique_id(p_type, p_id, "mesh_vx") + ", "; + code += make_unique_id(p_type, p_id, p_texture_name) + ", "; code += "ivec2(__scalar_ibuff, 0), 0).xy, 0.0);\n"; } else { - code += " " + p_output_vars[0] + " = texelFetch("; - code += make_unique_id(p_type, p_id, "mesh_vx") + ", "; + code += " " + p_output_vars[p_index] + " = texelFetch("; + code += make_unique_id(p_type, p_id, p_texture_name) + ", "; code += "ivec2(__scalar_ibuff, 0), 0).xyz;\n"; } } + return code; +} - if (normal_texture->get_width() == 0) { - code += " " + p_output_vars[1] + " = vec3(0.0);\n"; - } else { - if (mode_2d) { - code += " " + p_output_vars[1] + " = vec3("; - code += "texelFetch("; - code += make_unique_id(p_type, p_id, "mesh_nm") + ", "; - code += "ivec2(__scalar_ibuff, 0), 0).xy, 0.0);\n"; +String VisualShaderNodeParticleMeshEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + code += " __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n"; + + code += _generate_code(p_type, p_id, p_output_vars, 0, "mesh_vx"); + code += _generate_code(p_type, p_id, p_output_vars, 1, "mesh_nm"); + + if (is_output_port_connected(2) || is_output_port_connected(3)) { + code += " __vec4_buff = texelFetch("; + code += make_unique_id(p_type, p_id, "mesh_col") + ", "; + code += "ivec2(__scalar_ibuff, 0), 0);\n"; + if (is_output_port_connected(2)) { + code += " " + p_output_vars[2] + " = __vec4_buff.rgb;\n"; } else { - code += " " + p_output_vars[1] + " = texelFetch("; - code += make_unique_id(p_type, p_id, "mesh_nm") + ", "; - code += "ivec2(__scalar_ibuff, 0), 0).xyz;\n"; + code += " " + p_output_vars[2] + " = vec3(0.0);\n"; + } + if (is_output_port_connected(3)) { + code += " " + p_output_vars[3] + " = __vec4_buff.a;\n"; + } else { + code += " " + p_output_vars[3] + " = 0.0;\n"; } } + code += _generate_code(p_type, p_id, p_output_vars, 4, "mesh_uv", true); + code += _generate_code(p_type, p_id, p_output_vars, 5, "mesh_uv2", true); + return code; } Vector<VisualShader::DefaultTextureParam> VisualShaderNodeParticleMeshEmitter::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { - VisualShader::DefaultTextureParam dtp_vx; - dtp_vx.name = make_unique_id(p_type, p_id, "mesh_vx"); - dtp_vx.params.push_back(position_texture); + Vector<VisualShader::DefaultTextureParam> ret; - VisualShader::DefaultTextureParam dtp_nm; - dtp_nm.name = make_unique_id(p_type, p_id, "mesh_nm"); - dtp_nm.params.push_back(normal_texture); + if (is_output_port_connected(0)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_vx"); + dtp.params.push_back(position_texture); + ret.push_back(dtp); + } + + if (is_output_port_connected(1)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_nm"); + dtp.params.push_back(normal_texture); + ret.push_back(dtp); + } + + if (is_output_port_connected(2) || is_output_port_connected(3)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_col"); + dtp.params.push_back(color_texture); + ret.push_back(dtp); + } + + if (is_output_port_connected(4)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_uv"); + dtp.params.push_back(uv_texture); + ret.push_back(dtp); + } + + if (is_output_port_connected(5)) { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "mesh_uv2"); + dtp.params.push_back(uv2_texture); + ret.push_back(dtp); + } - Vector<VisualShader::DefaultTextureParam> ret; - ret.push_back(dtp_vx); - ret.push_back(dtp_nm); return ret; } -void VisualShaderNodeParticleMeshEmitter::update_texture() { +void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector2> &p_array, Ref<ImageTexture> &r_texture) { + Ref<Image> image; + image.instantiate(); + + if (p_array.size() == 0) { + image->create(1, 1, false, Image::Format::FORMAT_RGBF); + } else { + image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBF); + } + + for (int i = 0; i < p_array.size(); i++) { + Vector2 v = p_array[i]; + image->set_pixel(i, 0, Color(v.x, v.y, 0)); + } + if (r_texture->get_width() != p_array.size() || p_array.size() == 0) { + r_texture->create_from_image(image); + } else { + r_texture->update(image); + } +} + +void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector3> &p_array, Ref<ImageTexture> &r_texture) { + Ref<Image> image; + image.instantiate(); + + if (p_array.size() == 0) { + image->create(1, 1, false, Image::Format::FORMAT_RGBF); + } else { + image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBF); + } + + for (int i = 0; i < p_array.size(); i++) { + Vector3 v = p_array[i]; + image->set_pixel(i, 0, Color(v.x, v.y, v.z)); + } + if (r_texture->get_width() != p_array.size() || p_array.size() == 0) { + r_texture->create_from_image(image); + } else { + r_texture->update(image); + } +} + +void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Color> &p_array, Ref<ImageTexture> &r_texture) { + Ref<Image> image; + image.instantiate(); + + if (p_array.size() == 0) { + image->create(1, 1, false, Image::Format::FORMAT_RGBA8); + } else { + image->create(p_array.size(), 1, false, Image::Format::FORMAT_RGBA8); + } + + for (int i = 0; i < p_array.size(); i++) { + image->set_pixel(i, 0, p_array[i]); + } + if (r_texture->get_width() != p_array.size() || p_array.size() == 0) { + r_texture->create_from_image(image); + } else { + r_texture->update(image); + } +} + +void VisualShaderNodeParticleMeshEmitter::_update_textures() { if (!mesh.is_valid()) { return; } Vector<Vector3> vertices; Vector<Vector3> normals; + Vector<Color> colors; + Vector<Vector2> uvs; + Vector<Vector2> uvs2; if (use_all_surfaces) { for (int i = 0; i < max_surface_index; i++) { + // position Array vertex_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_VERTEX]; for (int j = 0; j < vertex_array.size(); j++) { vertices.push_back((Vector3)vertex_array[j]); } + // normal Array normal_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_NORMAL]; - for (int j = 0; j < vertex_array.size(); j++) { - normals.push_back((Vector3)vertex_array[j]); + for (int j = 0; j < normal_array.size(); j++) { + normals.push_back((Vector3)normal_array[j]); + } + + // color + Array color_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_COLOR]; + for (int j = 0; j < color_array.size(); j++) { + colors.push_back((Color)color_array[j]); + } + + // uv + Array uv_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV]; + for (int j = 0; j < uv_array.size(); j++) { + uvs.push_back((Vector2)uv_array[j]); + } + + // uv2 + Array uv2_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV2]; + for (int j = 0; j < uv2_array.size(); j++) { + uvs2.push_back((Vector2)uv2_array[j]); } } } else { + // position Array vertex_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_VERTEX]; for (int i = 0; i < vertex_array.size(); i++) { vertices.push_back((Vector3)vertex_array[i]); } + // normal Array normal_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_NORMAL]; for (int i = 0; i < normal_array.size(); i++) { normals.push_back((Vector3)normal_array[i]); } - } - // vertices - { - Ref<Image> image; - image.instantiate(); - image->create(vertices.size(), 1, false, Image::Format::FORMAT_RGBF); - - for (int i = 0; i < vertices.size(); i++) { - Vector3 v = vertices[i]; - image->set_pixel(i, 0, Color(v.x, v.y, v.z)); - } - if (position_texture->get_width() != vertices.size()) { - position_texture->create_from_image(image); - } else { - position_texture->update(image); + // color + Array color_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_COLOR]; + for (int i = 0; i < color_array.size(); i++) { + colors.push_back((Color)color_array[i]); } - } - - // normals - { - Ref<Image> image; - image.instantiate(); - image->create(normals.size(), 1, false, Image::Format::FORMAT_RGBF); - for (int i = 0; i < normals.size(); i++) { - Vector3 v = normals[i]; - image->set_pixel(i, 0, Color(v.x, v.y, v.z)); + // uv + Array uv_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV]; + for (int j = 0; j < uv_array.size(); j++) { + uvs.push_back((Vector2)uv_array[j]); } - if (normal_texture->get_width() != normals.size()) { - normal_texture->create_from_image(image); - } else { - normal_texture->update(image); + + // uv2 + Array uv2_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV2]; + for (int j = 0; j < uv2_array.size(); j++) { + uvs2.push_back((Vector2)uv2_array[j]); } } + + _update_texture(vertices, position_texture); + _update_texture(normals, normal_texture); + _update_texture(colors, color_texture); + _update_texture(uvs, uv_texture); + _update_texture(uvs2, uv2_texture); } void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) { @@ -442,7 +586,7 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) { } if (mesh.is_valid()) { - Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture); + Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures); if (mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) { mesh->disconnect(CoreStringNames::get_singleton()->changed, callable); @@ -452,7 +596,7 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) { mesh = p_mesh; if (mesh.is_valid()) { - Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture); + Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures); if (!mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) { mesh->connect(CoreStringNames::get_singleton()->changed, callable); @@ -528,10 +672,13 @@ void VisualShaderNodeParticleMeshEmitter::_bind_methods() { } VisualShaderNodeParticleMeshEmitter::VisualShaderNodeParticleMeshEmitter() { - connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture)); + connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures)); position_texture.instantiate(); normal_texture.instantiate(); + color_texture.instantiate(); + uv_texture.instantiate(); + uv2_texture.instantiate(); } // VisualShaderNodeParticleMultiplyByAxisAngle diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index 0d0f21e4bf..79459432f1 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -115,6 +115,16 @@ class VisualShaderNodeParticleMeshEmitter : public VisualShaderNodeParticleEmitt Ref<ImageTexture> position_texture; Ref<ImageTexture> normal_texture; + Ref<ImageTexture> color_texture; + Ref<ImageTexture> uv_texture; + Ref<ImageTexture> uv2_texture; + + String _generate_code(VisualShader::Type p_type, int p_id, const String *p_output_vars, int p_index, const String &p_texture_name, bool p_ignore_mode2d = false) const; + + void _update_texture(const Vector<Vector2> &p_array, Ref<ImageTexture> &r_texture); + void _update_texture(const Vector<Vector3> &p_array, Ref<ImageTexture> &r_texture); + void _update_texture(const Vector<Color> &p_array, Ref<ImageTexture> &r_texture); + void _update_textures(); protected: static void _bind_methods(); @@ -130,11 +140,9 @@ public: virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; - virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; - void update_texture(); - void set_mesh(Ref<Mesh> p_mesh); Ref<Mesh> get_mesh() const; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index e338e526a0..7b4e2d34df 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -644,6 +644,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi); scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index); + scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency); if (instance->lightmap_sh.size() == 9) { scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr()); } @@ -839,6 +840,8 @@ void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); + instance->transparency = p_transparency; + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency); diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index de22bc1328..2bfcfd462c 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -439,17 +439,18 @@ public: RID self; //scenario stuff DynamicBVH::ID indexer_id; - int32_t array_index; + int32_t array_index = -1; int32_t visibility_index = -1; - float visibility_range_begin; - float visibility_range_end; - float visibility_range_begin_margin; - float visibility_range_end_margin; + float visibility_range_begin = 0.0f; + float visibility_range_end = 0.0f; + float visibility_range_begin_margin = 0.0f; + float visibility_range_end_margin = 0.0f; RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED; Instance *visibility_parent = nullptr; Set<Instance *> visibility_dependencies; - uint32_t visibility_dependencies_depth; - Scenario *scenario; + uint32_t visibility_dependencies_depth = 0; + float transparency = 0.0f; + Scenario *scenario = nullptr; SelfList<Instance> scenario_item; //aabb stuff diff --git a/tests/core/io/test_pck_packer.h b/tests/core/io/test_pck_packer.h index ae51d58522..75a4abffbe 100644 --- a/tests/core/io/test_pck_packer.h +++ b/tests/core/io/test_pck_packer.h @@ -40,17 +40,11 @@ namespace TestPCKPacker { -// Dummy 64-character encryption key (since it's required). -constexpr const char *ENCRYPTION_KEY = "0000000000000000000000000000000000000000000000000000000000000000"; - TEST_CASE("[PCKPacker] Pack an empty PCK file") { PCKPacker pck_packer; const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck"); CHECK_MESSAGE( - pck_packer.pck_start( - output_pck_path, - 32, - ENCRYPTION_KEY) == OK, + pck_packer.pck_start(output_pck_path) == OK, "Starting a PCK file should return an OK error code."); CHECK_MESSAGE( @@ -70,14 +64,27 @@ TEST_CASE("[PCKPacker] Pack an empty PCK file") { "The generated empty PCK file shouldn't be too large."); } +TEST_CASE("[PCKPacker] Pack empty with zero alignment invalid") { + PCKPacker pck_packer; + const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck"); + ERR_PRINT_OFF; + CHECK_MESSAGE(pck_packer.pck_start(output_pck_path, 0) != OK, "PCK with zero alignment should fail."); + ERR_PRINT_ON; +} + +TEST_CASE("[PCKPacker] Pack empty with invalid key") { + PCKPacker pck_packer; + const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck"); + ERR_PRINT_OFF; + CHECK_MESSAGE(pck_packer.pck_start(output_pck_path, 32, "") != OK, "PCK with invalid key should fail."); + ERR_PRINT_ON; +} + TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") { PCKPacker pck_packer; const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_with_files.pck"); CHECK_MESSAGE( - pck_packer.pck_start( - output_pck_path, - 32, - ENCRYPTION_KEY) == OK, + pck_packer.pck_start(output_pck_path) == OK, "Starting a PCK file should return an OK error code."); const String base_dir = OS::get_singleton()->get_executable_path().get_base_dir(); |