diff options
Diffstat (limited to 'scene')
32 files changed, 757 insertions, 462 deletions
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 56367e9bdd..e7f3f53ca9 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -44,23 +44,36 @@ //TODO: Implement CylinderShape and HeightMapShape? -void CollisionShape3D::make_convex_from_brothers() { +void CollisionShape3D::make_convex_from_siblings() { Node *p = get_parent(); if (!p) { return; } + Vector<Vector3> vertices; + for (int i = 0; i < p->get_child_count(); i++) { Node *n = p->get_child(i); MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(n); if (mi) { Ref<Mesh> m = mi->get_mesh(); if (m.is_valid()) { - Ref<Shape3D> s = m->create_convex_shape(); - set_shape(s); + for (int j = 0; j < m->get_surface_count(); j++) { + Array a = m->surface_get_arrays(j); + if (!a.empty()) { + Vector<Vector3> v = a[RenderingServer::ARRAY_VERTEX]; + for (int k = 0; k < v.size(); k++) { + vertices.append(mi->get_transform().xform(v[k])); + } + } + } } } } + + Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D); + shape->set_points(vertices); + set_shape(shape); } void CollisionShape3D::_update_in_shape_owner(bool p_xform_only) { @@ -137,8 +150,8 @@ void CollisionShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape3D::get_shape); ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape3D::set_disabled); ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape3D::is_disabled); - ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape3D::make_convex_from_brothers); - ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ClassDB::bind_method(D_METHOD("make_convex_from_siblings"), &CollisionShape3D::make_convex_from_siblings); + ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_siblings", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape3D::_update_debug_shape); diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h index a32a3efeb6..35f40d27b1 100644 --- a/scene/3d/collision_shape_3d.h +++ b/scene/3d/collision_shape_3d.h @@ -60,7 +60,7 @@ protected: static void _bind_methods(); public: - void make_convex_from_brothers(); + void make_convex_from_siblings(); void set_shape(const Ref<Shape3D> &p_shape); Ref<Shape3D> get_shape() const; diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index c4480e3ed2..6fa0fc6ecb 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -301,6 +301,36 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const { } } +void GPUParticles3D::emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { + RS::get_singleton()->particles_emit(particles, p_transform, p_velocity, p_color, p_custom, p_emit_flags); +} + +void GPUParticles3D::_attach_sub_emitter() { + Node *n = get_node_or_null(sub_emitter); + if (n) { + GPUParticles3D *sen = Object::cast_to<GPUParticles3D>(n); + if (sen && sen != this) { + RS::get_singleton()->particles_set_subemitter(particles, sen->particles); + } + } +} + +void GPUParticles3D::set_sub_emitter(const NodePath &p_path) { + if (is_inside_tree()) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + + sub_emitter = p_path; + + if (is_inside_tree() && sub_emitter != NodePath()) { + _attach_sub_emitter(); + } +} + +NodePath GPUParticles3D::get_sub_emitter() const { + return sub_emitter; +} + void GPUParticles3D::_notification(int p_what) { if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { if (can_process()) { @@ -319,6 +349,16 @@ void GPUParticles3D::_notification(int p_what) { } } + if (p_what == NOTIFICATION_ENTER_TREE) { + if (sub_emitter != NodePath()) { + _attach_sub_emitter(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { // make sure particles are updated before rendering occurs if they were active before if (is_visible_in_tree() && !RS::get_singleton()->particles_is_inactive(particles)) { @@ -369,8 +409,14 @@ void GPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("restart"), &GPUParticles3D::restart); ClassDB::bind_method(D_METHOD("capture_aabb"), &GPUParticles3D::capture_aabb); + ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles3D::set_sub_emitter); + ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles3D::get_sub_emitter); + + ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); @@ -396,6 +442,12 @@ void GPUParticles3D::_bind_methods() { BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH); + BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION); + BIND_ENUM_CONSTANT(EMIT_FLAG_ROTATION_SCALE); + BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY); + BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR); + BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM); + BIND_CONSTANT(MAX_DRAW_PASSES); } diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h index e04473727d..0d8dadd31d 100644 --- a/scene/3d/gpu_particles_3d.h +++ b/scene/3d/gpu_particles_3d.h @@ -64,6 +64,7 @@ private: bool local_coords; int fixed_fps; bool fractional_delta; + NodePath sub_emitter; Ref<Material> process_material; @@ -71,6 +72,8 @@ private: Vector<Ref<Mesh>> draw_passes; + void _attach_sub_emitter(); + protected: static void _bind_methods(); void _notification(int p_what); @@ -121,13 +124,27 @@ public: virtual String get_configuration_warning() const override; + void set_sub_emitter(const NodePath &p_path); + NodePath get_sub_emitter() const; + void restart(); + enum EmitFlags { + EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION, + EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE, + EMIT_FLAG_VELOCITY = RS::PARTICLES_EMIT_FLAG_VELOCITY, + EMIT_FLAG_COLOR = RS::PARTICLES_EMIT_FLAG_COLOR, + EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM + }; + + void emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags); + AABB capture_aabb() const; GPUParticles3D(); ~GPUParticles3D(); }; VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder) +VARIANT_ENUM_CAST(GPUParticles3D::EmitFlags) #endif // PARTICLES_H diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index a267c57f5e..d3d7cdc1ce 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -106,7 +106,7 @@ SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { offset = obj_tocopy.offset; } -SoftBody3D::PinnedPoint SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { +SoftBody3D::PinnedPoint &SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { point_index = obj.point_index; spatial_attachment_path = obj.spatial_attachment_path; spatial_attachment = obj.spatial_attachment; diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index 85cfb81637..c59a0b3aa3 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -74,7 +74,7 @@ public: PinnedPoint(); PinnedPoint(const PinnedPoint &obj_tocopy); - PinnedPoint operator=(const PinnedPoint &obj); + PinnedPoint &operator=(const PinnedPoint &obj); }; private: diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 6fef44481a..aaae03df68 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -60,7 +60,7 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventMouseButton> mouse_button = p_event; bool ui_accept = p_event->is_action("ui_accept") && !p_event->is_echo(); - bool button_masked = mouse_button.is_valid() && ((1 << (mouse_button->get_button_index() - 1)) & button_mask) > 0; + bool button_masked = mouse_button.is_valid() && ((1 << (mouse_button->get_button_index() - 1)) & button_mask) != 0; if (button_masked || ui_accept) { on_action_event(p_event); return; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index f49acc1b96..9e3418a5c9 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -188,7 +188,7 @@ void Label::_notification(int p_what) { int spaces = 0; while (to && to->char_pos >= 0) { taken += to->pixel_width; - if (to != from && to->space_count) { + if (to->space_count) { spaces += to->space_count; } to = to->next; @@ -235,8 +235,8 @@ void Label::_notification(int p_what) { float x_ofs_shadow = x_ofs; for (int i = 0; i < from->word_len; i++) { if (visible_chars < 0 || chars_total_shadow < visible_chars) { - CharType c = xl_text[i + pos]; - CharType n = xl_text[i + pos + 1]; + char32_t c = xl_text[i + pos]; + char32_t n = xl_text[i + pos + 1]; if (uppercase) { c = String::char_uppercase(c); n = String::char_uppercase(n); @@ -255,8 +255,8 @@ void Label::_notification(int p_what) { } for (int i = 0; i < from->word_len; i++) { if (visible_chars < 0 || chars_total < visible_chars) { - CharType c = xl_text[i + pos]; - CharType n = xl_text[i + pos + 1]; + char32_t c = xl_text[i + pos]; + char32_t n = xl_text[i + pos + 1]; if (uppercase) { c = String::char_uppercase(c); n = String::char_uppercase(n); @@ -308,7 +308,7 @@ int Label::get_longest_line_width() const { real_t line_width = 0; for (int i = 0; i < xl_text.size(); i++) { - CharType current = xl_text[i]; + char32_t current = xl_text[i]; if (uppercase) { current = String::char_uppercase(current); } @@ -390,7 +390,7 @@ void Label::regenerate_word_cache() { WordCache *last = nullptr; for (int i = 0; i <= xl_text.length(); i++) { - CharType current = i < xl_text.length() ? xl_text[i] : L' '; //always a space at the end, so the algo works + char32_t current = i < xl_text.length() ? xl_text[i] : L' '; //always a space at the end, so the algo works if (uppercase) { current = String::char_uppercase(current); @@ -420,6 +420,22 @@ void Label::regenerate_word_cache() { wc->space_count = space_count; current_word_size = 0; space_count = 0; + } else if ((i == xl_text.length() || current == '\n') && last != nullptr && space_count != 0) { + //in case there are trailing white spaces we add a placeholder word cache with just the spaces + WordCache *wc = memnew(WordCache); + if (word_cache) { + last->next = wc; + } else { + word_cache = wc; + } + last = wc; + + wc->pixel_width = 0; + wc->char_pos = 0; + wc->word_len = 0; + wc->space_count = space_count; + current_word_size = 0; + space_count = 0; } if (current == '\n') { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index ef0e049f40..1b8f04297d 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -42,7 +42,7 @@ #include "editor/editor_settings.h" #endif #include "scene/main/window.h" -static bool _is_text_char(CharType c) { +static bool _is_text_char(char32_t c) { return !is_symbol(c); } @@ -581,7 +581,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (k->get_unicode() >= 32 && k->get_keycode() != KEY_DELETE) { if (editable) { selection_delete(); - CharType ucodestr[2] = { (CharType)k->get_unicode(), 0 }; + char32_t ucodestr[2] = { (char32_t)k->get_unicode(), 0 }; int prev_len = text.length(); append_at_cursor(ucodestr); if (text.length() != prev_len) { @@ -806,8 +806,8 @@ void LineEdit::_notification(int p_what) { break; } - CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs]; - CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1]; + char32_t cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs]; + char32_t next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1]; int im_char_width = font->get_char_size(cchar, next).width; if ((x_ofs + im_char_width) > ofs_max) { @@ -829,8 +829,8 @@ void LineEdit::_notification(int p_what) { } } - CharType cchar = (pass && !text.empty()) ? secret_character[0] : t[char_ofs]; - CharType next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1]; + char32_t cchar = (pass && !text.empty()) ? secret_character[0] : t[char_ofs]; + char32_t next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1]; int char_width = font->get_char_size(cchar, next).width; // End of widget, break. @@ -869,8 +869,8 @@ void LineEdit::_notification(int p_what) { break; } - CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs]; - CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1]; + char32_t cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs]; + char32_t next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1]; int im_char_width = font->get_char_size(cchar, next).width; if ((x_ofs + im_char_width) > ofs_max) { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 40bcc243d1..2fdcf11ca8 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -101,9 +101,11 @@ Size2 PopupMenu::_get_contents_minimum_size() const { minsize.width += check_w; } - int height_limit = get_usable_parent_rect().size.height; - if (minsize.height > height_limit) { - minsize.height = height_limit; + if (is_inside_tree()) { + int height_limit = get_usable_parent_rect().size.height; + if (minsize.height > height_limit) { + minsize.height = height_limit; + } } return minsize; @@ -282,14 +284,15 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { } // Make an area which does not include v scrollbar, so that items are not activated when dragging scrollbar. - Rect2 item_clickable_area = control->get_global_rect(); - float scroll_width = scroll_container->get_v_scrollbar()->is_visible_in_tree() ? scroll_container->get_v_scrollbar()->get_size().width : 0; - item_clickable_area.set_size(Size2(item_clickable_area.size.width - scroll_width, item_clickable_area.size.height)); + Rect2 item_clickable_area = scroll_container->get_rect(); + if (scroll_container->get_v_scrollbar()->is_visible_in_tree()) { + item_clickable_area.size.width -= scroll_container->get_v_scrollbar()->get_size().width; + } Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { - if (!item_clickable_area.has_point(b->get_global_position())) { + if (!item_clickable_area.has_point(b->get_position())) { return; } @@ -331,7 +334,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> m = p_event; if (m.is_valid()) { - if (!item_clickable_area.has_point(m->get_global_position())) { + if (!item_clickable_area.has_point(m->get_position())) { return; } diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h index 77c82aa780..a5401f7eaa 100644 --- a/scene/gui/rich_text_effect.h +++ b/scene/gui/rich_text_effect.h @@ -59,7 +59,7 @@ public: bool visibility; Point2 offset; Color color; - CharType character; + char32_t character; float elapsed_time; Dictionary environment; @@ -79,7 +79,7 @@ public: Color get_color() { return color; } void set_color(Color p_color) { color = p_color; } int get_character() { return (int)character; } - void set_character(int p_char) { character = (CharType)p_char; } + void set_character(int p_char) { character = (char32_t)p_char; } Dictionary get_environment() { return environment; } void set_environment(Dictionary p_environment) { environment = p_environment; } }; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 29337e20f3..c62fd24a5e 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -354,8 +354,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & font = p_base_font; } - const CharType *c = text->text.c_str(); - const CharType *cf = c; + const char32_t *c = text->text.get_data(); + const char32_t *cf = c; int ascent = font->get_ascent(); int descent = font->get_descent(); @@ -461,7 +461,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & bool selected = false; Color fx_color = Color(color); Point2 fx_offset; - CharType fx_char = c[i]; + char32_t fx_char = c[i]; if (selection.active) { int cofs = (&c[i]) - cf; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index d6d8e74748..1d732bec5b 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -44,23 +44,23 @@ #define TAB_PIXELS -inline bool _is_symbol(CharType c) { +inline bool _is_symbol(char32_t c) { return is_symbol(c); } -static bool _is_text_char(CharType c) { +static bool _is_text_char(char32_t c) { return !is_symbol(c); } -static bool _is_whitespace(CharType c) { +static bool _is_whitespace(char32_t c) { return c == '\t' || c == ' '; } -static bool _is_char(CharType c) { +static bool _is_char(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } -static bool _is_pair_right_symbol(CharType c) { +static bool _is_pair_right_symbol(char32_t c) { return c == '"' || c == '\'' || c == ')' || @@ -68,7 +68,7 @@ static bool _is_pair_right_symbol(CharType c) { c == '}'; } -static bool _is_pair_left_symbol(CharType c) { +static bool _is_pair_left_symbol(char32_t c) { return c == '"' || c == '\'' || c == '(' || @@ -76,11 +76,11 @@ static bool _is_pair_left_symbol(CharType c) { c == '{'; } -static bool _is_pair_symbol(CharType c) { +static bool _is_pair_symbol(char32_t c) { return _is_pair_left_symbol(c) || _is_pair_right_symbol(c); } -static CharType _get_right_pair_symbol(CharType c) { +static char32_t _get_right_pair_symbol(char32_t c) { if (c == '"') { return '"'; } @@ -119,7 +119,7 @@ void TextEdit::Text::_update_line_cache(int p_line) const { int w = 0; int len = text[p_line].data.length(); - const CharType *str = text[p_line].data.c_str(); + const char32_t *str = text[p_line].data.get_data(); // Update width. @@ -214,7 +214,7 @@ void TextEdit::Text::remove(int p_at) { text.remove(p_at); } -int TextEdit::Text::get_char_width(CharType c, CharType next_c, int px) const { +int TextEdit::Text::get_char_width(char32_t c, char32_t next_c, int px) const { int tab_w = font->get_char_size(' ').width * indent_size; int w = 0; @@ -654,8 +654,8 @@ void TextEdit::_notification(int p_what) { if (brace_matching_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) { if (cursor.column < text[cursor.line].length()) { // Check for open. - CharType c = text[cursor.line][cursor.column]; - CharType closec = 0; + char32_t c = text[cursor.line][cursor.column]; + char32_t closec = 0; if (c == '[') { closec = ']'; @@ -671,10 +671,10 @@ void TextEdit::_notification(int p_what) { for (int i = cursor.line; i < text.size(); i++) { int from = i == cursor.line ? cursor.column + 1 : 0; for (int j = from; j < text[i].length(); j++) { - CharType cc = text[i][j]; + char32_t cc = text[i][j]; // Ignore any brackets inside a string. if (cc == '"' || cc == '\'') { - CharType quotation = cc; + char32_t quotation = cc; do { j++; if (!(j < text[i].length())) { @@ -720,8 +720,8 @@ void TextEdit::_notification(int p_what) { } if (cursor.column > 0) { - CharType c = text[cursor.line][cursor.column - 1]; - CharType closec = 0; + char32_t c = text[cursor.line][cursor.column - 1]; + char32_t closec = 0; if (c == ']') { closec = '['; @@ -737,10 +737,10 @@ void TextEdit::_notification(int p_what) { for (int i = cursor.line; i >= 0; i--) { int from = i == cursor.line ? cursor.column - 2 : text[i].length() - 1; for (int j = from; j >= 0; j--) { - CharType cc = text[i][j]; + char32_t cc = text[i][j]; // Ignore any brackets inside a string. if (cc == '"' || cc == '\'') { - CharType quotation = cc; + char32_t quotation = cc; do { j--; if (!(j >= 0)) { @@ -1303,8 +1303,8 @@ void TextEdit::_notification(int p_what) { break; } - CharType cchar = ime_text[ofs]; - CharType next = ime_text[ofs + 1]; + char32_t cchar = ime_text[ofs]; + char32_t next = ime_text[ofs + 1]; int im_char_width = cache.font->get_char_size(cchar, next).width; if ((char_ofs + char_margin + im_char_width) >= xmargin_end) { @@ -1399,8 +1399,8 @@ void TextEdit::_notification(int p_what) { break; } - CharType cchar = ime_text[ofs]; - CharType next = ime_text[ofs + 1]; + char32_t cchar = ime_text[ofs]; + char32_t next = ime_text[ofs + 1]; int im_char_width = cache.font->get_char_size(cchar, next).width; if ((char_ofs + char_margin + im_char_width) >= xmargin_end) { @@ -1661,12 +1661,12 @@ void TextEdit::_notification(int p_what) { } } -void TextEdit::_consume_pair_symbol(CharType ch) { +void TextEdit::_consume_pair_symbol(char32_t ch) { int cursor_position_to_move = cursor_get_column() + 1; - CharType ch_single[2] = { ch, 0 }; - CharType ch_single_pair[2] = { _get_right_pair_symbol(ch), 0 }; - CharType ch_pair[3] = { ch, _get_right_pair_symbol(ch), 0 }; + char32_t ch_single[2] = { ch, 0 }; + char32_t ch_single_pair[2] = { _get_right_pair_symbol(ch), 0 }; + char32_t ch_pair[3] = { ch, _get_right_pair_symbol(ch), 0 }; if (is_selection_active()) { int new_column, new_line; @@ -1771,8 +1771,8 @@ void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column bool remove_right_symbol = false; if (cursor.column < text[cursor.line].length() && cursor.column > 0) { - CharType left_char = text[cursor.line][cursor.column - 1]; - CharType right_char = text[cursor.line][cursor.column]; + char32_t left_char = text[cursor.line][cursor.column - 1]; + char32_t right_char = text[cursor.line][cursor.column]; if (right_char == _get_right_pair_symbol(left_char)) { remove_right_symbol = true; @@ -2540,7 +2540,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (k->get_unicode() > 32) { _reset_caret_blink_timer(); - const CharType chr[2] = { (CharType)k->get_unicode(), 0 }; + const char32_t chr[2] = { (char32_t)k->get_unicode(), 0 }; if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { _consume_pair_symbol(chr[0]); } else { @@ -2784,7 +2784,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } // No need to move the brace below if we are not taking the text with us. - char closing_char = _get_right_pair_symbol(indent_char); + char32_t closing_char = _get_right_pair_symbol(indent_char); if ((closing_char != 0) && (closing_char == text[cursor.line][cursor.column]) && !k->get_command()) { brace_indent = true; ins += "\n" + ins.substr(1, ins.length() - 2); @@ -3312,7 +3312,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // Compute whitespace symbols seq length. int current_line_whitespace_len = 0; while (current_line_whitespace_len < text[cursor.line].length()) { - CharType c = text[cursor.line][current_line_whitespace_len]; + char32_t c = text[cursor.line][current_line_whitespace_len]; if (c != '\t' && c != ' ') { break; } @@ -3458,7 +3458,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { int current_line_whitespace_len = 0; while (current_line_whitespace_len < text[cursor.line].length()) { - CharType c = text[cursor.line][current_line_whitespace_len]; + char32_t c = text[cursor.line][current_line_whitespace_len]; if (c != '\t' && c != ' ') break; current_line_whitespace_len++; @@ -3624,7 +3624,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } - const CharType chr[2] = { (CharType)k->get_unicode(), 0 }; + const char32_t chr[2] = { (char32_t)k->get_unicode(), 0 }; if (completion_hint != "" && k->get_unicode() == ')') { completion_hint = ""; @@ -4251,7 +4251,7 @@ Vector<String> TextEdit::get_wrap_rows_text(int p_line) const { } while (col < line_text.length()) { - CharType c = line_text[col]; + char32_t c = line_text[col]; int w = text.get_char_width(c, line_text[col + 1], px + word_px); int indent_ofs = (cur_wrap_index != 0 ? tab_offset_px : 0); @@ -6115,9 +6115,9 @@ void TextEdit::_confirm_completion() { // When inserted into the middle of an existing string/method, don't add an unnecessary quote/bracket. String line = text[cursor.line]; - CharType next_char = line[cursor.column]; - CharType last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1]; - CharType last_completion_char_display = completion_current.display[completion_current.display.length() - 1]; + char32_t next_char = line[cursor.column]; + char32_t last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1]; + char32_t last_completion_char_display = completion_current.display[completion_current.display.length() - 1]; if ((last_completion_char == '"' || last_completion_char == '\'') && (last_completion_char == next_char || last_completion_char_display == next_char)) { _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1); @@ -6161,7 +6161,7 @@ void TextEdit::_cancel_completion() { update(); } -static bool _is_completable(CharType c) { +static bool _is_completable(char32_t c) { return !_is_symbol(c) || c == '"' || c == '\''; } @@ -6292,14 +6292,14 @@ void TextEdit::_update_completion_candidates() { String display_lower = option.display.to_lower(); - const CharType *ssq = &s[0]; - const CharType *ssq_lower = &s_lower[0]; + const char32_t *ssq = &s[0]; + const char32_t *ssq_lower = &s_lower[0]; - const CharType *tgt = &option.display[0]; - const CharType *tgt_lower = &display_lower[0]; + const char32_t *tgt = &option.display[0]; + const char32_t *tgt_lower = &display_lower[0]; - const CharType *ssq_last_tgt = nullptr; - const CharType *ssq_lower_last_tgt = nullptr; + const char32_t *ssq_last_tgt = nullptr; + const char32_t *ssq_lower_last_tgt = nullptr; for (; *tgt; tgt++, tgt_lower++) { if (*ssq == *tgt) { @@ -6416,7 +6416,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { int beg, end; if (select_word(s, col, beg, end)) { bool inside_quotes = false; - CharType selected_quote = '\0'; + char32_t selected_quote = '\0'; int qbegin = 0, qend = 0; for (int i = 0; i < s.length(); i++) { if (s[i] == '"' || s[i] == '\'') { diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index a6bc9963cc..70d7365d71 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -79,7 +79,7 @@ public: void set_font(const Ref<Font> &p_font); int get_line_width(int p_line) const; int get_max_width(bool p_exclude_hidden = false) const; - int get_char_width(CharType c, CharType next_c, int px) const; + int get_char_width(char32_t c, char32_t next_c, int px) const; void set_line_wrap_amount(int p_line, int p_wrap_amount) const; int get_line_wrap_amount(int p_line) const; void set(int p_line, const String &p_text); @@ -488,7 +488,7 @@ protected: void _gui_input(const Ref<InputEvent> &p_gui_input); void _notification(int p_what); - void _consume_pair_symbol(CharType ch); + void _consume_pair_symbol(char32_t ch); void _consume_backspace_for_pair_symbol(int prev_line, int prev_column); static void _bind_methods(); diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index d6d1134cc9..5cd45ea408 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -939,9 +939,9 @@ float CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const ERR_FAIL_COND_V(p_font.is_null(), 0); if (p_font->has_outline()) { - p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.c_str()[0], Color(1, 1, 1), true); + p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.get_data()[0], Color(1, 1, 1), true); } - return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.c_str()[0], p_modulate); + return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.get_data()[0], p_modulate); } void CanvasItem::_notify_transform(CanvasItem *p_node) { diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 82ee4dde50..2b506b686b 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "http_request.h" +#include "core/io/compression.h" +#include "core/ustring.h" void HTTPRequest::_redirect_request(const String &p_new_url) { } @@ -82,7 +84,51 @@ Error HTTPRequest::_parse_url(const String &p_url) { return OK; } +bool HTTPRequest::has_header(const PackedStringArray &p_headers, const String &p_header_name) { + bool exists = false; + + String lower_case_header_name = p_header_name.to_lower(); + for (int i = 0; i < p_headers.size() && !exists; i++) { + String sanitized = p_headers[i].strip_edges().to_lower(); + if (sanitized.begins_with(lower_case_header_name)) { + exists = true; + } + } + + return exists; +} + +String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const String &p_header_name) { + String value = ""; + + String lowwer_case_header_name = p_header_name.to_lower(); + for (int i = 0; i < p_headers.size(); i++) { + if (p_headers[i].find(":", 0) >= 0) { + Vector<String> parts = p_headers[i].split(":", false, 1); + if (parts[0].strip_edges().to_lower() == lowwer_case_header_name) { + value = parts[1].strip_edges(); + break; + } + } + } + + return value; +} + Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_headers, bool p_ssl_validate_domain, HTTPClient::Method p_method, const String &p_request_data) { + // Copy the string into a raw buffer + Vector<uint8_t> raw_data; + + CharString charstr = p_request_data.utf8(); + size_t len = charstr.length(); + raw_data.resize(len); + uint8_t *w = raw_data.ptrw(); + copymem(w, charstr.ptr(), len); + + return request_raw(p_url, p_custom_headers, p_ssl_validate_domain, p_method, raw_data); +} + +Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_custom_headers, bool p_ssl_validate_domain, HTTPClient::Method p_method, const Vector<uint8_t> &p_request_data_raw) { ERR_FAIL_COND_V(!is_inside_tree(), ERR_UNCONFIGURED); ERR_FAIL_COND_V_MSG(requesting, ERR_BUSY, "HTTPRequest is processing a request. Wait for completion or cancel it before attempting a new one."); @@ -102,7 +148,14 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h headers = p_custom_headers; - request_data = p_request_data; + if (accept_gzip) { + // If the user has specified a different Accept-Encoding, don't overwrite it + if (!has_header(headers, "Accept-Encoding")) { + headers.push_back("Accept-Encoding: gzip, deflate"); + } + } + + request_data = p_request_data_raw; requesting = true; @@ -288,7 +341,7 @@ bool HTTPRequest::_update_connection() { } else { // Did not request yet, do request - Error err = client->request(method, request_string, headers, request_data); + Error err = client->request_raw(method, request_string, headers, request_data); if (err != OK) { call_deferred("_request_done", RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray()); return true; @@ -382,9 +435,47 @@ bool HTTPRequest::_update_connection() { ERR_FAIL_V(false); } -void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data) { +void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data) { cancel_request(); - emit_signal("request_completed", p_status, p_code, headers, p_data); + + // Determine if the request body is compressed + bool is_compressed; + String content_encoding = get_header_value(p_headers, "Content-Encoding").to_lower(); + Compression::Mode mode; + if (content_encoding == "gzip") { + mode = Compression::Mode::MODE_GZIP; + is_compressed = true; + } else if (content_encoding == "deflate") { + mode = Compression::Mode::MODE_DEFLATE; + is_compressed = true; + } else { + is_compressed = false; + } + + const PackedByteArray *data = NULL; + + if (accept_gzip && is_compressed && p_data.size() > 0) { + // Decompress request body + PackedByteArray *decompressed = memnew(PackedByteArray); + int result = Compression::decompress_dynamic(decompressed, body_size_limit, p_data.ptr(), p_data.size(), mode); + if (result == OK) { + data = decompressed; + } else if (result == -5) { + WARN_PRINT("Decompressed size of HTTP response body exceeded body_size_limit"); + p_status = RESULT_BODY_SIZE_LIMIT_EXCEEDED; + // Just return the raw data if we failed to decompress it + data = &p_data; + } else { + WARN_PRINT("Failed to decompress HTTP response body"); + p_status = RESULT_BODY_DECOMPRESS_FAILED; + // Just return the raw data if we failed to decompress it + data = &p_data; + } + } else { + data = &p_data; + } + + emit_signal("request_completed", p_status, p_code, p_headers, *data); } void HTTPRequest::_notification(int p_what) { @@ -415,6 +506,14 @@ bool HTTPRequest::is_using_threads() const { return use_threads; } +void HTTPRequest::set_accept_gzip(bool p_gzip) { + accept_gzip = p_gzip; +} + +bool HTTPRequest::is_accepting_gzip() const { + return accept_gzip; +} + void HTTPRequest::set_body_size_limit(int p_bytes) { ERR_FAIL_COND(get_http_client_status() != HTTPClient::STATUS_DISCONNECTED); @@ -481,6 +580,7 @@ void HTTPRequest::_timeout() { void HTTPRequest::_bind_methods() { ClassDB::bind_method(D_METHOD("request", "url", "custom_headers", "ssl_validate_domain", "method", "request_data"), &HTTPRequest::request, DEFVAL(PackedStringArray()), DEFVAL(true), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("request_raw", "url", "custom_headers", "ssl_validate_domain", "method", "request_data_raw"), &HTTPRequest::request_raw, DEFVAL(PackedStringArray()), DEFVAL(true), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(PackedByteArray())); ClassDB::bind_method(D_METHOD("cancel_request"), &HTTPRequest::cancel_request); ClassDB::bind_method(D_METHOD("get_http_client_status"), &HTTPRequest::get_http_client_status); @@ -488,6 +588,9 @@ void HTTPRequest::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_threads", "enable"), &HTTPRequest::set_use_threads); ClassDB::bind_method(D_METHOD("is_using_threads"), &HTTPRequest::is_using_threads); + ClassDB::bind_method(D_METHOD("set_accept_gzip", "enable"), &HTTPRequest::set_accept_gzip); + ClassDB::bind_method(D_METHOD("is_accepting_gzip"), &HTTPRequest::is_accepting_gzip); + ClassDB::bind_method(D_METHOD("set_body_size_limit", "bytes"), &HTTPRequest::set_body_size_limit); ClassDB::bind_method(D_METHOD("get_body_size_limit"), &HTTPRequest::get_body_size_limit); @@ -512,6 +615,7 @@ void HTTPRequest::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "download_file", PROPERTY_HINT_FILE), "set_download_file", "get_download_file"); ADD_PROPERTY(PropertyInfo(Variant::INT, "download_chunk_size", PROPERTY_HINT_RANGE, "256,16777216"), "set_download_chunk_size", "get_download_chunk_size"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "is_using_threads"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "accept_gzip"), "set_accept_gzip", "is_accepting_gzip"); ADD_PROPERTY(PropertyInfo(Variant::INT, "body_size_limit", PROPERTY_HINT_RANGE, "-1,2000000000"), "set_body_size_limit", "get_body_size_limit"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_redirects", PROPERTY_HINT_RANGE, "-1,64"), "set_max_redirects", "get_max_redirects"); ADD_PROPERTY(PropertyInfo(Variant::INT, "timeout", PROPERTY_HINT_RANGE, "0,86400"), "set_timeout", "get_timeout"); @@ -544,6 +648,7 @@ HTTPRequest::HTTPRequest() { got_response = false; validate_ssl = false; use_ssl = false; + accept_gzip = true; response_code = 0; request_sent = false; requesting = false; diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 1409965d45..2e8931120b 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -50,6 +50,7 @@ public: RESULT_SSL_HANDSHAKE_ERROR, RESULT_NO_RESPONSE, RESULT_BODY_SIZE_LIMIT_EXCEEDED, + RESULT_BODY_DECOMPRESS_FAILED, RESULT_REQUEST_FAILED, RESULT_DOWNLOAD_FILE_CANT_OPEN, RESULT_DOWNLOAD_FILE_WRITE_ERROR, @@ -68,12 +69,13 @@ private: bool validate_ssl; bool use_ssl; HTTPClient::Method method; - String request_data; + Vector<uint8_t> request_data; bool request_sent; Ref<HTTPClient> client; PackedByteArray body; volatile bool use_threads; + bool accept_gzip; bool got_response; int response_code; @@ -102,12 +104,15 @@ private: Error _parse_url(const String &p_url); Error _request(); + bool has_header(const PackedStringArray &p_headers, const String &p_header_name); + String get_header_value(const PackedStringArray &p_headers, const String &header_name); + volatile bool thread_done; volatile bool thread_request_quit; Thread *thread; - void _request_done(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data); + void _request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data); static void _thread_func(void *p_userdata); protected: @@ -116,12 +121,16 @@ protected: public: Error request(const String &p_url, const Vector<String> &p_custom_headers = Vector<String>(), bool p_ssl_validate_domain = true, HTTPClient::Method p_method = HTTPClient::METHOD_GET, const String &p_request_data = ""); //connects to a full url and perform request + Error request_raw(const String &p_url, const Vector<String> &p_custom_headers = Vector<String>(), bool p_ssl_validate_domain = true, HTTPClient::Method p_method = HTTPClient::METHOD_GET, const Vector<uint8_t> &p_request_data_raw = Vector<uint8_t>()); //connects to a full url and perform request void cancel_request(); HTTPClient::Status get_http_client_status() const; void set_use_threads(bool p_use); bool is_using_threads() const; + void set_accept_gzip(bool p_gzip); + bool is_accepting_gzip() const; + void set_download_file(const String &p_file); String get_download_file() const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 6b304c03d2..e7753089c7 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1094,7 +1094,7 @@ String increase_numeric_string(const String &s) { if (!carry) { break; } - CharType n = s[i]; + char32_t n = s[i]; if (n == '9') { // keep carry as true: 9 + 1 res[i] = '0'; } else { @@ -1155,7 +1155,7 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co String name_string = name; String nums; for (int i = name_string.length() - 1; i >= 0; i--) { - CharType n = name_string[i]; + char32_t n = name_string[i]; if (n >= '0' && n <= '9') { nums = String::chr(name_string[i]) + nums; } else { diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 99f87dd6ed..bc983c1d7e 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -239,7 +239,7 @@ float DynamicFontAtSize::get_underline_thickness() const { return underline_thickness; } -const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFontAtSize::_find_char_with_font(CharType p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { +const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFontAtSize::_find_char_with_font(char32_t p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { const Character *chr = char_map.getptr(p_char); ERR_FAIL_COND_V(!chr, (Pair<const Character *, DynamicFontAtSize *>(nullptr, nullptr))); @@ -271,7 +271,7 @@ const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFon return Pair<const Character *, DynamicFontAtSize *>(chr, const_cast<DynamicFontAtSize *>(this)); } -Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { +Size2 DynamicFontAtSize::get_char_size(char32_t p_char, char32_t p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { if (!valid) { return Size2(1, 1); } @@ -297,7 +297,7 @@ String DynamicFontAtSize::get_available_chars() const { FT_ULong charcode = FT_Get_First_Char(face, &gindex); while (gindex != 0) { if (charcode != 0) { - chars += CharType(charcode); + chars += char32_t(charcode); } charcode = FT_Get_Next_Char(face, charcode, &gindex); } @@ -305,7 +305,7 @@ String DynamicFontAtSize::get_available_chars() const { return chars; } -float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only, bool p_outline) const { +float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only, bool p_outline) const { if (!valid) { return 0; } @@ -560,7 +560,7 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b return chr; } -DynamicFontAtSize::Character DynamicFontAtSize::_make_outline_char(CharType p_char) { +DynamicFontAtSize::Character DynamicFontAtSize::_make_outline_char(char32_t p_char) { Character ret = Character::not_found(); if (FT_Load_Char(face, p_char, FT_LOAD_NO_BITMAP | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)) != 0) { @@ -596,7 +596,7 @@ cleanup_stroker: return ret; } -void DynamicFontAtSize::_update_char(CharType p_char) { +void DynamicFontAtSize::_update_char(char32_t p_char) { if (char_map.has(p_char)) { return; } @@ -849,7 +849,7 @@ float DynamicFont::get_underline_thickness() const { return data_at_size->get_underline_thickness(); } -Size2 DynamicFont::get_char_size(CharType p_char, CharType p_next) const { +Size2 DynamicFont::get_char_size(char32_t p_char, char32_t p_next) const { if (!data_at_size.is_valid()) { return Size2(1, 1); } @@ -891,7 +891,7 @@ bool DynamicFont::has_outline() const { return outline_cache_id.outline_size > 0; } -float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const { +float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, bool p_outline) const { const Ref<DynamicFontAtSize> &font_at_size = p_outline && outline_cache_id.outline_size > 0 ? outline_data_at_size : data_at_size; if (!font_at_size.is_valid()) { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index e8637e7e34..a881e21da8 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -159,17 +159,17 @@ class DynamicFontAtSize : public Reference { int y; }; - const Pair<const Character *, DynamicFontAtSize *> _find_char_with_font(CharType p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; - Character _make_outline_char(CharType p_char); + const Pair<const Character *, DynamicFontAtSize *> _find_char_with_font(char32_t p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; + Character _make_outline_char(char32_t p_char); TexturePosition _find_texture_pos_for_glyph(int p_color_size, Image::Format p_image_format, int p_width, int p_height); Character _bitmap_to_character(FT_Bitmap bitmap, int yofs, int xofs, float advance); static unsigned long _ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count); static void _ft_stream_close(FT_Stream stream); - HashMap<CharType, Character> char_map; + HashMap<char32_t, Character> char_map; - _FORCE_INLINE_ void _update_char(CharType p_char); + _FORCE_INLINE_ void _update_char(char32_t p_char); friend class DynamicFontData; Ref<DynamicFontData> font; @@ -188,10 +188,10 @@ public: float get_underline_position() const; float get_underline_thickness() const; - Size2 get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; + Size2 get_char_size(char32_t p_char, char32_t p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; String get_available_chars() const; - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const; + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const; void set_texture_flags(uint32_t p_flags); void update_oversampling(); @@ -277,14 +277,14 @@ public: virtual float get_underline_position() const override; virtual float get_underline_thickness() const override; - virtual Size2 get_char_size(CharType p_char, CharType p_next = 0) const override; + virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const override; String get_available_chars() const; virtual bool is_distance_field_hint() const override; virtual bool has_outline() const override; - virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; + virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; SelfList<DynamicFont> font_list; diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index ccab88a153..7cc39f661d 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -125,7 +125,7 @@ void BitmapFont::_set_chars(const Vector<int> &p_chars) { Vector<int> BitmapFont::_get_chars() const { Vector<int> chars; - const CharType *key = nullptr; + const char32_t *key = nullptr; while ((key = char_map.next(key))) { const Character *c = char_map.getptr(*key); @@ -272,7 +272,7 @@ Error BitmapFont::create_from_fnt(const String &p_file) { } } } else if (type == "char") { - CharType idx = 0; + char32_t idx = 0; if (keys.has("id")) { idx = keys["id"].to_int(); } @@ -313,7 +313,7 @@ Error BitmapFont::create_from_fnt(const String &p_file) { add_char(idx, texture, rect, ofs, advance); } else if (type == "kerning") { - CharType first = 0, second = 0; + char32_t first = 0, second = 0; int k = 0; if (keys.has("first")) { @@ -385,10 +385,10 @@ int BitmapFont::get_character_count() const { return char_map.size(); }; -Vector<CharType> BitmapFont::get_char_keys() const { - Vector<CharType> chars; +Vector<char32_t> BitmapFont::get_char_keys() const { + Vector<char32_t> chars; chars.resize(char_map.size()); - const CharType *ct = nullptr; + const char32_t *ct = nullptr; int count = 0; while ((ct = char_map.next(ct))) { chars.write[count++] = *ct; @@ -397,7 +397,7 @@ Vector<CharType> BitmapFont::get_char_keys() const { return chars; }; -BitmapFont::Character BitmapFont::get_character(CharType p_char) const { +BitmapFont::Character BitmapFont::get_character(char32_t p_char) const { if (!char_map.has(p_char)) { ERR_FAIL_V(Character()); }; @@ -405,7 +405,7 @@ BitmapFont::Character BitmapFont::get_character(CharType p_char) const { return char_map[p_char]; }; -void BitmapFont::add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { +void BitmapFont::add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { if (p_advance < 0) { p_advance = p_rect.size.width; } @@ -420,7 +420,7 @@ void BitmapFont::add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rec char_map[p_char] = c; } -void BitmapFont::add_kerning_pair(CharType p_A, CharType p_B, int p_kerning) { +void BitmapFont::add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) { KerningPairKey kpk; kpk.A = p_A; kpk.B = p_B; @@ -444,7 +444,7 @@ Vector<BitmapFont::KerningPairKey> BitmapFont::get_kerning_pair_keys() const { return ret; } -int BitmapFont::get_kerning_pair(CharType p_A, CharType p_B) const { +int BitmapFont::get_kerning_pair(char32_t p_A, char32_t p_B) const { KerningPairKey kpk; kpk.A = p_A; kpk.B = p_B; @@ -482,7 +482,7 @@ Size2 Font::get_string_size(const String &p_string) const { if (l == 0) { return Size2(0, get_height()); } - const CharType *sptr = &p_string[0]; + const char32_t *sptr = &p_string[0]; for (int i = 0; i < l; i++) { w += get_char_size(sptr[i], sptr[i + 1]).width; @@ -534,7 +534,7 @@ Ref<BitmapFont> BitmapFont::get_fallback() const { return fallback; } -float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const { +float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, bool p_outline) const { const Character *c = char_map.getptr(p_char); if (!c) { @@ -556,7 +556,7 @@ float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_c return get_char_size(p_char, p_next).width; } -Size2 BitmapFont::get_char_size(CharType p_char, CharType p_next) const { +Size2 BitmapFont::get_char_size(char32_t p_char, char32_t p_next) const { const Character *c = char_map.getptr(p_char); if (!c) { diff --git a/scene/resources/font.h b/scene/resources/font.h index e6b296800b..c739520da3 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -49,7 +49,7 @@ public: virtual float get_underline_position() const = 0; virtual float get_underline_thickness() const = 0; - virtual Size2 get_char_size(CharType p_char, CharType p_next = 0) const = 0; + virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const = 0; Size2 get_string_size(const String &p_string) const; Size2 get_wordwrap_string_size(const String &p_string, float p_width) const; @@ -59,7 +59,7 @@ public: void draw_halign(RID p_canvas_item, const Point2 &p_pos, HAlign p_align, float p_width, const String &p_text, const Color &p_modulate = Color(1, 1, 1), const Color &p_outline_modulate = Color(1, 1, 1)) const; virtual bool has_outline() const { return false; } - virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0; + virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0; void update_changes(); Font(); @@ -74,8 +74,8 @@ class FontDrawer { struct PendingDraw { RID canvas_item; Point2 pos; - CharType chr; - CharType next; + char32_t chr; + char32_t next; Color modulate; }; @@ -88,7 +88,7 @@ public: has_outline = p_font->has_outline(); } - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1)) { + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1)) { if (has_outline) { PendingDraw draw = { p_canvas_item, p_pos, p_char, p_next, p_modulate }; pending_draws.push_back(draw); @@ -137,7 +137,7 @@ public: }; private: - HashMap<CharType, Character> char_map; + HashMap<char32_t, Character> char_map; Map<KerningPairKey, int> kerning_map; float height; @@ -169,20 +169,20 @@ public: float get_underline_thickness() const override; void add_texture(const Ref<Texture2D> &p_texture); - void add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance = -1); + void add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance = -1); int get_character_count() const; - Vector<CharType> get_char_keys() const; - Character get_character(CharType p_char) const; + Vector<char32_t> get_char_keys() const; + Character get_character(char32_t p_char) const; int get_texture_count() const; Ref<Texture2D> get_texture(int p_idx) const; - void add_kerning_pair(CharType p_A, CharType p_B, int p_kerning); - int get_kerning_pair(CharType p_A, CharType p_B) const; + void add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning); + int get_kerning_pair(char32_t p_A, char32_t p_B) const; Vector<KerningPairKey> get_kerning_pair_keys() const; - Size2 get_char_size(CharType p_char, CharType p_next = 0) const override; + Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const override; void set_fallback(const Ref<BitmapFont> &p_fallback); Ref<BitmapFont> get_fallback() const; @@ -192,7 +192,7 @@ public: void set_distance_field_hint(bool p_distance_field); bool is_distance_field_hint() const override; - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; BitmapFont(); ~BitmapFont(); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index fd1fa1b48f..b0a30a5627 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -209,7 +209,6 @@ public: void surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data); int get_surface_count() const override; - void surface_remove(int p_idx); void clear_surfaces(); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index a0095ed952..49b8cbe7e0 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -91,13 +91,13 @@ void ParticlesMaterial::init_shaders() { shader_names->emission_texture_normal = "emission_texture_normal"; shader_names->emission_texture_color = "emission_texture_color"; - shader_names->trail_divisor = "trail_divisor"; - shader_names->trail_size_modifier = "trail_size_modifier"; - shader_names->trail_color_modifier = "trail_color_modifier"; - shader_names->gravity = "gravity"; shader_names->lifetime_randomness = "lifetime_randomness"; + + shader_names->sub_emitter_frequency = "sub_emitter_frequency"; + shader_names->sub_emitter_amount_at_end = "sub_emitter_amount_at_end"; + shader_names->sub_emitter_keep_velocity = "sub_emitter_keep_velocity"; } void ParticlesMaterial::finish_shaders() { @@ -192,9 +192,17 @@ void ParticlesMaterial::_update_shader() { } } - code += "uniform vec4 color_value : hint_color;\n"; + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { + if (sub_emitter_mode == SUB_EMITTER_CONSTANT) { + code += "uniform float sub_emitter_frequency;\n"; + } + if (sub_emitter_mode == SUB_EMITTER_AT_END) { + code += "uniform int sub_emitter_amount_at_end;\n"; + } + code += "uniform bool sub_emitter_keep_velocity;\n"; + } - code += "uniform int trail_divisor;\n"; + code += "uniform vec4 color_value : hint_color;\n"; code += "uniform vec3 gravity;\n"; @@ -239,14 +247,6 @@ void ParticlesMaterial::_update_shader() { code += "uniform sampler2D anim_offset_texture;\n"; } - if (trail_size_modifier.is_valid()) { - code += "uniform sampler2D trail_size_modifier;\n"; - } - - if (trail_color_modifier.is_valid()) { - code += "uniform sampler2D trail_color_modifier;\n"; - } - //need a random function code += "\n\n"; code += "float rand_from_seed(inout uint seed) {\n"; @@ -278,7 +278,7 @@ void ParticlesMaterial::_update_shader() { code += "\n"; code += "void compute() {\n"; - code += " uint base_number = NUMBER / uint(trail_divisor);\n"; + code += " uint base_number = NUMBER;\n"; code += " uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);\n"; code += " float angle_rand = rand_from_seed(alt_seed);\n"; code += " float scale_rand = rand_from_seed(alt_seed);\n"; @@ -293,17 +293,7 @@ void ParticlesMaterial::_update_shader() { code += " ivec2 emission_tex_size = textureSize(emission_texture_points, 0);\n"; code += " ivec2 emission_tex_ofs = ivec2(point % emission_tex_size.x, point / emission_tex_size.x);\n"; } - code += " bool restart = false;\n"; - code += " if (CUSTOM.y > CUSTOM.w) {\n"; - code += " restart = true;\n"; - code += " }\n\n"; - code += " if (RESTART || restart) {\n"; - - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(0.0, 0.0), 0.0).r;\n"; - } else { - code += " float tex_linear_velocity = 0.0;\n"; - } + code += " if (RESTART) {\n"; if (tex_parameters[PARAM_ANGLE].is_valid()) { code += " float tex_angle = textureLod(angle_texture, vec2(0.0, 0.0), 0.0).r;\n"; @@ -319,25 +309,34 @@ void ParticlesMaterial::_update_shader() { code += " float spread_rad = spread * degree_to_rad;\n"; + code += " if (RESTART_VELOCITY) {\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(0.0, 0.0), 0.0).r;\n"; + } else { + code += " float tex_linear_velocity = 0.0;\n"; + } + if (flags[FLAG_DISABLE_Z]) { - code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; - code += " angle1_rad += direction.x != 0.0 ? atan(direction.y, direction.x) : sign(direction.y) * (pi / 2.0);\n"; - code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; - code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " angle1_rad += direction.x != 0.0 ? atan(direction.y, direction.x) : sign(direction.y) * (pi / 2.0);\n"; + code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; + code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } else { //initiate velocity spread in 3D - code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; - code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; - code += " angle1_rad += direction.z != 0.0 ? atan(direction.x, direction.z) : sign(direction.x) * (pi / 2.0);\n"; - code += " angle2_rad += direction.z != 0.0 ? atan(direction.y, abs(direction.z)) : (direction.x != 0.0 ? atan(direction.y, abs(direction.x)) : sign(direction.y) * (pi / 2.0));\n"; - code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; - code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; - code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; - code += " vec3 vec_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; - code += " vec_direction = normalize(vec_direction);\n"; - code += " VELOCITY = vec_direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; + code += " angle1_rad += direction.z != 0.0 ? atan(direction.x, direction.z) : sign(direction.x) * (pi / 2.0);\n"; + code += " angle2_rad += direction.z != 0.0 ? atan(direction.y, abs(direction.z)) : (direction.x != 0.0 ? atan(direction.y, abs(direction.x)) : sign(direction.y) * (pi / 2.0));\n"; + code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; + code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; + code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; + code += " vec3 vec_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; + code += " vec_direction = normalize(vec_direction);\n"; + code += " VELOCITY = vec_direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } + code += " }\n"; code += " float base_angle = (initial_angle + tex_angle) * mix(1.0, angle_rand, initial_angle_random);\n"; code += " CUSTOM.x = base_angle * degree_to_rad;\n"; // angle @@ -345,35 +344,38 @@ void ParticlesMaterial::_update_shader() { code += " CUSTOM.w = (1.0 - lifetime_randomness * rand_from_seed(alt_seed));\n"; code += " CUSTOM.z = (anim_offset + tex_anim_offset) * mix(1.0, anim_offset_rand, anim_offset_random);\n"; // animation offset (0-1) + code += " if (RESTART_POSITION) {\n"; + switch (emission_shape) { case EMISSION_SHAPE_POINT: { - //do none + //do none, identity (will later be multiplied by emission transform) + code += " TRANSFORM = mat4(vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(0,0,0,1));\n"; } break; case EMISSION_SHAPE_SPHERE: { - code += " float s = rand_from_seed(alt_seed) * 2.0 - 1.0;\n"; - code += " float t = rand_from_seed(alt_seed) * 2.0 * pi;\n"; - code += " float radius = emission_sphere_radius * sqrt(1.0 - s * s);\n"; - code += " TRANSFORM[3].xyz = vec3(radius * cos(t), radius * sin(t), emission_sphere_radius * s);\n"; + code += " float s = rand_from_seed(alt_seed) * 2.0 - 1.0;\n"; + code += " float t = rand_from_seed(alt_seed) * 2.0 * pi;\n"; + code += " float radius = emission_sphere_radius * sqrt(1.0 - s * s);\n"; + code += " TRANSFORM[3].xyz = vec3(radius * cos(t), radius * sin(t), emission_sphere_radius * s);\n"; } break; case EMISSION_SHAPE_BOX: { - code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0) * emission_box_extents;\n"; + code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0) * emission_box_extents;\n"; } break; case EMISSION_SHAPE_POINTS: case EMISSION_SHAPE_DIRECTED_POINTS: { - code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs, 0).xyz;\n"; + code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs, 0).xyz;\n"; if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) { if (flags[FLAG_DISABLE_Z]) { - code += " mat2 rotm;"; - code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy;\n"; - code += " rotm[1] = rotm[0].yx * vec2(1.0, -1.0);\n"; - code += " VELOCITY.xy = rotm * VELOCITY.xy;\n"; + code += " mat2 rotm;"; + code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy;\n"; + code += " rotm[1] = rotm[0].yx * vec2(1.0, -1.0);\n"; + code += " if (RESTART_VELOCITY) VELOCITY.xy = rotm * VELOCITY.xy;\n"; } else { - code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xyz;\n"; - code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);\n"; - code += " vec3 tangent = normalize(cross(v0, normal));\n"; - code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; - code += " VELOCITY = mat3(tangent, bitangent, normal) * VELOCITY;\n"; + code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xyz;\n"; + code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);\n"; + code += " vec3 tangent = normalize(cross(v0, normal));\n"; + code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; + code += " if (RESTART_VELOCITY) VELOCITY = mat3(tangent, bitangent, normal) * VELOCITY;\n"; } } } break; @@ -381,12 +383,14 @@ void ParticlesMaterial::_update_shader() { break; } } - code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; - code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; + + code += " if (RESTART_VELOCITY) VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; + code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; if (flags[FLAG_DISABLE_Z]) { - code += " VELOCITY.z = 0.0;\n"; - code += " TRANSFORM[3].z = 0.0;\n"; + code += " VELOCITY.z = 0.0;\n"; + code += " TRANSFORM[3].z = 0.0;\n"; } + code += " }\n"; code += " } else {\n"; @@ -540,11 +544,6 @@ void ParticlesMaterial::_update_shader() { if (emission_color_texture.is_valid() && (emission_shape == EMISSION_SHAPE_POINTS || emission_shape == EMISSION_SHAPE_DIRECTED_POINTS)) { code += " COLOR *= texelFetch(emission_texture_color, emission_tex_ofs, 0);\n"; } - if (trail_color_modifier.is_valid()) { - code += " if (trail_divisor > 1) {\n"; - code += " COLOR *= textureLod(trail_color_modifier, vec2(float(int(NUMBER) % trail_divisor) / float(trail_divisor - 1), 0.0), 0.0);\n"; - code += " }\n"; - } code += "\n"; if (flags[FLAG_DISABLE_Z]) { @@ -592,11 +591,6 @@ void ParticlesMaterial::_update_shader() { code += " if (base_scale < 0.000001) {\n"; code += " base_scale = 0.000001;\n"; code += " }\n"; - if (trail_size_modifier.is_valid()) { - code += " if (trail_divisor > 1) {\n"; - code += " base_scale *= textureLod(trail_size_modifier, vec2(float(int(NUMBER) % trail_divisor) / float(trail_divisor - 1), 0.0), 0.0).r;\n"; - code += " }\n"; - } code += " TRANSFORM[0].xyz *= base_scale;\n"; code += " TRANSFORM[1].xyz *= base_scale;\n"; @@ -605,6 +599,33 @@ void ParticlesMaterial::_update_shader() { code += " VELOCITY.z = 0.0;\n"; code += " TRANSFORM[3].z = 0.0;\n"; } + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { + code += " int emit_count = 0;\n"; + switch (sub_emitter_mode) { + case SUB_EMITTER_CONSTANT: { + code += " float interval_from = CUSTOM.y * LIFETIME - DELTA;\n"; + code += " float interval_rem = sub_emitter_frequency - mod(interval_from,sub_emitter_frequency);\n"; + code += " if (DELTA >= interval_rem) emit_count = 1;\n"; + } break; + case SUB_EMITTER_AT_COLLISION: { + //not implemented yet + } break; + case SUB_EMITTER_AT_END: { + //not implemented yet + code += " float unit_delta = DELTA/LIFETIME;\n"; + code += " float end_time = CUSTOM.w * 0.95;\n"; // if we do at the end we might miss it, as it can just get deactivated by emitter + code += " if (CUSTOM.y < end_time && (CUSTOM.y + unit_delta) >= end_time) emit_count = sub_emitter_amount_at_end;\n"; + } break; + default: { + } + } + code += " for(int i=0;i<emit_count;i++) {\n"; + code += " uint flags = FLAG_EMIT_POSITION|FLAG_EMIT_ROT_SCALE;\n"; + code += " if (sub_emitter_keep_velocity) flags|=FLAG_EMIT_VELOCITY;\n"; + code += " emit_particle(TRANSFORM,VELOCITY,vec4(0.0),vec4(0.0),flags);\n"; + code += " }"; + } + code += " if (CUSTOM.y > CUSTOM.w) {"; code += " ACTIVE = false;\n"; code += " }\n"; @@ -951,41 +972,6 @@ int ParticlesMaterial::get_emission_point_count() const { return emission_point_count; } -void ParticlesMaterial::set_trail_divisor(int p_divisor) { - trail_divisor = p_divisor; - RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); -} - -int ParticlesMaterial::get_trail_divisor() const { - return trail_divisor; -} - -void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier) { - trail_size_modifier = p_trail_size_modifier; - - Ref<CurveTexture> curve = trail_size_modifier; - if (curve.is_valid()) { - curve->ensure_default_setup(); - } - - RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, curve); - _queue_shader_change(); -} - -Ref<CurveTexture> ParticlesMaterial::get_trail_size_modifier() const { - return trail_size_modifier; -} - -void ParticlesMaterial::set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier) { - trail_color_modifier = p_trail_color_modifier; - RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, p_trail_color_modifier); - _queue_shader_change(); -} - -Ref<GradientTexture> ParticlesMaterial::get_trail_color_modifier() const { - return trail_color_modifier; -} - void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { gravity = p_gravity; Vector3 gset = gravity; @@ -1038,11 +1024,54 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const { property.usage = 0; } + if (property.name == "sub_emitter_frequency" && sub_emitter_mode != SUB_EMITTER_CONSTANT) { + property.usage = 0; + } + + if (property.name == "sub_emitter_amount_at_end" && sub_emitter_mode != SUB_EMITTER_AT_END) { + property.usage = 0; + } + if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { property.usage = 0; } } +void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { + sub_emitter_mode = p_sub_emitter_mode; + _queue_shader_change(); + _change_notify(); +} + +ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() const { + return sub_emitter_mode; +} + +void ParticlesMaterial::set_sub_emitter_frequency(float p_frequency) { + sub_emitter_frequency = p_frequency; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pas delta instead of frequency, since its easier to compute +} +float ParticlesMaterial::get_sub_emitter_frequency() const { + return sub_emitter_frequency; +} + +void ParticlesMaterial::set_sub_emitter_amount_at_end(int p_amount) { + sub_emitter_amount_at_end = p_amount; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_amount_at_end, p_amount); +} + +int ParticlesMaterial::get_sub_emitter_amount_at_end() const { + return sub_emitter_amount_at_end; +} + +void ParticlesMaterial::set_sub_emitter_keep_velocity(bool p_enable) { + sub_emitter_keep_velocity = p_enable; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_keep_velocity, p_enable); +} +bool ParticlesMaterial::get_sub_emitter_keep_velocity() const { + return sub_emitter_keep_velocity; +} + Shader::Mode ParticlesMaterial::get_shader_mode() const { return Shader::MODE_PARTICLES; } @@ -1096,27 +1125,27 @@ void ParticlesMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); - ClassDB::bind_method(D_METHOD("set_trail_divisor", "divisor"), &ParticlesMaterial::set_trail_divisor); - ClassDB::bind_method(D_METHOD("get_trail_divisor"), &ParticlesMaterial::get_trail_divisor); - - ClassDB::bind_method(D_METHOD("set_trail_size_modifier", "texture"), &ParticlesMaterial::set_trail_size_modifier); - ClassDB::bind_method(D_METHOD("get_trail_size_modifier"), &ParticlesMaterial::get_trail_size_modifier); - - ClassDB::bind_method(D_METHOD("set_trail_color_modifier", "texture"), &ParticlesMaterial::set_trail_color_modifier); - ClassDB::bind_method(D_METHOD("get_trail_color_modifier"), &ParticlesMaterial::get_trail_color_modifier); - ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "randomness"), &ParticlesMaterial::set_lifetime_randomness); ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &ParticlesMaterial::get_lifetime_randomness); + ClassDB::bind_method(D_METHOD("get_sub_emitter_mode"), &ParticlesMaterial::get_sub_emitter_mode); + ClassDB::bind_method(D_METHOD("set_sub_emitter_mode", "mode"), &ParticlesMaterial::set_sub_emitter_mode); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_frequency"), &ParticlesMaterial::get_sub_emitter_frequency); + ClassDB::bind_method(D_METHOD("set_sub_emitter_frequency", "hz"), &ParticlesMaterial::set_sub_emitter_frequency); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_end"), &ParticlesMaterial::get_sub_emitter_amount_at_end); + ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_end", "amount"), &ParticlesMaterial::set_sub_emitter_amount_at_end); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticlesMaterial::get_sub_emitter_keep_velocity); + ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticlesMaterial::set_sub_emitter_keep_velocity); + ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); - ADD_GROUP("Trail", "trail_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_divisor", PROPERTY_HINT_RANGE, "1,1000000,1"), "set_trail_divisor", "get_trail_divisor"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_color_modifier", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_trail_color_modifier", "get_trail_color_modifier"); + ADD_GROUP("Emission Shape", "emission_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius"); @@ -1186,6 +1215,12 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET); + ADD_GROUP("Sub Emitter", "sub_emitter_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled,Constant,AtEnd,AtCollision"), "set_sub_emitter_mode", "get_sub_emitter_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sub_emitter_frequency", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_sub_emitter_frequency", "get_sub_emitter_frequency"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_amount_at_end", PROPERTY_HINT_RANGE, "1,32,1"), "set_sub_emitter_amount_at_end", "get_sub_emitter_amount_at_end"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sub_emitter_keep_velocity"), "set_sub_emitter_keep_velocity", "get_sub_emitter_keep_velocity"); + BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY); BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY); @@ -1233,11 +1268,15 @@ ParticlesMaterial::ParticlesMaterial() : set_emission_shape(EMISSION_SHAPE_POINT); set_emission_sphere_radius(1); set_emission_box_extents(Vector3(1, 1, 1)); - set_trail_divisor(1); set_gravity(Vector3(0, -9.8, 0)); set_lifetime_randomness(0); emission_point_count = 1; + set_sub_emitter_mode(SUB_EMITTER_DISABLED); + set_sub_emitter_frequency(4); + set_sub_emitter_amount_at_end(1); + set_sub_emitter_keep_velocity(false); + for (int i = 0; i < PARAM_MAX; i++) { set_param_randomness(Parameter(i), 0); } diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index 1c1b6c92f9..9d41c91937 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -34,6 +34,17 @@ #ifndef PARTICLES_MATERIAL_H #define PARTICLES_MATERIAL_H +/* + TODO: +-Path following +*Manual emission +-Sub Emitters +-Attractors +-Emitter positions deformable by bones +-Collision +-Proper trails +*/ + class ParticlesMaterial : public Material { GDCLASS(ParticlesMaterial, Material); @@ -71,6 +82,14 @@ public: EMISSION_SHAPE_MAX }; + enum SubEmitterMode { + SUB_EMITTER_DISABLED, + SUB_EMITTER_CONSTANT, + SUB_EMITTER_AT_END, + SUB_EMITTER_AT_COLLISION, + SUB_EMITTER_MAX + }; + private: union MaterialKey { struct { @@ -78,10 +97,9 @@ private: uint32_t texture_color : 1; uint32_t flags : 4; uint32_t emission_shape : 2; - uint32_t trail_size_texture : 1; - uint32_t trail_color_texture : 1; uint32_t invalid_key : 1; uint32_t has_emission_color : 1; + uint32_t sub_emitter : 2; }; uint32_t key; @@ -116,9 +134,8 @@ private: mk.texture_color = color_ramp.is_valid() ? 1 : 0; mk.emission_shape = emission_shape; - mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; - mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); + mk.sub_emitter = sub_emitter_mode; return mk; } @@ -178,13 +195,13 @@ private: StringName emission_texture_normal; StringName emission_texture_color; - StringName trail_divisor; - StringName trail_size_modifier; - StringName trail_color_modifier; - StringName gravity; StringName lifetime_randomness; + + StringName sub_emitter_frequency; + StringName sub_emitter_amount_at_end; + StringName sub_emitter_keep_velocity; }; static ShaderNames *shader_names; @@ -218,15 +235,14 @@ private: bool anim_loop; - int trail_divisor; - - Ref<CurveTexture> trail_size_modifier; - Ref<GradientTexture> trail_color_modifier; - Vector3 gravity; float lifetime_randomness; + SubEmitterMode sub_emitter_mode; + float sub_emitter_frequency; + int sub_emitter_amount_at_end; + bool sub_emitter_keep_velocity; //do not save emission points here protected: @@ -277,15 +293,6 @@ public: Ref<Texture2D> get_emission_color_texture() const; int get_emission_point_count() const; - void set_trail_divisor(int p_divisor); - int get_trail_divisor() const; - - void set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier); - Ref<CurveTexture> get_trail_size_modifier() const; - - void set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier); - Ref<GradientTexture> get_trail_color_modifier() const; - void set_gravity(const Vector3 &p_gravity); Vector3 get_gravity() const; @@ -296,6 +303,18 @@ public: static void finish_shaders(); static void flush_changes(); + void set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode); + SubEmitterMode get_sub_emitter_mode() const; + + void set_sub_emitter_frequency(float p_frequency); + float get_sub_emitter_frequency() const; + + void set_sub_emitter_amount_at_end(int p_amount); + int get_sub_emitter_amount_at_end() const; + + void set_sub_emitter_keep_velocity(bool p_enable); + bool get_sub_emitter_keep_velocity() const; + RID get_shader_rid() const; virtual Shader::Mode get_shader_mode() const override; @@ -307,5 +326,6 @@ public: VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) VARIANT_ENUM_CAST(ParticlesMaterial::Flags) VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) +VARIANT_ENUM_CAST(ParticlesMaterial::SubEmitterMode) #endif // PARTICLES_MATERIAL_H diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 4249542567..92f0353abf 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -142,8 +142,6 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param); - //ClassDB::bind_method(D_METHOD("get_param_list"),&Shader::get_fragment_code); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_code", "get_code"); BIND_ENUM_CONSTANT(MODE_SPATIAL); diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp index 4479b822c0..d7a08d9eb6 100644 --- a/scene/resources/syntax_highlighter.cpp +++ b/scene/resources/syntax_highlighter.cpp @@ -125,11 +125,11 @@ void SyntaxHighlighter::_bind_methods() { //////////////////////////////////////////////////////////////////////////////// -static bool _is_char(CharType c) { +static bool _is_char(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } -static bool _is_hex_symbol(CharType c) { +static bool _is_hex_symbol(char32_t c) { return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); } @@ -195,7 +195,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) { /* search the line */ bool match = true; - const CharType *start_key = color_regions[c].start_key.c_str(); + const char32_t *start_key = color_regions[c].start_key.get_data(); for (int k = 0; k < start_key_length; k++) { if (start_key[k] != str[from + k]) { match = false; @@ -229,18 +229,16 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) { /* if we are in one find the end key */ if (in_region != -1) { - /* check there is enough room */ - int chars_left = line_length - from; - int end_key_length = color_regions[in_region].end_key.length(); - if (chars_left < end_key_length) { - continue; - } - /* search the line */ int region_end_index = -1; - const CharType *end_key = color_regions[in_region].start_key.c_str(); + int end_key_length = color_regions[in_region].end_key.length(); + const char32_t *end_key = color_regions[in_region].end_key.get_data(); for (; from < line_length; from++) { - if (!is_a_symbol) { + if (line_length - from < end_key_length) { + break; + } + + if (!is_symbol(str[from])) { continue; } @@ -249,9 +247,10 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) { continue; } + region_end_index = from; for (int k = 0; k < end_key_length; k++) { - if (end_key[k] == str[from + k]) { - region_end_index = from; + if (end_key[k] != str[from + k]) { + region_end_index = -1; break; } } @@ -265,7 +264,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) { highlighter_info["color"] = color_regions[in_region].color; color_map[j] = highlighter_info; - j = from; + j = from + (end_key_length - 1); if (region_end_index == -1) { color_region_cache[p_line] = in_region; } @@ -484,8 +483,12 @@ void CodeHighlighter::add_color_region(const String &p_start_key, const String & } } + int at = 0; for (int i = 0; i < color_regions.size(); i++) { ERR_FAIL_COND_MSG(color_regions[i].start_key == p_start_key, "color region with start key '" + p_start_key + "' already exists."); + if (p_start_key.length() < color_regions[i].start_key.length()) { + at++; + } } ColorRegion color_region; @@ -493,7 +496,7 @@ void CodeHighlighter::add_color_region(const String &p_start_key, const String & color_region.start_key = p_start_key; color_region.end_key = p_end_key; color_region.line_only = p_line_only || p_end_key == ""; - color_regions.push_back(color_region); + color_regions.insert(at, color_region); clear_highlighting_cache(); } diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 6992360df7..84b067d1e2 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -40,7 +40,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { if (slash == -1) { return false; } - int id = String::to_int(n.c_str(), slash); + int id = String::to_int(n.get_data(), slash); if (!tile_map.has(id)) { create_tile(id); @@ -216,7 +216,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { if (slash == -1) { return false; } - int id = String::to_int(n.c_str(), slash); + int id = String::to_int(n.get_data(), slash); ERR_FAIL_COND_V(!tile_map.has(id), false); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 33de24ad14..b851b4c4dc 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -172,8 +172,6 @@ void VisualShaderNode::_bind_methods() { } VisualShaderNode::VisualShaderNode() { - port_preview = -1; - simple_decl = true; } ///////////////////////////////////////////////////////// @@ -921,8 +919,11 @@ static const char *type_string[VisualShader::TYPE_MAX] = { "vertex", "fragment", "light", - "compute" + "emit", + "process", + "end" }; + bool VisualShader::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; if (name == "mode") { @@ -1345,6 +1346,19 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui return OK; } +bool VisualShader::has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const { + if (!ShaderTypes::get_singleton()->get_functions(p_mode).has(p_func_name)) { + if (p_mode == RenderingServer::ShaderMode::SHADER_PARTICLES) { + if (p_func_name == "emit" || p_func_name == "process" || p_func_name == "end") { + return true; + } + } + return false; + } + + return true; +} + void VisualShader::_update_shader() const { if (!dirty) { return; @@ -1416,14 +1430,14 @@ void VisualShader::_update_shader() const { global_code += "render_mode " + render_mode + ";\n\n"; } - static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "compute" }; + static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "emit", "process", "end" }; String global_expressions; Set<String> used_uniform_names; List<VisualShaderNodeUniform *> uniforms; for (int i = 0, index = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { continue; } @@ -1458,8 +1472,10 @@ void VisualShader::_update_shader() const { } } + Map<int, String> code_map; + for (int i = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { continue; } @@ -1467,6 +1483,8 @@ void VisualShader::_update_shader() const { VMap<ConnectionKey, const List<Connection>::Element *> input_connections; VMap<ConnectionKey, const List<Connection>::Element *> output_connections; + StringBuilder func_code; + for (const List<Connection>::Element *E = graph[i].connections.front(); E; E = E->next()) { ConnectionKey from_key; from_key.node = E->get().from_node; @@ -1480,14 +1498,30 @@ void VisualShader::_update_shader() const { input_connections.insert(to_key, E); } - - code += "\nvoid " + String(func_name[i]) + "() {\n"; + if (shader_mode != Shader::MODE_PARTICLES) { + func_code += "\nvoid " + String(func_name[i]) + "() {\n"; + } Set<int> processed; - Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes); + Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes); ERR_FAIL_COND(err != OK); insertion_pos.insert(i, code.get_string_length()); + if (shader_mode == Shader::MODE_PARTICLES) { + code_map.insert(i, func_code); + } else { + func_code += "}\n"; + code += func_code; + } + } + + if (shader_mode == Shader::MODE_PARTICLES) { + code += "\nvoid compute() {\n"; + code += "\tif (RESTART) {\n"; + code += code_map[TYPE_EMIT]; + code += "\t} else {\n"; + code += code_map[TYPE_PROCESS]; + code += "\t}\n"; code += "}\n"; } @@ -1498,7 +1532,7 @@ void VisualShader::_update_shader() const { final_code += global_expressions; String tcode = code; for (int i = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { continue; } tcode = tcode.insert(insertion_pos[i], global_code_per_func[Type(i)]); @@ -1577,6 +1611,8 @@ void VisualShader::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "version", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_version", "get_version"); + ADD_PROPERTY_DEFAULT("code", ""); // Inherited from Shader, prevents showing default code as override in docs. + BIND_ENUM_CONSTANT(TYPE_VERTEX); BIND_ENUM_CONSTANT(TYPE_FRAGMENT); BIND_ENUM_CONSTANT(TYPE_LIGHT); @@ -1587,8 +1623,6 @@ void VisualShader::_bind_methods() { } VisualShader::VisualShader() { - shader_mode = Shader::MODE_SPATIAL; - for (int i = 0; i < TYPE_MAX; i++) { Ref<VisualShaderNodeOutput> output; output.instance(); @@ -1597,8 +1631,6 @@ VisualShader::VisualShader() { graph[i].nodes[NODE_ID_OUTPUT].node = output; graph[i].nodes[NODE_ID_OUTPUT].position = Vector2(400, 150); } - - dirty = true; } /////////////////////////////////////////////////////////// @@ -1721,20 +1753,50 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, - // Particles, Compute - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + // Particles, Emit + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + + // Particles, Process + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + + // Particles, End + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Sky, Fragment { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_cubemap_pass", "AT_CUBEMAP_PASS" }, @@ -2036,10 +2098,6 @@ void VisualShaderNodeInput::_bind_methods() { } VisualShaderNodeInput::VisualShaderNodeInput() { - input_name = "[None]"; - // changed when set - shader_type = VisualShader::TYPE_MAX; - shader_mode = Shader::MODE_MAX; } ////////////// UniformRef @@ -2231,8 +2289,6 @@ Vector<StringName> VisualShaderNodeUniformRef::get_editable_properties() const { } VisualShaderNodeUniformRef::VisualShaderNodeUniformRef() { - uniform_name = "[None]"; - uniform_type = UniformType::UNIFORM_TYPE_FLOAT; } //////////////////////////////////////////// @@ -2291,13 +2347,30 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { // Canvas Item, Light { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" }, - // Particles, Compute - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + // Particles, Emit + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, + // Particles, Process + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, + // Particles, End + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, // Sky, Fragment { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR" }, { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" }, @@ -2485,7 +2558,6 @@ Vector<StringName> VisualShaderNodeUniform::get_editable_properties() const { } VisualShaderNodeUniform::VisualShaderNodeUniform() { - qualifier = QUAL_NONE; } ////////////// GroupBase @@ -2959,10 +3031,6 @@ String VisualShaderNodeGroupBase::generate_code(Shader::Mode p_mode, VisualShade } VisualShaderNodeGroupBase::VisualShaderNodeGroupBase() { - size = Size2(0, 0); - inputs = ""; - outputs = ""; - editable = false; simple_decl = false; } @@ -3087,7 +3155,6 @@ void VisualShaderNodeExpression::_bind_methods() { } VisualShaderNodeExpression::VisualShaderNodeExpression() { - expression = ""; set_editable(true); } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 4ef9db06bc..3f5266142a 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -50,7 +50,9 @@ public: TYPE_VERTEX, TYPE_FRAGMENT, TYPE_LIGHT, - TYPE_COMPUTE, + TYPE_EMIT, + TYPE_PROCESS, + TYPE_END, TYPE_MAX }; @@ -78,7 +80,7 @@ private: List<Connection> connections; } graph[TYPE_MAX]; - Shader::Mode shader_mode; + Shader::Mode shader_mode = Shader::MODE_SPATIAL; mutable String previous_code; Array _get_node_connections(Type p_type) const; @@ -95,7 +97,7 @@ private: static RenderModeEnums render_mode_enums[]; - volatile mutable bool dirty; + volatile mutable bool dirty = true; void _queue_update(); union ConnectionKey { @@ -112,6 +114,7 @@ private: Error _write_node(Type p_type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const; void _input_type_changed(Type p_type, int p_id); + bool has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const; protected: virtual void _update_shader() const override; @@ -180,7 +183,7 @@ VARIANT_ENUM_CAST(VisualShader::Type) class VisualShaderNode : public Resource { GDCLASS(VisualShaderNode, Resource); - int port_preview; + int port_preview = -1; Map<int, Variant> default_input_values; Map<int, bool> connected_input_ports; @@ -188,7 +191,7 @@ class VisualShaderNode : public Resource { int connected_output_count = 0; protected: - bool simple_decl; + bool simple_decl = true; static void _bind_methods(); public: @@ -290,8 +293,8 @@ class VisualShaderNodeInput : public VisualShaderNode { GDCLASS(VisualShaderNodeInput, VisualShaderNode); friend class VisualShader; - VisualShader::Type shader_type; - Shader::Mode shader_mode; + VisualShader::Type shader_type = VisualShader::TYPE_MAX; + Shader::Mode shader_mode = Shader::MODE_MAX; struct Port { Shader::Mode mode; @@ -304,7 +307,7 @@ class VisualShaderNodeInput : public VisualShaderNode { static const Port ports[]; static const Port preview_ports[]; - String input_name; + String input_name = "[None]"; protected: static void _bind_methods(); @@ -388,8 +391,8 @@ public: }; private: - String uniform_name; - Qualifier qualifier; + String uniform_name = ""; + Qualifier qualifier = QUAL_NONE; bool global_code_generated = false; protected: @@ -436,8 +439,8 @@ public: }; private: - String uniform_name; - UniformType uniform_type; + String uniform_name = "[None]"; + UniformType uniform_type = UniformType::UNIFORM_TYPE_FLOAT; protected: static void _bind_methods(); @@ -479,10 +482,10 @@ private: void _apply_port_changes(); protected: - Vector2 size; - String inputs; - String outputs; - bool editable; + Vector2 size = Size2(0, 0); + String inputs = ""; + String outputs = ""; + bool editable = false; struct Port { PortType type; @@ -550,7 +553,7 @@ class VisualShaderNodeExpression : public VisualShaderNodeGroupBase { GDCLASS(VisualShaderNodeExpression, VisualShaderNodeGroupBase); protected: - String expression; + String expression = ""; static void _bind_methods(); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index b0c871bc71..182aeae5d4 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -87,7 +87,6 @@ void VisualShaderNodeFloatConstant::_bind_methods() { } VisualShaderNodeFloatConstant::VisualShaderNodeFloatConstant() { - constant = 0.0; } ////////////// Scalar(Int) @@ -147,7 +146,6 @@ void VisualShaderNodeIntConstant::_bind_methods() { } VisualShaderNodeIntConstant::VisualShaderNodeIntConstant() { - constant = 0; } ////////////// Boolean @@ -207,7 +205,6 @@ void VisualShaderNodeBooleanConstant::_bind_methods() { } VisualShaderNodeBooleanConstant::VisualShaderNodeBooleanConstant() { - constant = false; } ////////////// Color @@ -271,7 +268,6 @@ void VisualShaderNodeColorConstant::_bind_methods() { } VisualShaderNodeColorConstant::VisualShaderNodeColorConstant() { - constant = Color(1, 1, 1, 1); } ////////////// Vector @@ -777,8 +773,6 @@ void VisualShaderNodeTexture::_bind_methods() { } VisualShaderNodeTexture::VisualShaderNodeTexture() { - texture_type = TYPE_DATA; - source = SOURCE_TEXTURE; } ////////////// Sample3D @@ -898,7 +892,6 @@ String VisualShaderNodeSample3D::get_warning(Shader::Mode p_mode, VisualShader:: } VisualShaderNodeSample3D::VisualShaderNodeSample3D() { - source = SOURCE_TEXTURE; simple_decl = false; } @@ -1143,8 +1136,6 @@ void VisualShaderNodeCubemap::_bind_methods() { } VisualShaderNodeCubemap::VisualShaderNodeCubemap() { - texture_type = TYPE_DATA; - source = SOURCE_TEXTURE; simple_decl = false; } @@ -1250,7 +1241,6 @@ void VisualShaderNodeFloatOp::_bind_methods() { } VisualShaderNodeFloatOp::VisualShaderNodeFloatOp() { - op = OP_ADD; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); } @@ -1345,7 +1335,6 @@ void VisualShaderNodeIntOp::_bind_methods() { } VisualShaderNodeIntOp::VisualShaderNodeIntOp() { - op = OP_ADD; set_input_port_default_value(0, 0); set_input_port_default_value(1, 0); } @@ -1460,7 +1449,6 @@ void VisualShaderNodeVectorOp::_bind_methods() { } VisualShaderNodeVectorOp::VisualShaderNodeVectorOp() { - op = OP_ADD; set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); } @@ -1628,7 +1616,6 @@ void VisualShaderNodeColorOp::_bind_methods() { } VisualShaderNodeColorOp::VisualShaderNodeColorOp() { - op = OP_SCREEN; set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); } @@ -1703,7 +1690,6 @@ void VisualShaderNodeTransformMult::_bind_methods() { } VisualShaderNodeTransformMult::VisualShaderNodeTransformMult() { - op = OP_AxB; set_input_port_default_value(0, Transform()); set_input_port_default_value(1, Transform()); } @@ -1778,7 +1764,6 @@ void VisualShaderNodeTransformVecMult::_bind_methods() { } VisualShaderNodeTransformVecMult::VisualShaderNodeTransformVecMult() { - op = OP_AxB; set_input_port_default_value(0, Transform()); set_input_port_default_value(1, Vector3()); } @@ -1908,7 +1893,6 @@ void VisualShaderNodeFloatFunc::_bind_methods() { } VisualShaderNodeFloatFunc::VisualShaderNodeFloatFunc() { - func = FUNC_SIGN; set_input_port_default_value(0, 0.0); } @@ -2003,7 +1987,6 @@ void VisualShaderNodeIntFunc::_bind_methods() { } VisualShaderNodeIntFunc::VisualShaderNodeIntFunc() { - func = FUNC_SIGN; set_input_port_default_value(0, 0); } @@ -2169,7 +2152,6 @@ void VisualShaderNodeVectorFunc::_bind_methods() { } VisualShaderNodeVectorFunc::VisualShaderNodeVectorFunc() { - func = FUNC_NORMALIZE; set_input_port_default_value(0, Vector3()); } @@ -2256,9 +2238,8 @@ void VisualShaderNodeColorFunc::_bind_methods() { } VisualShaderNodeColorFunc::VisualShaderNodeColorFunc() { - func = FUNC_GRAYSCALE; - set_input_port_default_value(0, Vector3()); simple_decl = false; + set_input_port_default_value(0, Vector3()); } ////////////// Transform Func @@ -2328,7 +2309,6 @@ void VisualShaderNodeTransformFunc::_bind_methods() { } VisualShaderNodeTransformFunc::VisualShaderNodeTransformFunc() { - func = FUNC_INVERSE; set_input_port_default_value(0, Transform()); } @@ -2516,7 +2496,6 @@ void VisualShaderNodeScalarDerivativeFunc::_bind_methods() { } VisualShaderNodeScalarDerivativeFunc::VisualShaderNodeScalarDerivativeFunc() { - func = FUNC_SUM; set_input_port_default_value(0, 0.0); } @@ -2589,7 +2568,6 @@ void VisualShaderNodeVectorDerivativeFunc::_bind_methods() { } VisualShaderNodeVectorDerivativeFunc::VisualShaderNodeVectorDerivativeFunc() { - func = FUNC_SUM; set_input_port_default_value(0, Vector3()); } @@ -3561,12 +3539,6 @@ Vector<StringName> VisualShaderNodeFloatUniform::get_editable_properties() const } VisualShaderNodeFloatUniform::VisualShaderNodeFloatUniform() { - hint = HINT_NONE; - hint_range_min = 0.0; - hint_range_max = 1.0; - hint_range_step = 0.1; - default_value_enabled = false; - default_value = 0.0; } ////////////// Integer Uniform @@ -3726,12 +3698,6 @@ Vector<StringName> VisualShaderNodeIntUniform::get_editable_properties() const { } VisualShaderNodeIntUniform::VisualShaderNodeIntUniform() { - hint = HINT_NONE; - hint_range_min = 0; - hint_range_max = 100; - hint_range_step = 1; - default_value_enabled = false; - default_value = 0; } ////////////// Boolean Uniform @@ -3824,8 +3790,6 @@ Vector<StringName> VisualShaderNodeBooleanUniform::get_editable_properties() con } VisualShaderNodeBooleanUniform::VisualShaderNodeBooleanUniform() { - default_value_enabled = false; - default_value = false; } ////////////// Color Uniform @@ -3916,8 +3880,6 @@ Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const } VisualShaderNodeColorUniform::VisualShaderNodeColorUniform() { - default_value_enabled = false; - default_value = Color(1.0, 1.0, 1.0, 1.0); } ////////////// Vector Uniform @@ -4006,8 +3968,6 @@ Vector<StringName> VisualShaderNodeVec3Uniform::get_editable_properties() const } VisualShaderNodeVec3Uniform::VisualShaderNodeVec3Uniform() { - default_value_enabled = false; - default_value = Vector3(0.0, 0.0, 0.0); } ////////////// Transform Uniform @@ -4100,8 +4060,6 @@ Vector<StringName> VisualShaderNodeTransformUniform::get_editable_properties() c } VisualShaderNodeTransformUniform::VisualShaderNodeTransformUniform() { - default_value_enabled = false; - default_value = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0); } ////////////// Texture Uniform @@ -4271,8 +4229,6 @@ bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) co } VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() { - texture_type = TYPE_DATA; - color_default = COLOR_DEFAULT_WHITE; simple_decl = false; } @@ -4577,13 +4533,13 @@ String VisualShaderNodeIf::generate_code(Shader::Mode p_mode, VisualShader::Type } VisualShaderNodeIf::VisualShaderNodeIf() { + simple_decl = false; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); set_input_port_default_value(3, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(4, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(5, Vector3(0.0, 0.0, 0.0)); - simple_decl = false; } ////////////// Switch @@ -4642,10 +4598,10 @@ String VisualShaderNodeSwitch::generate_code(Shader::Mode p_mode, VisualShader:: } VisualShaderNodeSwitch::VisualShaderNodeSwitch() { + simple_decl = false; set_input_port_default_value(0, false); set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); - simple_decl = false; } ////////////// Switch(scalar) @@ -4836,7 +4792,6 @@ void VisualShaderNodeIs::_bind_methods() { } VisualShaderNodeIs::VisualShaderNodeIs() { - func = FUNC_IS_INF; set_input_port_default_value(0, 0.0); } @@ -5072,9 +5027,6 @@ void VisualShaderNodeCompare::_bind_methods() { } VisualShaderNodeCompare::VisualShaderNodeCompare() { - ctype = CTYPE_SCALAR; - func = FUNC_EQUAL; - condition = COND_ALL; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); @@ -5167,7 +5119,6 @@ void VisualShaderNodeMultiplyAdd::_bind_methods() { } VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() { - type = TYPE_SCALAR; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, 0.0); diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index b9c40d0521..245435591b 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -39,7 +39,7 @@ class VisualShaderNodeFloatConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeFloatConstant, VisualShaderNode); - float constant; + float constant = 0.0f; protected: static void _bind_methods(); @@ -69,7 +69,7 @@ public: class VisualShaderNodeIntConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeIntConstant, VisualShaderNode); - int constant; + int constant = 0; protected: static void _bind_methods(); @@ -99,7 +99,7 @@ public: class VisualShaderNodeBooleanConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeBooleanConstant, VisualShaderNode); - bool constant; + bool constant = false; protected: static void _bind_methods(); @@ -129,7 +129,7 @@ public: class VisualShaderNodeColorConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeColorConstant, VisualShaderNode); - Color constant; + Color constant = Color(1, 1, 1, 1); protected: static void _bind_methods(); @@ -240,8 +240,8 @@ public: }; private: - Source source; - TextureType texture_type; + Source source = SOURCE_TEXTURE; + TextureType texture_type = TYPE_DATA; protected: static void _bind_methods(); @@ -294,7 +294,7 @@ public: }; protected: - Source source; + Source source = SOURCE_TEXTURE; static void _bind_methods(); @@ -360,8 +360,8 @@ public: }; private: - Source source; - TextureType texture_type; + Source source = SOURCE_TEXTURE; + TextureType texture_type = TYPE_DATA; protected: static void _bind_methods(); @@ -421,7 +421,7 @@ public: }; protected: - Operator op; + Operator op = OP_ADD; static void _bind_methods(); @@ -463,7 +463,7 @@ public: }; protected: - Operator op; + Operator op = OP_ADD; static void _bind_methods(); @@ -510,7 +510,7 @@ public: }; protected: - Operator op; + Operator op = OP_ADD; static void _bind_methods(); @@ -556,7 +556,7 @@ public: }; protected: - Operator op; + Operator op = OP_SCREEN; static void _bind_methods(); @@ -599,7 +599,7 @@ public: }; protected: - Operator op; + Operator op = OP_AxB; static void _bind_methods(); @@ -642,7 +642,7 @@ public: }; protected: - Operator op; + Operator op = OP_AxB; static void _bind_methods(); @@ -713,7 +713,7 @@ public: }; protected: - Function func; + Function func = FUNC_SIGN; static void _bind_methods(); @@ -756,7 +756,7 @@ public: }; protected: - Function func; + Function func = FUNC_SIGN; static void _bind_methods(); @@ -830,7 +830,7 @@ public: }; protected: - Function func; + Function func = FUNC_NORMALIZE; static void _bind_methods(); @@ -871,7 +871,7 @@ public: }; protected: - Function func; + Function func = FUNC_GRAYSCALE; static void _bind_methods(); @@ -912,7 +912,7 @@ public: }; protected: - Function func; + Function func = FUNC_INVERSE; static void _bind_methods(); @@ -1067,7 +1067,7 @@ public: }; protected: - Function func; + Function func = FUNC_SUM; static void _bind_methods(); @@ -1107,7 +1107,7 @@ public: }; protected: - Function func; + Function func = FUNC_SUM; static void _bind_methods(); @@ -1482,12 +1482,12 @@ public: }; private: - Hint hint; - float hint_range_min; - float hint_range_max; - float hint_range_step; - bool default_value_enabled; - float default_value; + Hint hint = HINT_NONE; + float hint_range_min = 0.0f; + float hint_range_max = 1.0f; + float hint_range_step = 0.1f; + bool default_value_enabled = false; + float default_value = 0.0f; protected: static void _bind_methods(); @@ -1544,12 +1544,12 @@ public: }; private: - Hint hint; - int hint_range_min; - int hint_range_max; - int hint_range_step; - bool default_value_enabled; - int default_value; + Hint hint = HINT_NONE; + int hint_range_min = 0; + int hint_range_max = 100; + int hint_range_step = 1; + bool default_value_enabled = false; + int default_value = 0; protected: static void _bind_methods(); @@ -1601,8 +1601,8 @@ class VisualShaderNodeBooleanUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeBooleanUniform, VisualShaderNodeUniform); private: - bool default_value_enabled; - bool default_value; + bool default_value_enabled = false; + bool default_value = false; protected: static void _bind_methods(); @@ -1640,8 +1640,8 @@ class VisualShaderNodeColorUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeColorUniform, VisualShaderNodeUniform); private: - bool default_value_enabled; - Color default_value; + bool default_value_enabled = false; + Color default_value = Color(1.0, 1.0, 1.0, 1.0); protected: static void _bind_methods(); @@ -1679,7 +1679,7 @@ class VisualShaderNodeVec3Uniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeVec3Uniform, VisualShaderNodeUniform); private: - bool default_value_enabled; + bool default_value_enabled = false; Vector3 default_value; protected: @@ -1718,8 +1718,8 @@ class VisualShaderNodeTransformUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeTransformUniform, VisualShaderNodeUniform); private: - bool default_value_enabled; - Transform default_value; + bool default_value_enabled = false; + Transform default_value = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0); protected: static void _bind_methods(); @@ -1770,8 +1770,8 @@ public: }; protected: - TextureType texture_type; - ColorDefault color_default; + TextureType texture_type = TYPE_DATA; + ColorDefault color_default = COLOR_DEFAULT_WHITE; protected: static void _bind_methods(); @@ -1973,7 +1973,7 @@ public: }; protected: - Function func; + Function func = FUNC_IS_INF; protected: static void _bind_methods(); @@ -2032,9 +2032,9 @@ public: }; protected: - ComparisonType ctype; - Function func; - Condition condition; + ComparisonType ctype = CTYPE_SCALAR; + Function func = FUNC_EQUAL; + Condition condition = COND_ALL; protected: static void _bind_methods(); @@ -2082,7 +2082,7 @@ public: }; protected: - Type type; + Type type = TYPE_SCALAR; protected: static void _bind_methods(); |