summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/animated_sprite_2d.cpp2
-rw-r--r--scene/2d/line_2d.cpp2
-rw-r--r--scene/2d/navigation_region_2d.cpp2
-rw-r--r--scene/2d/ray_cast_2d.cpp20
-rw-r--r--scene/2d/ray_cast_2d.h6
-rw-r--r--scene/2d/shape_cast_2d.cpp20
-rw-r--r--scene/2d/shape_cast_2d.h6
-rw-r--r--scene/3d/ray_cast_3d.cpp20
-rw-r--r--scene/3d/ray_cast_3d.h6
-rw-r--r--scene/gui/base_button.cpp4
-rw-r--r--scene/gui/button.cpp5
-rw-r--r--scene/gui/code_edit.cpp43
-rw-r--r--scene/gui/control.cpp5
-rw-r--r--scene/gui/label.cpp40
-rw-r--r--scene/gui/label.h1
-rw-r--r--scene/gui/line_edit.cpp17
-rw-r--r--scene/gui/line_edit.h4
-rw-r--r--scene/gui/rich_text_label.cpp77
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/gui/tab_bar.cpp552
-rw-r--r--scene/gui/tab_bar.h16
-rw-r--r--scene/gui/text_edit.cpp89
-rw-r--r--scene/gui/text_edit.h9
-rw-r--r--scene/gui/texture_button.cpp5
-rw-r--r--scene/gui/tree.cpp6
-rw-r--r--scene/gui/tree.h10
-rw-r--r--scene/main/http_request.cpp56
-rw-r--r--scene/main/scene_tree.cpp2
-rw-r--r--scene/main/viewport.cpp49
-rw-r--r--scene/main/viewport.h2
-rw-r--r--scene/register_scene_types.cpp8
-rw-r--r--scene/resources/curve.cpp14
-rw-r--r--scene/resources/default_theme/default_theme.cpp8
-rw-r--r--scene/resources/mesh.cpp4
-rw-r--r--scene/resources/text_line.cpp6
-rw-r--r--scene/resources/text_line.h2
-rw-r--r--scene/resources/text_paragraph.cpp6
-rw-r--r--scene/resources/text_paragraph.h2
-rw-r--r--scene/resources/texture.cpp4
-rw-r--r--scene/resources/texture.h6
-rw-r--r--scene/resources/visual_shader.cpp563
-rw-r--r--scene/resources/visual_shader.h8
-rw-r--r--scene/resources/visual_shader_nodes.cpp1310
-rw-r--r--scene/resources/visual_shader_nodes.h257
44 files changed, 2262 insertions, 1014 deletions
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp
index 4916eb573c..decb3d0dd8 100644
--- a/scene/2d/animated_sprite_2d.cpp
+++ b/scene/2d/animated_sprite_2d.cpp
@@ -417,7 +417,7 @@ void AnimatedSprite2D::_reset_timeout() {
void AnimatedSprite2D::set_animation(const StringName &p_animation) {
ERR_FAIL_COND_MSG(frames == nullptr, vformat("There is no animation with name '%s'.", p_animation));
- ERR_FAIL_COND_MSG(frames->get_animation_names().find(p_animation) == -1, vformat("There is no animation with name '%s'.", p_animation));
+ ERR_FAIL_COND_MSG(!frames->get_animation_names().has(p_animation), vformat("There is no animation with name '%s'.", p_animation));
if (animation == p_animation) {
return;
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 1a6aaecaa8..7f2290bdc7 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -133,7 +133,7 @@ int Line2D::get_point_count() const {
void Line2D::clear_points() {
int count = _points.size();
if (count > 0) {
- _points.resize(0);
+ _points.clear();
update();
}
}
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 34f5830d8d..4bead978f1 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -299,7 +299,7 @@ void NavigationPolygon::make_polygons_from_outlines() {
}
polygons.clear();
- vertices.resize(0);
+ vertices.clear();
Map<Vector2, int> points;
for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index 1fdd8b05a6..9521667854 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -263,26 +263,18 @@ void RayCast2D::add_exception_rid(const RID &p_rid) {
exclude.insert(p_rid);
}
-void RayCast2D::add_exception(const Object *p_object) {
- ERR_FAIL_NULL(p_object);
- const CollisionObject2D *co = Object::cast_to<CollisionObject2D>(p_object);
- if (!co) {
- return;
- }
- add_exception_rid(co->get_rid());
+void RayCast2D::add_exception(const CollisionObject2D *p_node) {
+ ERR_FAIL_NULL_MSG(p_node, "The passed Node must be an instance of CollisionObject2D.");
+ add_exception_rid(p_node->get_rid());
}
void RayCast2D::remove_exception_rid(const RID &p_rid) {
exclude.erase(p_rid);
}
-void RayCast2D::remove_exception(const Object *p_object) {
- ERR_FAIL_NULL(p_object);
- const CollisionObject2D *co = Object::cast_to<CollisionObject2D>(p_object);
- if (!co) {
- return;
- }
- remove_exception_rid(co->get_rid());
+void RayCast2D::remove_exception(const CollisionObject2D *p_node) {
+ ERR_FAIL_NULL_MSG(p_node, "The passed Node must be an instance of CollisionObject2D.");
+ remove_exception_rid(p_node->get_rid());
}
void RayCast2D::clear_exceptions() {
diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h
index a1015c6ce0..2c6f2d5c00 100644
--- a/scene/2d/ray_cast_2d.h
+++ b/scene/2d/ray_cast_2d.h
@@ -33,6 +33,8 @@
#include "scene/2d/node_2d.h"
+class CollisionObject2D;
+
class RayCast2D : public Node2D {
GDCLASS(RayCast2D, Node2D);
@@ -94,9 +96,9 @@ public:
Vector2 get_collision_normal() const;
void add_exception_rid(const RID &p_rid);
- void add_exception(const Object *p_object);
+ void add_exception(const CollisionObject2D *p_node);
void remove_exception_rid(const RID &p_rid);
- void remove_exception(const Object *p_object);
+ void remove_exception(const CollisionObject2D *p_node);
void clear_exceptions();
RayCast2D();
diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/shape_cast_2d.cpp
index 10194861b4..24199c96b5 100644
--- a/scene/2d/shape_cast_2d.cpp
+++ b/scene/2d/shape_cast_2d.cpp
@@ -322,26 +322,18 @@ void ShapeCast2D::add_exception_rid(const RID &p_rid) {
exclude.insert(p_rid);
}
-void ShapeCast2D::add_exception(const Object *p_object) {
- ERR_FAIL_NULL(p_object);
- const CollisionObject2D *co = Object::cast_to<CollisionObject2D>(p_object);
- if (!co) {
- return;
- }
- add_exception_rid(co->get_rid());
+void ShapeCast2D::add_exception(const CollisionObject2D *p_node) {
+ ERR_FAIL_NULL_MSG(p_node, "The passed Node must be an instance of CollisionObject2D.");
+ add_exception_rid(p_node->get_rid());
}
void ShapeCast2D::remove_exception_rid(const RID &p_rid) {
exclude.erase(p_rid);
}
-void ShapeCast2D::remove_exception(const Object *p_object) {
- ERR_FAIL_NULL(p_object);
- const CollisionObject2D *co = Object::cast_to<CollisionObject2D>(p_object);
- if (!co) {
- return;
- }
- remove_exception_rid(co->get_rid());
+void ShapeCast2D::remove_exception(const CollisionObject2D *p_node) {
+ ERR_FAIL_NULL_MSG(p_node, "The passed Node must be an instance of CollisionObject2D.");
+ remove_exception_rid(p_node->get_rid());
}
void ShapeCast2D::clear_exceptions() {
diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/shape_cast_2d.h
index 7e1ebeb315..ea36b25068 100644
--- a/scene/2d/shape_cast_2d.h
+++ b/scene/2d/shape_cast_2d.h
@@ -34,6 +34,8 @@
#include "scene/2d/node_2d.h"
#include "scene/resources/shape_2d.h"
+class CollisionObject2D;
+
class ShapeCast2D : public Node2D {
GDCLASS(ShapeCast2D, Node2D);
@@ -109,9 +111,9 @@ public:
real_t get_closest_collision_unsafe_fraction() const;
void add_exception_rid(const RID &p_rid);
- void add_exception(const Object *p_object);
+ void add_exception(const CollisionObject2D *p_node);
void remove_exception_rid(const RID &p_rid);
- void remove_exception(const Object *p_object);
+ void remove_exception(const CollisionObject2D *p_node);
void clear_exceptions();
TypedArray<String> get_configuration_warnings() const override;
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index 3bb65d07a0..b71c54dcf9 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -243,26 +243,18 @@ void RayCast3D::add_exception_rid(const RID &p_rid) {
exclude.insert(p_rid);
}
-void RayCast3D::add_exception(const Object *p_object) {
- ERR_FAIL_NULL(p_object);
- const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object);
- if (!co) {
- return;
- }
- add_exception_rid(co->get_rid());
+void RayCast3D::add_exception(const CollisionObject3D *p_node) {
+ ERR_FAIL_NULL_MSG(p_node, "The passed Node must be an instance of CollisionObject3D.");
+ add_exception_rid(p_node->get_rid());
}
void RayCast3D::remove_exception_rid(const RID &p_rid) {
exclude.erase(p_rid);
}
-void RayCast3D::remove_exception(const Object *p_object) {
- ERR_FAIL_NULL(p_object);
- const CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_object);
- if (!co) {
- return;
- }
- remove_exception_rid(co->get_rid());
+void RayCast3D::remove_exception(const CollisionObject3D *p_node) {
+ ERR_FAIL_NULL_MSG(p_node, "The passed Node must be an instance of CollisionObject3D.");
+ remove_exception_rid(p_node->get_rid());
}
void RayCast3D::clear_exceptions() {
diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h
index a53e2c83fc..ad85001591 100644
--- a/scene/3d/ray_cast_3d.h
+++ b/scene/3d/ray_cast_3d.h
@@ -33,6 +33,8 @@
#include "scene/3d/node_3d.h"
+class CollisionObject3D;
+
class RayCast3D : public Node3D {
GDCLASS(RayCast3D, Node3D);
@@ -116,9 +118,9 @@ public:
Vector3 get_collision_normal() const;
void add_exception_rid(const RID &p_rid);
- void add_exception(const Object *p_object);
+ void add_exception(const CollisionObject3D *p_node);
void remove_exception_rid(const RID &p_rid);
- void remove_exception(const Object *p_object);
+ void remove_exception(const CollisionObject3D *p_node);
void clear_exceptions();
RayCast3D();
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 5f937acb8d..ec451b07cf 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -444,6 +444,7 @@ void BaseButton::_bind_methods() {
ADD_SIGNAL(MethodInfo("button_up"));
ADD_SIGNAL(MethodInfo("button_down"));
ADD_SIGNAL(MethodInfo("toggled", PropertyInfo(Variant::BOOL, "button_pressed")));
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_in_tooltip"), "set_shortcut_in_tooltip", "is_shortcut_in_tooltip_enabled");
@@ -503,7 +504,8 @@ BaseButton *ButtonGroup::get_pressed_button() {
void ButtonGroup::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_pressed_button"), &ButtonGroup::get_pressed_button);
ClassDB::bind_method(D_METHOD("get_buttons"), &ButtonGroup::_get_buttons);
- ADD_SIGNAL(MethodInfo("pressed", PropertyInfo(Variant::OBJECT, "button")));
+
+ ADD_SIGNAL(MethodInfo("pressed", PropertyInfo(Variant::OBJECT, "button", PROPERTY_HINT_RESOURCE_TYPE, "BaseButton")));
}
ButtonGroup::ButtonGroup() {
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 552dd28513..3ed1b873af 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -197,6 +197,8 @@ void Button::_notification(int p_what) {
color = get_theme_color(SNAME("font_disabled_color"));
if (has_theme_color(SNAME("icon_disabled_color"))) {
color_icon = get_theme_color(SNAME("icon_disabled_color"));
+ } else {
+ color_icon.a = 0.4;
}
} break;
@@ -232,9 +234,6 @@ void Button::_notification(int p_what) {
}
if (!_icon.is_null()) {
int valign = size.height - style->get_minimum_size().y;
- if (is_disabled()) {
- color_icon.a = 0.4;
- }
float icon_ofs_region = 0.0;
Point2 style_offset;
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 5511a1d910..22def607ed 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -571,6 +571,8 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
// Overridable actions
void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode) {
bool had_selection = has_selection();
+ String selection_text = (had_selection ? get_selected_text() : "");
+
if (had_selection) {
begin_complex_operation();
delete_selection();
@@ -591,27 +593,38 @@ void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode) {
if (auto_brace_completion_enabled) {
int cl = get_caret_line();
int cc = get_caret_column();
- int caret_move_offset = 1;
-
- int post_brace_pair = cc < get_line(cl).length() ? _get_auto_brace_pair_close_at_pos(cl, cc) : -1;
- if (has_string_delimiter(chr) && cc > 0 && _is_char(get_line(cl)[cc - 1]) && post_brace_pair == -1) {
- insert_text_at_caret(chr);
- } else if (cc < get_line(cl).length() && _is_char(get_line(cl)[cc])) {
- insert_text_at_caret(chr);
- } else if (post_brace_pair != -1 && auto_brace_completion_pairs[post_brace_pair].close_key[0] == chr[0]) {
- caret_move_offset = auto_brace_completion_pairs[post_brace_pair].close_key.length();
- } else if (is_in_comment(cl, cc) != -1 || (is_in_string(cl, cc) != -1 && has_string_delimiter(chr))) {
+ if (had_selection) {
insert_text_at_caret(chr);
+
+ String close_key = get_auto_brace_completion_close_key(chr);
+ if (!close_key.is_empty()) {
+ insert_text_at_caret(selection_text + close_key);
+ set_caret_column(get_caret_column() - 1);
+ }
} else {
- insert_text_at_caret(chr);
+ int caret_move_offset = 1;
+
+ int post_brace_pair = cc < get_line(cl).length() ? _get_auto_brace_pair_close_at_pos(cl, cc) : -1;
+
+ if (has_string_delimiter(chr) && cc > 0 && _is_char(get_line(cl)[cc - 1]) && post_brace_pair == -1) {
+ insert_text_at_caret(chr);
+ } else if (cc < get_line(cl).length() && _is_char(get_line(cl)[cc])) {
+ insert_text_at_caret(chr);
+ } else if (post_brace_pair != -1 && auto_brace_completion_pairs[post_brace_pair].close_key[0] == chr[0]) {
+ caret_move_offset = auto_brace_completion_pairs[post_brace_pair].close_key.length();
+ } else if (is_in_comment(cl, cc) != -1 || (is_in_string(cl, cc) != -1 && has_string_delimiter(chr))) {
+ insert_text_at_caret(chr);
+ } else {
+ insert_text_at_caret(chr);
- int pre_brace_pair = _get_auto_brace_pair_open_at_pos(cl, cc + 1);
- if (pre_brace_pair != -1) {
- insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key);
+ int pre_brace_pair = _get_auto_brace_pair_open_at_pos(cl, cc + 1);
+ if (pre_brace_pair != -1) {
+ insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key);
+ }
}
+ set_caret_column(cc + caret_move_offset);
}
- set_caret_column(cc + caret_move_offset);
} else {
insert_text_at_caret(chr);
}
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 562ea8a8f7..7ebc5c27f8 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -576,6 +576,11 @@ void Control::_update_canvas_item_transform() {
Transform2D xform = _get_internal_transform();
xform[2] += get_position();
+ // We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot()
+ if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) {
+ xform[2] = xform[2].round();
+ }
+
RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform);
}
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index fab420d593..852aaaab24 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -82,9 +82,11 @@ void Label::_shape() {
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
int width = (get_size().width - style->get_minimum_size().width);
- if (dirty) {
+ if (dirty || font_dirty) {
String lang = (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale();
- TS->shaped_text_clear(text_rid);
+ if (dirty) {
+ TS->shaped_text_clear(text_rid);
+ }
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
TS->shaped_text_set_direction(text_rid, is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
@@ -97,9 +99,17 @@ void Label::_shape() {
if (visible_chars >= 0 && visible_chars_behavior == VC_CHARS_BEFORE_SHAPING) {
text = text.substr(0, visible_chars);
}
- TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, lang);
+ if (dirty) {
+ TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, lang);
+ } else {
+ int spans = TS->shaped_get_span_count(text_rid);
+ for (int i = 0; i < spans; i++) {
+ TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features);
+ }
+ }
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, text));
dirty = false;
+ font_dirty = false;
lines_dirty = true;
}
@@ -276,7 +286,7 @@ void Label::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true);
}
- if (dirty || lines_dirty) {
+ if (dirty || font_dirty || lines_dirty) {
_shape();
}
@@ -521,7 +531,7 @@ void Label::_notification(int p_what) {
}
if (p_what == NOTIFICATION_THEME_CHANGED) {
- dirty = true;
+ font_dirty = true;
update();
}
if (p_what == NOTIFICATION_RESIZED) {
@@ -531,7 +541,7 @@ void Label::_notification(int p_what) {
Size2 Label::get_minimum_size() const {
// don't want to mutable everything
- if (dirty || lines_dirty) {
+ if (dirty || font_dirty || lines_dirty) {
const_cast<Label *>(this)->_shape();
}
@@ -555,7 +565,7 @@ int Label::get_line_count() const {
if (!is_inside_tree()) {
return 1;
}
- if (dirty || lines_dirty) {
+ if (dirty || font_dirty || lines_dirty) {
const_cast<Label *>(this)->_shape();
}
@@ -630,7 +640,7 @@ void Label::set_text_direction(Control::TextDirection p_text_direction) {
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (text_direction != p_text_direction) {
text_direction = p_text_direction;
- dirty = true;
+ font_dirty = true;
update();
}
}
@@ -638,7 +648,7 @@ void Label::set_text_direction(Control::TextDirection p_text_direction) {
void Label::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) {
if (st_parser != p_parser) {
st_parser = p_parser;
- dirty = true;
+ font_dirty = true;
update();
}
}
@@ -649,7 +659,7 @@ Control::StructuredTextParser Label::get_structured_text_bidi_override() const {
void Label::set_structured_text_bidi_override_options(Array p_args) {
st_args = p_args;
- dirty = true;
+ font_dirty = true;
update();
}
@@ -663,7 +673,7 @@ Control::TextDirection Label::get_text_direction() const {
void Label::clear_opentype_features() {
opentype_features.clear();
- dirty = true;
+ font_dirty = true;
update();
}
@@ -671,7 +681,7 @@ void Label::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
- dirty = true;
+ font_dirty = true;
update();
}
}
@@ -798,7 +808,7 @@ int Label::get_max_lines_visible() const {
}
int Label::get_total_character_count() const {
- if (dirty || lines_dirty) {
+ if (dirty || font_dirty || lines_dirty) {
const_cast<Label *>(this)->_shape();
}
@@ -814,13 +824,13 @@ bool Label::_set(const StringName &p_name, const Variant &p_value) {
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
- dirty = true;
+ font_dirty = true;
update();
}
} else {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
- dirty = true;
+ font_dirty = true;
update();
}
}
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 354e9c664d..0b931b3084 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -73,6 +73,7 @@ private:
bool lines_dirty = true;
bool dirty = true;
+ bool font_dirty = true;
RID text_rid;
Vector<RID> lines_rid;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 88953fa7db..3aae3377bc 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -752,7 +752,7 @@ void LineEdit::_notification(int p_what) {
// Draw placeholder color.
if (using_placeholder) {
- font_color.a *= placeholder_alpha;
+ font_color = get_theme_color(SNAME("font_placeholder_color"));
}
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
@@ -1476,15 +1476,6 @@ String LineEdit::get_placeholder() const {
return placeholder;
}
-void LineEdit::set_placeholder_alpha(float p_alpha) {
- placeholder_alpha = p_alpha;
- update();
-}
-
-float LineEdit::get_placeholder_alpha() const {
- return placeholder_alpha;
-}
-
void LineEdit::set_caret_column(int p_column) {
if (p_column > (int)text.length()) {
p_column = text.length();
@@ -2245,8 +2236,6 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &LineEdit::get_structured_text_bidi_override_options);
ClassDB::bind_method(D_METHOD("set_placeholder", "text"), &LineEdit::set_placeholder);
ClassDB::bind_method(D_METHOD("get_placeholder"), &LineEdit::get_placeholder);
- ClassDB::bind_method(D_METHOD("set_placeholder_alpha", "alpha"), &LineEdit::set_placeholder_alpha);
- ClassDB::bind_method(D_METHOD("get_placeholder_alpha"), &LineEdit::get_placeholder_alpha);
ClassDB::bind_method(D_METHOD("set_caret_column", "position"), &LineEdit::set_caret_column);
ClassDB::bind_method(D_METHOD("get_caret_column"), &LineEdit::get_caret_column);
ClassDB::bind_method(D_METHOD("get_scroll_offset"), &LineEdit::get_scroll_offset);
@@ -2328,6 +2317,7 @@ void LineEdit::_bind_methods() {
BIND_ENUM_CONSTANT(MENU_MAX);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_max_length", "get_max_length");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
@@ -2349,9 +2339,6 @@ void LineEdit::_bind_methods() {
ADD_GROUP("Structured Text", "structured_text_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
- ADD_GROUP("Placeholder", "placeholder_");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha");
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "set_caret_blink_enabled", "is_caret_blink_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "set_caret_blink_speed", "get_caret_blink_speed");
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 0c313f71c2..1519c09d73 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -82,7 +82,6 @@ private:
String placeholder;
String placeholder_translated;
String secret_character = "*";
- float placeholder_alpha = 0.6;
String ime_text;
Point2 ime_selection;
@@ -262,9 +261,6 @@ public:
void set_placeholder(String p_text);
String get_placeholder() const;
- void set_placeholder_alpha(float p_alpha);
- float get_placeholder_alpha() const;
-
void set_caret_column(int p_column);
int get_caret_column() const;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 151ae2f092..8f4c063c58 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -205,6 +205,49 @@ String RichTextLabel::_letters(int p_num, bool p_capitalize) const {
return s;
}
+void RichTextLabel::_update_line_font(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size) {
+ ERR_FAIL_COND(p_frame == nullptr);
+ ERR_FAIL_COND(p_line < 0 || p_line >= p_frame->lines.size());
+
+ Line &l = p_frame->lines.write[p_line];
+
+ RID t = l.text_buf->get_rid();
+ int spans = TS->shaped_get_span_count(t);
+ for (int i = 0; i < spans; i++) {
+ ItemText *it = (ItemText *)(uint64_t)TS->shaped_get_span_meta(t, i);
+ if (it) {
+ Ref<Font> font = _find_font(it);
+ if (font.is_null()) {
+ font = p_base_font;
+ }
+ int font_size = _find_font_size(it);
+ if (font_size == -1) {
+ font_size = p_base_font_size;
+ }
+ Dictionary font_ftr = _find_font_features(it);
+ TS->shaped_set_span_update_font(t, i, font->get_rids(), font_size, font_ftr);
+ }
+ }
+
+ Item *it_to = (p_line + 1 < p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr;
+ for (Item *it = l.from; it && it != it_to; it = _get_next_item(it)) {
+ switch (it->type) {
+ case ITEM_TABLE: {
+ ItemTable *table = static_cast<ItemTable *>(it);
+ for (Item *E : table->subitems) {
+ ERR_CONTINUE(E->type != ITEM_FRAME); // Children should all be frames.
+ ItemFrame *frame = static_cast<ItemFrame *>(E);
+ for (int i = 0; i < frame->lines.size(); i++) {
+ _update_line_font(frame, i, p_base_font, p_base_font_size);
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+}
+
void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width) {
ERR_FAIL_COND(p_frame == nullptr);
ERR_FAIL_COND(p_line < 0 || p_line >= p_frame->lines.size());
@@ -449,7 +492,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
}
remaining_characters -= tx.length();
- l.text_buf->add_string(tx, font, font_size, font_ftr, lang);
+ l.text_buf->add_string(tx, font, font_size, font_ftr, lang, (uint64_t)it);
text += tx;
l.char_count += tx.length();
} break;
@@ -1448,7 +1491,10 @@ void RichTextLabel::_notification(int p_what) {
update();
} break;
- case NOTIFICATION_THEME_CHANGED:
+ case NOTIFICATION_THEME_CHANGED: {
+ main->first_invalid_font_line = 0; //invalidate ALL
+ update();
+ } break;
case NOTIFICATION_ENTER_TREE: {
if (!text.is_empty()) {
set_text(text);
@@ -1545,6 +1591,10 @@ Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const
return get_default_cursor_shape(); //invalid
}
+ if (main->first_invalid_font_line < main->lines.size()) {
+ return get_default_cursor_shape(); //invalid
+ }
+
if (main->first_resized_line < main->lines.size()) {
return get_default_cursor_shape(); //invalid
}
@@ -1569,6 +1619,9 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
if (main->first_invalid_line < main->lines.size()) {
return;
}
+ if (main->first_invalid_font_line < main->lines.size()) {
+ return;
+ }
if (main->first_resized_line < main->lines.size()) {
return;
}
@@ -1732,6 +1785,9 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
if (main->first_invalid_line < main->lines.size()) {
return;
}
+ if (main->first_invalid_font_line < main->lines.size()) {
+ return;
+ }
if (main->first_resized_line < main->lines.size()) {
return;
}
@@ -2184,6 +2240,18 @@ bool RichTextLabel::_find_layout_subitem(Item *from, Item *to) {
void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
if (p_frame->first_invalid_line == p_frame->lines.size()) {
+ Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
+ int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
+
+ // Update fonts.
+ if (p_frame->first_invalid_font_line != p_frame->lines.size()) {
+ for (int i = p_frame->first_invalid_font_line; i < p_frame->lines.size(); i++) {
+ _update_line_font(p_frame, i, base_font, base_font_size);
+ }
+ p_frame->first_resized_line = p_frame->first_invalid_font_line;
+ p_frame->first_invalid_font_line = p_frame->lines.size();
+ }
+
if (p_frame->first_resized_line == p_frame->lines.size()) {
return;
}
@@ -2191,9 +2259,6 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
// Resize lines without reshaping.
Rect2 text_rect = _get_text_rect();
- Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
- int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
-
for (int i = p_frame->first_resized_line; i < p_frame->lines.size(); i++) {
_resize_line(p_frame, i, base_font, base_font_size, text_rect.get_size().width - scroll_w);
}
@@ -2237,6 +2302,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
p_frame->first_invalid_line = p_frame->lines.size();
p_frame->first_resized_line = p_frame->lines.size();
+ p_frame->first_invalid_font_line = p_frame->lines.size();
updating_scroll = true;
vscroll->set_max(total_height);
@@ -4494,6 +4560,7 @@ RichTextLabel::RichTextLabel() {
main->lines.write[0].from = main;
main->first_invalid_line = 0;
main->first_resized_line = 0;
+ main->first_invalid_font_line = 0;
current_frame = main;
vscroll = memnew(VScrollBar);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 70467e7e7c..2b24da4c37 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -129,6 +129,7 @@ private:
Vector<Line> lines;
int first_invalid_line = 0;
+ int first_invalid_font_line = 0;
int first_resized_line = 0;
ItemFrame *parent_frame = nullptr;
@@ -414,6 +415,7 @@ private:
void _shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width, int *r_char_offset);
void _resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width);
+ void _update_line_font(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size);
int _draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs);
float _find_click_in_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr);
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index 9da030f0a2..5a551ec5a5 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -38,48 +38,71 @@
#include "scene/gui/texture_rect.h"
Size2 TabBar::get_minimum_size() const {
+ Size2 ms;
+
+ if (tabs.is_empty()) {
+ return ms;
+ }
+
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
+ Ref<StyleBox> button_highlight = get_theme_stylebox(SNAME("button_highlight"));
+ Ref<Texture2D> close = get_theme_icon(SNAME("close"));
+ int hseparation = get_theme_constant(SNAME("hseparation"));
int y_margin = MAX(MAX(tab_unselected->get_minimum_size().height, tab_selected->get_minimum_size().height), tab_disabled->get_minimum_size().height);
- Size2 ms(0, 0);
-
for (int i = 0; i < tabs.size(); i++) {
- Ref<Texture2D> tex = tabs[i].icon;
- if (tex.is_valid()) {
- ms.height = MAX(ms.height, tex->get_size().height);
- if (!tabs[i].text.is_empty()) {
- ms.width += get_theme_constant(SNAME("hseparation"));
- }
+ if (tabs[i].hidden) {
+ continue;
}
- ms.width += Math::ceil(tabs[i].text_buf->get_size().x);
- ms.height = MAX(ms.height, tabs[i].text_buf->get_size().y + y_margin);
+ int ofs = ms.width;
+ Ref<StyleBox> style;
if (tabs[i].disabled) {
- ms.width += tab_disabled->get_minimum_size().width;
+ style = tab_disabled;
} else if (current == i) {
- ms.width += tab_selected->get_minimum_size().width;
+ style = tab_selected;
} else {
- ms.width += tab_unselected->get_minimum_size().width;
+ style = tab_unselected;
+ }
+ ms.width += style->get_minimum_size().width;
+
+ Ref<Texture2D> tex = tabs[i].icon;
+ if (tex.is_valid()) {
+ ms.height = MAX(ms.height, tex->get_size().height);
+ ms.width += tex->get_size().width + hseparation;
}
+ if (!tabs[i].text.is_empty()) {
+ ms.width += tabs[i].size_text + hseparation;
+ }
+ ms.height = MAX(ms.height, tabs[i].text_buf->get_size().y + y_margin);
+
+ bool close_visible = cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current);
+
if (tabs[i].right_button.is_valid()) {
Ref<Texture2D> rb = tabs[i].right_button;
- Size2 bms = rb->get_size();
- bms.width += get_theme_constant(SNAME("hseparation"));
- ms.width += bms.width;
- ms.height = MAX(bms.height + tab_unselected->get_minimum_size().height, ms.height);
+
+ if (close_visible) {
+ ms.width += button_highlight->get_minimum_size().width + rb->get_width();
+ } else {
+ ms.width += button_highlight->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
+ }
+
+ ms.height = MAX(rb->get_height() + style->get_minimum_size().height, ms.height);
+ }
+
+ if (close_visible) {
+ ms.width += button_highlight->get_margin(SIDE_LEFT) + close->get_width() + hseparation;
+
+ ms.height = MAX(close->get_height() + style->get_minimum_size().height, ms.height);
}
- if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
- Size2 bms = cb->get_size();
- bms.width += get_theme_constant(SNAME("hseparation"));
- ms.width += bms.width;
- ms.height = MAX(bms.height + tab_unselected->get_minimum_size().height, ms.height);
+ if (ms.width - ofs > style->get_minimum_size().width) {
+ ms.width -= hseparation;
}
}
@@ -165,8 +188,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
if (rb_hover != -1) {
- // Right mouse button clicked.
- emit_signal(SNAME("tab_rmb_clicked"), rb_hover);
+ emit_signal(SNAME("tab_button_pressed"), rb_hover);
}
rb_pressing = false;
@@ -175,7 +197,6 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
if (cb_hover != -1) {
- // Close button pressed.
emit_signal(SNAME("tab_close_pressed"), cb_hover);
}
@@ -184,7 +205,6 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
}
if (mb->is_pressed() && (mb->get_button_index() == MouseButton::LEFT || (select_with_rmb && mb->get_button_index() == MouseButton::RIGHT))) {
- // Clicks.
Point2 pos = mb->get_position();
if (buttons_visible) {
@@ -234,6 +254,10 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
int found = -1;
for (int i = offset; i <= max_drawn_tab; i++) {
+ if (tabs[i].hidden) {
+ continue;
+ }
+
if (tabs[i].rb_rect.has_point(pos)) {
rb_pressing = true;
update();
@@ -256,6 +280,12 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
if (found != -1) {
set_current_tab(found);
+
+ if (mb->get_button_index() == MouseButton::RIGHT) {
+ // Right mouse button clicked.
+ emit_signal(SNAME("tab_rmb_clicked"), found);
+ }
+
emit_signal(SNAME("tab_clicked"), found);
}
}
@@ -275,13 +305,12 @@ void TabBar::_shape(int p_tab) {
tabs.write[p_tab].text_buf->set_direction((TextServer::Direction)tabs[p_tab].text_direction);
}
- tabs.write[p_tab].text_buf->add_string(tabs.write[p_tab].xl_text, font, font_size, tabs[p_tab].opentype_features, !tabs[p_tab].language.is_empty() ? tabs[p_tab].language : TranslationServer::get_singleton()->get_tool_locale());
+ tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, font, font_size, tabs[p_tab].opentype_features, !tabs[p_tab].language.is_empty() ? tabs[p_tab].language : TranslationServer::get_singleton()->get_tool_locale());
}
void TabBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- _update_cache();
update();
} break;
case NOTIFICATION_THEME_CHANGED:
@@ -289,14 +318,19 @@ void TabBar::_notification(int p_what) {
for (int i = 0; i < tabs.size(); ++i) {
_shape(i);
}
- _update_cache();
- update_minimum_size();
- update();
- } break;
+
+ [[fallthrough]];
+ }
case NOTIFICATION_RESIZED: {
+ int ofs_old = offset;
+ int max_old = max_drawn_tab;
+
_update_cache();
_ensure_no_over_offset();
- ensure_tab_visible(current);
+
+ if (scroll_to_selected && (offset != ofs_old || max_drawn_tab != max_old)) {
+ ensure_tab_visible(current);
+ }
} break;
case NOTIFICATION_DRAW: {
if (tabs.is_empty()) {
@@ -322,6 +356,10 @@ void TabBar::_notification(int p_what) {
// Draw unselected tabs in the back.
for (int i = offset; i <= max_drawn_tab; i++) {
+ if (tabs[i].hidden) {
+ continue;
+ }
+
if (i != current) {
Ref<StyleBox> sb;
Color col;
@@ -344,14 +382,14 @@ void TabBar::_notification(int p_what) {
}
// Draw selected tab in the front, but only if it's visible.
- if (current >= offset && current <= max_drawn_tab) {
+ if (current >= offset && current <= max_drawn_tab && !tabs[current].hidden) {
Ref<StyleBox> sb = tabs[current].disabled ? tab_disabled : tab_selected;
float x = rtl ? size.width - tabs[current].ofs_cache - tabs[current].size_cache : tabs[current].ofs_cache;
_draw_tab(sb, font_selected_color, current, x);
}
- if (offset > 0 || missing_right) {
+ if (buttons_visible) {
int vofs = (get_size().height - incr->get_size().height) / 2;
if (rtl) {
@@ -386,47 +424,52 @@ void TabBar::_notification(int p_what) {
void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x) {
RID ci = get_canvas_item();
+ bool rtl = is_layout_rtl();
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
int outline_size = get_theme_constant(SNAME("outline_size"));
+ int hseparation = get_theme_constant(SNAME("hseparation"));
- Tab tab = tabs[p_index];
-
- Rect2 sb_rect = Rect2(p_x, 0, tab.size_cache, get_size().height);
+ Rect2 sb_rect = Rect2(p_x, 0, tabs[p_index].size_cache, get_size().height);
p_tab_style->draw(ci, sb_rect);
- p_x += p_tab_style->get_margin(SIDE_LEFT);
+ p_x += rtl ? tabs[p_index].size_cache - p_tab_style->get_margin(SIDE_LEFT) : p_tab_style->get_margin(SIDE_LEFT);
Size2i sb_ms = p_tab_style->get_minimum_size();
- Ref<Texture2D> icon = tab.icon;
+ // Draw the icon.
+ Ref<Texture2D> icon = tabs[p_index].icon;
if (icon.is_valid()) {
- icon->draw(ci, Point2i(p_x, p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2));
+ icon->draw(ci, Point2i(rtl ? p_x - icon->get_width() : p_x, p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2));
- if (!tab.text.is_empty()) {
- p_x += icon->get_width() + get_theme_constant(SNAME("hseparation"));
- }
+ p_x = rtl ? p_x - icon->get_width() - hseparation : p_x + icon->get_width() + hseparation;
}
- Vector2 text_pos = Point2i(p_x, p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tab.text_buf->get_size().y) / 2);
- if (outline_size > 0 && font_outline_color.a > 0) {
- tab.text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
- }
- tab.text_buf->draw(ci, text_pos, p_font_color);
+ // Draw the text.
+ if (!tabs[p_index].text.is_empty()) {
+ Point2i text_pos = Point2i(rtl ? p_x - tabs[p_index].size_text : p_x,
+ p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tabs[p_index].text_buf->get_size().y) / 2);
- p_x += tab.size_text;
+ if (outline_size > 0 && font_outline_color.a > 0) {
+ tabs[p_index].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ }
+ tabs[p_index].text_buf->draw(ci, text_pos, p_font_color);
- if (tab.right_button.is_valid()) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("close_bg_highlight"));
- Ref<Texture2D> rb = tab.right_button;
+ p_x = rtl ? p_x - tabs[p_index].size_text - hseparation : p_x + tabs[p_index].size_text + hseparation;
+ }
- p_x += get_theme_constant(SNAME("hseparation"));
+ // Draw and calculate rect of the right button.
+ if (tabs[p_index].right_button.is_valid()) {
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("button_highlight"));
+ Ref<Texture2D> rb = tabs[p_index].right_button;
Rect2 rb_rect;
rb_rect.size = style->get_minimum_size() + rb->get_size();
- rb_rect.position.x = p_x;
+ rb_rect.position.x = rtl ? p_x - rb_rect.size.width : p_x;
rb_rect.position.y = p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - (rb_rect.size.y)) / 2;
+ tabs.write[p_index].rb_rect = rb_rect;
+
if (rb_hover == p_index) {
if (rb_pressing) {
get_theme_stylebox(SNAME("button_pressed"))->draw(ci, rb_rect);
@@ -435,41 +478,61 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
}
}
- rb->draw(ci, Point2i(p_x + style->get_margin(SIDE_LEFT), rb_rect.position.y + style->get_margin(SIDE_TOP)));
- p_x += rb->get_width();
- tabs.write[p_index].rb_rect = rb_rect;
+ rb->draw(ci, Point2i(rb_rect.position.x + style->get_margin(SIDE_LEFT), rb_rect.position.y + style->get_margin(SIDE_TOP)));
+
+ p_x = rtl ? rb_rect.position.x : rb_rect.position.x + rb_rect.size.width;
}
+ // Draw and calculate rect of the close button.
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_index == current)) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("close_bg_highlight"));
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("button_highlight"));
Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
- p_x += get_theme_constant(SNAME("hseparation"));
-
Rect2 cb_rect;
cb_rect.size = style->get_minimum_size() + cb->get_size();
- cb_rect.position.x = p_x;
+ cb_rect.position.x = rtl ? p_x - cb_rect.size.width : p_x;
cb_rect.position.y = p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - (cb_rect.size.y)) / 2;
- if (!tab.disabled && cb_hover == p_index) {
+ tabs.write[p_index].cb_rect = cb_rect;
+
+ if (!tabs[p_index].disabled && cb_hover == p_index) {
if (cb_pressing) {
- get_theme_stylebox(SNAME("close_bg_pressed"))->draw(ci, cb_rect);
+ get_theme_stylebox(SNAME("button_pressed"))->draw(ci, cb_rect);
} else {
style->draw(ci, cb_rect);
}
}
- cb->draw(ci, Point2i(p_x + style->get_margin(SIDE_LEFT), cb_rect.position.y + style->get_margin(SIDE_TOP)));
- p_x += cb->get_width();
- tabs.write[p_index].cb_rect = cb_rect;
+ cb->draw(ci, Point2i(cb_rect.position.x + style->get_margin(SIDE_LEFT), cb_rect.position.y + style->get_margin(SIDE_TOP)));
}
}
void TabBar::set_tab_count(int p_count) {
+ if (p_count == tabs.size()) {
+ return;
+ }
+
ERR_FAIL_COND(p_count < 0);
tabs.resize(p_count);
+
+ if (p_count == 0) {
+ offset = 0;
+ max_drawn_tab = 0;
+ current = 0;
+ previous = 0;
+ } else {
+ offset = MIN(offset, p_count - 1);
+ max_drawn_tab = MIN(max_drawn_tab, p_count - 1);
+ current = MIN(current, p_count - 1);
+ }
+
_update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
+ update_minimum_size();
notify_property_list_changed();
}
@@ -478,15 +541,26 @@ int TabBar::get_tab_count() const {
}
void TabBar::set_current_tab(int p_current) {
- if (current == p_current) {
- return;
- }
ERR_FAIL_INDEX(p_current, get_tab_count());
previous = current;
current = p_current;
+ if (current == previous) {
+ emit_signal(SNAME("tab_selected"), current);
+ return;
+ }
+ // Triggered by dragging a tab from another TabBar to the selected index, to ensure that tab_changed is emitted.
+ if (previous == -1) {
+ previous = current;
+ }
+
+ emit_signal(SNAME("tab_selected"), current);
+
_update_cache();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
emit_signal(SNAME("tab_changed"), p_current);
@@ -515,8 +589,13 @@ bool TabBar::get_offset_buttons_visible() const {
void TabBar::set_tab_title(int p_tab, const String &p_title) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].text = p_title;
+
_shape(p_tab);
_update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
update_minimum_size();
}
@@ -529,6 +608,7 @@ String TabBar::get_tab_title(int p_tab) const {
void TabBar::set_tab_text_direction(int p_tab, Control::TextDirection p_text_direction) {
ERR_FAIL_INDEX(p_tab, tabs.size());
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
+
if (tabs[p_tab].text_direction != p_text_direction) {
tabs.write[p_tab].text_direction = p_text_direction;
_shape(p_tab);
@@ -544,24 +624,38 @@ Control::TextDirection TabBar::get_tab_text_direction(int p_tab) const {
void TabBar::clear_tab_opentype_features(int p_tab) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].opentype_features.clear();
+
_shape(p_tab);
_update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
+ update_minimum_size();
}
void TabBar::set_tab_opentype_feature(int p_tab, const String &p_name, int p_value) {
ERR_FAIL_INDEX(p_tab, tabs.size());
+
int32_t tag = TS->name_to_tag(p_name);
if (!tabs[p_tab].opentype_features.has(tag) || (int)tabs[p_tab].opentype_features[tag] != p_value) {
tabs.write[p_tab].opentype_features[tag] = p_value;
+
_shape(p_tab);
_update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
+ update_minimum_size();
}
}
int TabBar::get_tab_opentype_feature(int p_tab, const String &p_name) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), -1);
+
int32_t tag = TS->name_to_tag(p_name);
if (!tabs[p_tab].opentype_features.has(tag)) {
return -1;
@@ -571,10 +665,17 @@ int TabBar::get_tab_opentype_feature(int p_tab, const String &p_name) const {
void TabBar::set_tab_language(int p_tab, const String &p_language) {
ERR_FAIL_INDEX(p_tab, tabs.size());
+
if (tabs[p_tab].language != p_language) {
tabs.write[p_tab].language = p_language;
_shape(p_tab);
+ _update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
+ update_minimum_size();
}
}
@@ -586,7 +687,12 @@ String TabBar::get_tab_language(int p_tab) const {
void TabBar::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].icon = p_icon;
+
_update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
update_minimum_size();
}
@@ -599,7 +705,14 @@ Ref<Texture2D> TabBar::get_tab_icon(int p_tab) const {
void TabBar::set_tab_disabled(int p_tab, bool p_disabled) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].disabled = p_disabled;
+
+ _update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
+ update_minimum_size();
}
bool TabBar::is_tab_disabled(int p_tab) const {
@@ -607,15 +720,38 @@ bool TabBar::is_tab_disabled(int p_tab) const {
return tabs[p_tab].disabled;
}
-void TabBar::set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_button) {
+void TabBar::set_tab_hidden(int p_tab, bool p_hidden) {
+ ERR_FAIL_INDEX(p_tab, tabs.size());
+ tabs.write[p_tab].hidden = p_hidden;
+
+ _update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
+ update();
+ update_minimum_size();
+}
+
+bool TabBar::is_tab_hidden(int p_tab) const {
+ ERR_FAIL_INDEX_V(p_tab, tabs.size(), false);
+ return tabs[p_tab].hidden;
+}
+
+void TabBar::set_tab_button_icon(int p_tab, const Ref<Texture2D> &p_icon) {
ERR_FAIL_INDEX(p_tab, tabs.size());
- tabs.write[p_tab].right_button = p_right_button;
+ tabs.write[p_tab].right_button = p_icon;
+
_update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
update_minimum_size();
}
-Ref<Texture2D> TabBar::get_tab_right_button(int p_tab) const {
+Ref<Texture2D> TabBar::get_tab_button_icon(int p_tab) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), Ref<Texture2D>());
return tabs[p_tab].right_button;
}
@@ -626,34 +762,53 @@ void TabBar::_update_hover() {
}
const Point2 &pos = get_local_mouse_position();
- // test hovering to display right or close button.
+ // Test hovering to display right or close button.
int hover_now = -1;
int hover_buttons = -1;
- for (int i = offset; i < tabs.size(); i++) {
+ for (int i = offset; i <= max_drawn_tab; i++) {
+ if (tabs[i].hidden) {
+ continue;
+ }
+
Rect2 rect = get_tab_rect(i);
if (rect.has_point(pos)) {
hover_now = i;
}
+
if (tabs[i].rb_rect.has_point(pos)) {
rb_hover = i;
cb_hover = -1;
hover_buttons = i;
- break;
} else if (!tabs[i].disabled && tabs[i].cb_rect.has_point(pos)) {
cb_hover = i;
rb_hover = -1;
hover_buttons = i;
+ }
+
+ if (hover_buttons != -1) {
+ update();
break;
}
}
+
if (hover != hover_now) {
hover = hover_now;
- emit_signal(SNAME("tab_hovered"), hover);
+
+ if (hover != -1) {
+ emit_signal(SNAME("tab_hovered"), hover);
+ }
}
if (hover_buttons == -1) { // No hover.
+ int rb_hover_old = rb_hover;
+ int cb_hover_old = cb_hover;
+
rb_hover = hover_buttons;
cb_hover = hover_buttons;
+
+ if (rb_hover != rb_hover_old || cb_hover != cb_hover_old) {
+ update();
+ }
}
}
@@ -677,16 +832,20 @@ void TabBar::_update_cache() {
int count_resize = 0;
for (int i = 0; i < tabs.size(); i++) {
- tabs.write[i].ofs_cache = 0;
- tabs.write[i].size_cache = get_tab_width(i);
tabs.write[i].size_text = Math::ceil(tabs[i].text_buf->get_size().x);
tabs.write[i].text_buf->set_width(-1);
- mw += tabs[i].size_cache;
- if (tabs[i].size_cache <= min_width || i == current) {
- size_fixed += tabs[i].size_cache;
- } else {
- count_resize++;
+ tabs.write[i].ofs_cache = 0;
+ tabs.write[i].size_cache = get_tab_width(i);
+
+ if (!tabs[i].hidden) {
+ mw += tabs[i].size_cache;
+
+ if (tabs[i].size_cache <= min_width || i == current) {
+ size_fixed += tabs[i].size_cache;
+ } else {
+ count_resize++;
+ }
}
}
@@ -696,34 +855,20 @@ void TabBar::_update_cache() {
}
for (int i = offset; i < tabs.size(); i++) {
- Ref<StyleBox> sb;
- if (tabs[i].disabled) {
- sb = tab_disabled;
- } else if (i == current) {
- sb = tab_selected;
- } else {
- sb = tab_unselected;
+ if (tabs[i].hidden) {
+ tabs.write[i].ofs_cache = w;
+ max_drawn_tab = i;
+
+ continue;
}
int lsize = tabs[i].size_cache;
int slen = tabs[i].size_text;
- if (min_width > 0 && mw > limit_minus_buttons && i != current) {
- if (lsize > m_width) {
- slen = m_width - (sb->get_margin(SIDE_LEFT) + sb->get_margin(SIDE_RIGHT));
- if (tabs[i].icon.is_valid()) {
- slen -= tabs[i].icon->get_width();
- slen -= get_theme_constant(SNAME("hseparation"));
- }
- if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
- slen -= cb->get_width();
- slen -= get_theme_constant(SNAME("hseparation"));
- }
-
- slen = MAX(slen, 1);
- lsize = m_width;
- }
+ // FIXME: This is completely broken.
+ if (min_width > 0 && (mw > limit || (offset > 0 && mw > limit_minus_buttons)) && i != current && lsize > m_width) {
+ slen = MAX(m_width - tabs[i].size_cache + tabs[i].size_text, 1);
+ lsize = m_width;
}
tabs.write[i].ofs_cache = w;
@@ -735,13 +880,22 @@ void TabBar::_update_cache() {
max_drawn_tab = i;
// Check if all tabs would fit inside the area.
- if (i > offset && (w > limit || (offset > 0 && w > limit_minus_buttons))) {
- w -= get_tab_width(i);
- max_drawn_tab -= 1;
+ if (clip_tabs && i > offset && (w > limit || (offset > 0 && w > limit_minus_buttons))) {
+ tabs.write[i].ofs_cache = 0;
+ tabs.write[i].text_buf->set_width(-1);
+
+ w -= tabs[i].size_cache;
+ max_drawn_tab--;
while (w > limit_minus_buttons && max_drawn_tab > offset) {
- w -= get_tab_width(max_drawn_tab);
- max_drawn_tab -= 1;
+ tabs.write[max_drawn_tab].ofs_cache = 0;
+
+ if (!tabs[max_drawn_tab].hidden) {
+ tabs.write[max_drawn_tab].text_buf->set_width(-1);
+ w -= tabs[max_drawn_tab].size_cache;
+ }
+
+ max_drawn_tab--;
}
break;
@@ -752,21 +906,25 @@ void TabBar::_update_cache() {
buttons_visible = offset > 0 || missing_right;
if (tab_alignment == ALIGNMENT_LEFT) {
+ _update_hover();
return;
- } else if (tab_alignment == ALIGNMENT_CENTER) {
+ }
+
+ if (tab_alignment == ALIGNMENT_CENTER) {
w = ((buttons_visible ? limit_minus_buttons : limit) - w) / 2;
} else if (tab_alignment == ALIGNMENT_RIGHT) {
w = (buttons_visible ? limit_minus_buttons : limit) - w;
}
- if (w < 0) {
- w = 0;
- }
-
for (int i = offset; i <= max_drawn_tab; i++) {
tabs.write[i].ofs_cache = w;
- w += tabs.write[i].size_cache;
+
+ if (!tabs[i].hidden) {
+ w += tabs[i].size_cache;
+ }
}
+
+ _update_hover();
}
void TabBar::_on_mouse_exited() {
@@ -784,20 +942,26 @@ void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
t.text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
t.text_buf->add_string(t.xl_text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
t.icon = p_icon;
-
tabs.push_back(t);
+
_update_cache();
- call_deferred(SNAME("_update_hover"));
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
update_minimum_size();
}
void TabBar::clear_tabs() {
tabs.clear();
+ offset = 0;
+ max_drawn_tab = 0;
current = 0;
previous = 0;
- call_deferred(SNAME("_update_hover"));
+
+ _update_cache();
update();
+ update_minimum_size();
notify_property_list_changed();
}
@@ -807,10 +971,6 @@ void TabBar::remove_tab(int p_idx) {
if (current >= p_idx) {
current--;
}
- _update_cache();
- call_deferred(SNAME("_update_hover"));
- update();
- update_minimum_size();
if (current < 0) {
current = 0;
@@ -820,7 +980,13 @@ void TabBar::remove_tab(int p_idx) {
current = tabs.size() - 1;
}
+ _update_cache();
_ensure_no_over_offset();
+ if (scroll_to_selected && !tabs.is_empty()) {
+ ensure_tab_visible(current);
+ }
+ update();
+ update_minimum_size();
notify_property_list_changed();
}
@@ -840,15 +1006,13 @@ Variant TabBar::get_drag_data(const Point2 &p_point) {
if (!tabs[tab_over].icon.is_null()) {
TextureRect *tf = memnew(TextureRect);
tf->set_texture(tabs[tab_over].icon);
+ tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
drag_preview->add_child(tf);
}
+
Label *label = memnew(Label(tabs[tab_over].xl_text));
drag_preview->add_child(label);
- if (!tabs[tab_over].right_button.is_null()) {
- TextureRect *tf = memnew(TextureRect);
- tf->set_texture(tabs[tab_over].right_button);
- drag_preview->add_child(tf);
- }
+
set_drag_preview(drag_preview);
Dictionary drag_data;
@@ -901,31 +1065,40 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) {
int tab_from_id = d["tab_element"];
NodePath from_path = d["from_path"];
NodePath to_path = get_path();
+
if (from_path == to_path) {
if (hover_now < 0) {
hover_now = get_tab_count() - 1;
}
+
move_tab(tab_from_id, hover_now);
emit_signal(SNAME("active_tab_rearranged"), hover_now);
set_current_tab(hover_now);
} else if (get_tabs_rearrange_group() != -1) {
// Drag and drop between Tabs.
+
Node *from_node = get_node(from_path);
TabBar *from_tabs = Object::cast_to<TabBar>(from_node);
+
if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
if (tab_from_id >= from_tabs->get_tab_count()) {
return;
}
+
Tab moving_tab = from_tabs->tabs[tab_from_id];
if (hover_now < 0) {
hover_now = get_tab_count();
}
+
+ // Workaround to ensure that tab_changed is emitted.
+ if (current == hover_now) {
+ current = -1;
+ }
+
tabs.insert(hover_now, moving_tab);
from_tabs->remove_tab(tab_from_id);
set_current_tab(hover_now);
- emit_signal(SNAME("tab_changed"), hover_now);
- _update_cache();
- update();
+ update_minimum_size();
}
}
}
@@ -946,6 +1119,7 @@ int TabBar::get_tab_idx_at_point(const Point2 &p_point) const {
void TabBar::set_tab_alignment(AlignmentMode p_alignment) {
ERR_FAIL_INDEX(p_alignment, ALIGNMENT_MAX);
tab_alignment = p_alignment;
+
_update_cache();
update();
}
@@ -959,7 +1133,16 @@ void TabBar::set_clip_tabs(bool p_clip_tabs) {
return;
}
clip_tabs = p_clip_tabs;
+
+ if (!clip_tabs) {
+ offset = 0;
+ max_drawn_tab = 0;
+ }
+
_update_cache();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
update_minimum_size();
}
@@ -981,6 +1164,10 @@ void TabBar::move_tab(int from, int to) {
tabs.insert(to, tab_from);
_update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
notify_property_list_changed();
}
@@ -991,37 +1178,49 @@ int TabBar::get_tab_width(int p_idx) const {
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
+ int hseparation = get_theme_constant(SNAME("hseparation"));
- int x = 0;
+ Ref<StyleBox> style;
+
+ if (tabs[p_idx].disabled) {
+ style = tab_disabled;
+ } else if (current == p_idx) {
+ style = tab_selected;
+ } else {
+ style = tab_unselected;
+ }
+ int x = style->get_minimum_size().width;
Ref<Texture2D> tex = tabs[p_idx].icon;
if (tex.is_valid()) {
- x += tex->get_width();
- if (!tabs[p_idx].text.is_empty()) {
- x += get_theme_constant(SNAME("hseparation"));
- }
+ x += tex->get_width() + hseparation;
}
- x += Math::ceil(tabs[p_idx].text_buf->get_size().x);
-
- if (tabs[p_idx].disabled) {
- x += tab_disabled->get_minimum_size().width;
- } else if (current == p_idx) {
- x += tab_selected->get_minimum_size().width;
- } else {
- x += tab_unselected->get_minimum_size().width;
+ if (!tabs[p_idx].text.is_empty()) {
+ x += tabs[p_idx].size_text + hseparation;
}
+ bool close_visible = cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx == current);
+
if (tabs[p_idx].right_button.is_valid()) {
+ Ref<StyleBox> btn_style = get_theme_stylebox(SNAME("button_highlight"));
Ref<Texture2D> rb = tabs[p_idx].right_button;
- x += rb->get_width();
- x += get_theme_constant(SNAME("hseparation"));
+
+ if (close_visible) {
+ x += btn_style->get_minimum_size().width + rb->get_width();
+ } else {
+ x += btn_style->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
+ }
}
- if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx == current)) {
+ if (close_visible) {
+ Ref<StyleBox> btn_style = get_theme_stylebox(SNAME("button_highlight"));
Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
- x += cb->get_width();
- x += get_theme_constant(SNAME("hseparation"));
+ x += btn_style->get_margin(SIDE_LEFT) + cb->get_width() + hseparation;
+ }
+
+ if (x > style->get_minimum_size().width) {
+ x -= hseparation;
}
return x;
@@ -1039,8 +1238,12 @@ void TabBar::_ensure_no_over_offset() {
int prev_offset = offset;
int total_w = tabs[max_drawn_tab].ofs_cache + tabs[max_drawn_tab].size_cache - tabs[offset].ofs_cache;
- while (offset > 0) {
- total_w += tabs[offset - 1].size_cache;
+ for (int i = offset; i > 0; i--) {
+ if (tabs[i - 1].hidden) {
+ continue;
+ }
+
+ total_w += tabs[i - 1].size_cache;
if (total_w < limit_minus_buttons) {
offset--;
@@ -1061,7 +1264,7 @@ void TabBar::ensure_tab_visible(int p_idx) {
}
ERR_FAIL_INDEX(p_idx, tabs.size());
- if (p_idx >= offset && p_idx <= max_drawn_tab) {
+ if (tabs[p_idx].hidden || (p_idx >= offset && p_idx <= max_drawn_tab)) {
return;
}
@@ -1079,12 +1282,20 @@ void TabBar::ensure_tab_visible(int p_idx) {
int total_w = tabs[max_drawn_tab].ofs_cache - tabs[offset].ofs_cache;
for (int i = max_drawn_tab; i <= p_idx; i++) {
+ if (tabs[i].hidden) {
+ continue;
+ }
+
total_w += tabs[i].size_cache;
}
int prev_offset = offset;
for (int i = offset; i < p_idx; i++) {
+ if (tabs[i].hidden) {
+ continue;
+ }
+
if (total_w > limit_minus_buttons) {
total_w -= tabs[i].size_cache;
offset++;
@@ -1111,8 +1322,14 @@ Rect2 TabBar::get_tab_rect(int p_tab) const {
void TabBar::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
ERR_FAIL_INDEX(p_policy, CLOSE_BUTTON_MAX);
cb_displaypolicy = p_policy;
+
_update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
update();
+ update_minimum_size();
}
TabBar::CloseButtonDisplayPolicy TabBar::get_tab_close_display_policy() const {
@@ -1147,6 +1364,17 @@ int TabBar::get_tabs_rearrange_group() const {
return tabs_rearrange_group;
}
+void TabBar::set_scroll_to_selected(bool p_enabled) {
+ scroll_to_selected = p_enabled;
+ if (p_enabled) {
+ ensure_tab_visible(current);
+ }
+}
+
+bool TabBar::get_scroll_to_selected() const {
+ return scroll_to_selected;
+}
+
void TabBar::set_select_with_rmb(bool p_enabled) {
select_with_rmb = p_enabled;
}
@@ -1225,8 +1453,12 @@ void TabBar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tab_language", "tab_idx"), &TabBar::get_tab_language);
ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &TabBar::set_tab_icon);
ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &TabBar::get_tab_icon);
+ ClassDB::bind_method(D_METHOD("set_tab_button_icon", "tab_idx", "icon"), &TabBar::set_tab_button_icon);
+ ClassDB::bind_method(D_METHOD("get_tab_button_icon", "tab_idx"), &TabBar::get_tab_button_icon);
ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabBar::set_tab_disabled);
ClassDB::bind_method(D_METHOD("is_tab_disabled", "tab_idx"), &TabBar::is_tab_disabled);
+ ClassDB::bind_method(D_METHOD("set_tab_hidden", "tab_idx", "hidden"), &TabBar::set_tab_hidden);
+ ClassDB::bind_method(D_METHOD("is_tab_hidden", "tab_idx"), &TabBar::is_tab_hidden);
ClassDB::bind_method(D_METHOD("remove_tab", "tab_idx"), &TabBar::remove_tab);
ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &TabBar::add_tab, DEFVAL(""), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("set_tab_alignment", "alignment"), &TabBar::set_tab_alignment);
@@ -1246,16 +1478,19 @@ void TabBar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_drag_to_rearrange_enabled"), &TabBar::get_drag_to_rearrange_enabled);
ClassDB::bind_method(D_METHOD("set_tabs_rearrange_group", "group_id"), &TabBar::set_tabs_rearrange_group);
ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &TabBar::get_tabs_rearrange_group);
-
+ ClassDB::bind_method(D_METHOD("set_scroll_to_selected", "enabled"), &TabBar::set_scroll_to_selected);
+ ClassDB::bind_method(D_METHOD("get_scroll_to_selected"), &TabBar::get_scroll_to_selected);
ClassDB::bind_method(D_METHOD("set_select_with_rmb", "enabled"), &TabBar::set_select_with_rmb);
ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &TabBar::get_select_with_rmb);
+ ADD_SIGNAL(MethodInfo("tab_selected", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
+ ADD_SIGNAL(MethodInfo("tab_clicked", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_rmb_clicked", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_close_pressed", PropertyInfo(Variant::INT, "tab")));
+ ADD_SIGNAL(MethodInfo("tab_button_pressed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_hovered", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("active_tab_rearranged", PropertyInfo(Variant::INT, "idx_to")));
- ADD_SIGNAL(MethodInfo("tab_clicked", PropertyInfo(Variant::INT, "tab")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment");
@@ -1263,6 +1498,8 @@ void TabBar::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_to_selected"), "set_scroll_to_selected", "get_scroll_to_selected");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "select_with_rmb"), "set_select_with_rmb", "get_select_with_rmb");
ADD_ARRAY_COUNT("Tabs", "tab_count", "set_tab_count", "get_tab_count", "tab_");
@@ -1278,5 +1515,6 @@ void TabBar::_bind_methods() {
}
TabBar::TabBar() {
+ set_size(Size2(get_size().width, get_minimum_size().height));
connect("mouse_exited", callable_mp(this, &TabBar::_on_mouse_exited));
}
diff --git a/scene/gui/tab_bar.h b/scene/gui/tab_bar.h
index d0055ae4d2..b428538570 100644
--- a/scene/gui/tab_bar.h
+++ b/scene/gui/tab_bar.h
@@ -63,12 +63,11 @@ private:
Ref<TextLine> text_buf;
Ref<Texture2D> icon;
- int ofs_cache = 0;
bool disabled = false;
+ bool hidden = false;
+ int ofs_cache = 0;
int size_cache = 0;
int size_text = 0;
- int x_cache = 0;
- int x_size_cache = 0;
Ref<Texture2D> right_button;
Rect2 rb_rect;
@@ -102,6 +101,7 @@ private:
int min_width = 0;
bool scrolling_enabled = true;
bool drag_to_rearrange_enabled = false;
+ bool scroll_to_selected = true;
int tabs_rearrange_group = -1;
int get_tab_width(int p_idx) const;
@@ -150,8 +150,11 @@ public:
void set_tab_disabled(int p_tab, bool p_disabled);
bool is_tab_disabled(int p_tab) const;
- void set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_button);
- Ref<Texture2D> get_tab_right_button(int p_tab) const;
+ void set_tab_hidden(int p_tab, bool p_hidden);
+ bool is_tab_hidden(int p_tab) const;
+
+ void set_tab_button_icon(int p_tab, const Ref<Texture2D> &p_icon);
+ Ref<Texture2D> get_tab_button_icon(int p_tab) const;
void set_tab_alignment(AlignmentMode p_alignment);
AlignmentMode get_tab_alignment() const;
@@ -187,6 +190,9 @@ public:
void set_tabs_rearrange_group(int p_group_id);
int get_tabs_rearrange_group() const;
+ void set_scroll_to_selected(bool p_enabled);
+ bool get_scroll_to_selected() const;
+
void set_select_with_rmb(bool p_enabled);
bool get_select_with_rmb() const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7db1fae2b6..0ee4a6af4e 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -187,29 +187,44 @@ void TextEdit::Text::_calculate_max_line_width() {
max_width = width;
}
-void TextEdit::Text::invalidate_cache(int p_line, int p_column, const String &p_ime_text, const Array &p_bidi_override) {
+void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_changed, const String &p_ime_text, const Array &p_bidi_override) {
ERR_FAIL_INDEX(p_line, text.size());
if (font.is_null() || font_size <= 0) {
return; // Not in tree?
}
- text.write[p_line].data_buf->clear();
+ if (p_text_changed) {
+ text.write[p_line].data_buf->clear();
+ }
+
text.write[p_line].data_buf->set_width(width);
text.write[p_line].data_buf->set_direction((TextServer::Direction)direction);
text.write[p_line].data_buf->set_preserve_control(draw_control_chars);
if (p_ime_text.length() > 0) {
- text.write[p_line].data_buf->add_string(p_ime_text, font, font_size, opentype_features, language);
+ if (p_text_changed) {
+ text.write[p_line].data_buf->add_string(p_ime_text, font, font_size, opentype_features, language);
+ }
if (!p_bidi_override.is_empty()) {
TS->shaped_text_set_bidi_override(text.write[p_line].data_buf->get_rid(), p_bidi_override);
}
} else {
- text.write[p_line].data_buf->add_string(text[p_line].data, font, font_size, opentype_features, language);
+ if (p_text_changed) {
+ text.write[p_line].data_buf->add_string(text[p_line].data, font, font_size, opentype_features, language);
+ }
if (!text[p_line].bidi_override.is_empty()) {
TS->shaped_text_set_bidi_override(text.write[p_line].data_buf->get_rid(), text[p_line].bidi_override);
}
}
+ if (!p_text_changed) {
+ RID r = text.write[p_line].data_buf->get_rid();
+ int spans = TS->shaped_get_span_count(r);
+ for (int i = 0; i < spans; i++) {
+ TS->shaped_set_span_update_font(r, i, font->get_rids(), font_size, opentype_features);
+ }
+ }
+
// Apply tab align.
if (tab_size > 0) {
Vector<float> tabs;
@@ -266,6 +281,24 @@ void TextEdit::Text::invalidate_all_lines() {
}
}
+void TextEdit::Text::invalidate_font() {
+ if (!is_dirty) {
+ return;
+ }
+
+ max_width = -1;
+ line_height = -1;
+
+ if (!font.is_null() && font_size > 0) {
+ font_height = font->get_height(font_size);
+ }
+
+ for (int i = 0; i < text.size(); i++) {
+ invalidate_cache(i, -1, false);
+ }
+ is_dirty = false;
+}
+
void TextEdit::Text::invalidate_all() {
if (!is_dirty) {
return;
@@ -279,7 +312,7 @@ void TextEdit::Text::invalidate_all() {
}
for (int i = 0; i < text.size(); i++) {
- invalidate_cache(i);
+ invalidate_cache(i, -1, true);
}
is_dirty = false;
}
@@ -294,7 +327,7 @@ void TextEdit::Text::clear() {
line.gutters.resize(gutter_count);
line.data = "";
text.insert(0, line);
- invalidate_cache(0);
+ invalidate_cache(0, -1, true);
}
int TextEdit::Text::get_max_width() const {
@@ -306,7 +339,7 @@ void TextEdit::Text::set(int p_line, const String &p_text, const Array &p_bidi_o
text.write[p_line].data = p_text;
text.write[p_line].bidi_override = p_bidi_override;
- invalidate_cache(p_line);
+ invalidate_cache(p_line, -1, true);
}
void TextEdit::Text::insert(int p_at, const Vector<String> &p_text, const Vector<Array> &p_bidi_override) {
@@ -331,7 +364,7 @@ void TextEdit::Text::insert(int p_at, const Vector<String> &p_text, const Vector
line.data = p_text[i];
line.bidi_override = p_bidi_override[i];
text.write[p_at + i] = line;
- invalidate_cache(p_at + i);
+ invalidate_cache(p_at + i, -1, true);
}
}
@@ -874,7 +907,7 @@ void TextEdit::_notification(int p_what) {
// Ensure we at least use the font color.
Color current_color = !editable ? font_readonly_color : font_color;
if (draw_placeholder) {
- current_color.a *= placeholder_alpha;
+ current_color = font_placeholder_color;
}
const Ref<TextParagraph> ldata = draw_placeholder ? placeholder_data_buf : text.get_line_data(line);
@@ -1446,9 +1479,11 @@ void TextEdit::_notification(int p_what) {
DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id());
DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id());
}
- ime_text = "";
- ime_selection = Point2();
- text.invalidate_cache(caret.line, caret.column, ime_text);
+ if (!ime_text.is_empty()) {
+ ime_text = "";
+ ime_selection = Point2();
+ text.invalidate_cache(caret.line, caret.column, true, ime_text);
+ }
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) {
DisplayServer::get_singleton()->virtual_keyboard_hide();
@@ -1470,7 +1505,7 @@ void TextEdit::_notification(int p_what) {
t = ime_text;
}
- text.invalidate_cache(caret.line, caret.column, t, structured_text_parser(st_parser, st_args, t));
+ text.invalidate_cache(caret.line, caret.column, true, t, structured_text_parser(st_parser, st_args, t));
update();
}
} break;
@@ -2515,6 +2550,7 @@ void TextEdit::_update_caches() {
font_size = get_theme_font_size(SNAME("font_size"));
font_color = get_theme_color(SNAME("font_color"));
font_readonly_color = get_theme_color(SNAME("font_readonly_color"));
+ font_placeholder_color = get_theme_color(SNAME("font_placeholder_color"));
outline_size = get_theme_constant(SNAME("outline_size"));
outline_color = get_theme_color(SNAME("font_outline_color"));
@@ -2537,7 +2573,7 @@ void TextEdit::_update_caches() {
text.set_draw_control_chars(draw_control_chars);
text.set_font(font);
text.set_font_size(font_size);
- text.invalidate_all();
+ text.invalidate_font();
_update_placeholder();
/* Syntax highlighting. */
@@ -2717,7 +2753,7 @@ void TextEdit::set_text_direction(Control::TextDirection p_text_direction) {
dir = (TextServer::Direction)text_direction;
}
text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
- text.invalidate_all();
+ text.invalidate_font();
_update_placeholder();
if (menu_dir) {
@@ -2739,7 +2775,7 @@ void TextEdit::set_opentype_feature(const String &p_name, int p_value) {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
text.set_font_features(opentype_features);
- text.invalidate_all();
+ text.invalidate_font();
_update_placeholder();
update();
}
@@ -2756,7 +2792,7 @@ int TextEdit::get_opentype_feature(const String &p_name) const {
void TextEdit::clear_opentype_features() {
opentype_features.clear();
text.set_font_features(opentype_features);
- text.invalidate_all();
+ text.invalidate_font();
_update_placeholder();
update();
}
@@ -2947,15 +2983,6 @@ String TextEdit::get_placeholder() const {
return placeholder_text;
}
-void TextEdit::set_placeholder_alpha(float p_alpha) {
- placeholder_alpha = p_alpha;
- update();
-}
-
-float TextEdit::get_placeholder_alpha() const {
- return placeholder_alpha;
-}
-
void TextEdit::set_line(int p_line, const String &p_new_text) {
if (p_line < 0 || p_line >= text.size()) {
return;
@@ -4860,7 +4887,7 @@ void TextEdit::set_draw_control_chars(bool p_enabled) {
menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
}
text.set_draw_control_chars(draw_control_chars);
- text.invalidate_all();
+ text.invalidate_font();
_update_placeholder();
update();
}
@@ -4944,9 +4971,6 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_placeholder", "text"), &TextEdit::set_placeholder);
ClassDB::bind_method(D_METHOD("get_placeholder"), &TextEdit::get_placeholder);
- ClassDB::bind_method(D_METHOD("set_placeholder_alpha", "alpha"), &TextEdit::set_placeholder_alpha);
- ClassDB::bind_method(D_METHOD("get_placeholder_alpha"), &TextEdit::get_placeholder_alpha);
-
ClassDB::bind_method(D_METHOD("set_line", "line", "new_text"), &TextEdit::set_line);
ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line);
@@ -5256,7 +5280,6 @@ void TextEdit::_bind_methods() {
/* Inspector */
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text", PROPERTY_HINT_MULTILINE_TEXT), "set_placeholder", "get_placeholder");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
@@ -5331,7 +5354,7 @@ bool TextEdit::_set(const StringName &p_name, const Variant &p_value) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
text.set_font_features(opentype_features);
- text.invalidate_all();
+ text.invalidate_font();
_update_placeholder();
update();
}
@@ -5339,7 +5362,7 @@ bool TextEdit::_set(const StringName &p_name, const Variant &p_value) {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
text.set_font_features(opentype_features);
- text.invalidate_all();
+ text.invalidate_font();
_update_placeholder();
update();
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index fdaa928598..83a63ae40a 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -210,7 +210,8 @@ private:
int size() const { return text.size(); }
void clear();
- void invalidate_cache(int p_line, int p_column = -1, const String &p_ime_text = String(), const Array &p_bidi_override = Array());
+ void invalidate_cache(int p_line, int p_column = -1, bool p_text_changed = false, const String &p_ime_text = String(), const Array &p_bidi_override = Array());
+ void invalidate_font();
void invalidate_all();
void invalidate_all_lines();
@@ -251,8 +252,6 @@ private:
Point2 ime_selection;
// Placeholder
- float placeholder_alpha = 0.6;
-
String placeholder_text = "";
Array placeholder_bidi_override;
Ref<TextParagraph> placeholder_data_buf;
@@ -525,6 +524,7 @@ private:
int font_size = 16;
Color font_color = Color(1, 1, 1);
Color font_readonly_color = Color(1, 1, 1);
+ Color font_placeholder_color = Color(1, 1, 1, 0.6);
int outline_size = 0;
Color outline_color = Color(1, 1, 1);
@@ -684,9 +684,6 @@ public:
void set_placeholder(const String &p_text);
String get_placeholder() const;
- void set_placeholder_alpha(float p_alpha);
- float get_placeholder_alpha() const;
-
void set_line(int p_line, const String &p_new_text);
String get_line(int p_line) const;
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index da202c1c8f..89a17ae854 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -173,7 +173,8 @@ void TextureButton::_notification(int p_what) {
bool draw_focus = (has_focus() && focused.is_valid());
// If no other texture is valid, try using focused texture.
- if (!texdraw.is_valid() && draw_focus) {
+ bool draw_focus_only = draw_focus && !texdraw.is_valid();
+ if (draw_focus_only) {
texdraw = focused;
}
@@ -232,7 +233,7 @@ void TextureButton::_notification(int p_what) {
size.width *= hflip ? -1.0f : 1.0f;
size.height *= vflip ? -1.0f : 1.0f;
- if (texdraw == focused) {
+ if (draw_focus_only) {
// Do nothing, we only needed to calculate the rectangle.
} else if (_tile) {
draw_texture_rect(texdraw, Rect2(ofs, size), _tile);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index bc8e81b1ae..1b32884880 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1319,10 +1319,10 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children);
ClassDB::bind_method(D_METHOD("get_index"), &TreeItem::get_index);
- ClassDB::bind_method(D_METHOD("move_before", "item"), &TreeItem::_move_before);
- ClassDB::bind_method(D_METHOD("move_after", "item"), &TreeItem::_move_after);
+ ClassDB::bind_method(D_METHOD("move_before", "item"), &TreeItem::move_before);
+ ClassDB::bind_method(D_METHOD("move_after", "item"), &TreeItem::move_after);
- ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::_remove_child);
+ ClassDB::bind_method(D_METHOD("remove_child", "child"), &TreeItem::remove_child);
{
MethodInfo mi;
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index fd65f90c49..c24763a0e4 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -188,16 +188,6 @@ protected:
return d;
}
- void _remove_child(Object *p_child) {
- remove_child(Object::cast_to<TreeItem>(p_child));
- }
-
- void _move_before(Object *p_item) {
- move_before(Object::cast_to<TreeItem>(p_item));
- }
- void _move_after(Object *p_item) {
- move_after(Object::cast_to<TreeItem>(p_item));
- }
Variant _call_recursive_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 65d210983e..4e91548d14 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -46,7 +46,7 @@ Error HTTPRequest::_parse_url(const String &p_url) {
request_sent = false;
got_response = false;
body_len = -1;
- body.resize(0);
+ body.clear();
downloaded.set(0);
redirections = 0;
@@ -86,9 +86,9 @@ String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const S
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) {
+ if (p_headers[i].find(":") > 0) {
Vector<String> parts = p_headers[i].split(":", false, 1);
- if (parts[0].strip_edges().to_lower() == lowwer_case_header_name) {
+ if (parts.size() > 1 && parts[0].strip_edges().to_lower() == lowwer_case_header_name) {
value = parts[1].strip_edges();
break;
}
@@ -99,7 +99,7 @@ String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const S
}
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
+ // Copy the string into a raw buffer.
Vector<uint8_t> raw_data;
CharString charstr = p_request_data.utf8();
@@ -134,7 +134,7 @@ Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_cust
headers = p_custom_headers;
if (accept_gzip) {
- // If the user has specified a different Accept-Encoding, don't overwrite it
+ // If the user has specified an Accept-Encoding header, don't overwrite it.
if (!has_header(headers, "Accept-Encoding")) {
headers.push_back("Accept-Encoding: gzip, deflate");
}
@@ -202,7 +202,7 @@ void HTTPRequest::cancel_request() {
file = nullptr;
}
client->close();
- body.resize(0);
+ body.clear();
got_response = false;
response_code = -1;
request_sent = false;
@@ -220,14 +220,14 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
response_code = client->get_response_code();
List<String> rheaders;
client->get_response_headers(&rheaders);
- response_headers.resize(0);
+ response_headers.clear();
downloaded.set(0);
for (const String &E : rheaders) {
response_headers.push_back(E);
}
if (response_code == 301 || response_code == 302) {
- // Handle redirect
+ // Handle redirect.
if (max_redirects >= 0 && redirections >= max_redirects) {
call_deferred(SNAME("_request_done"), RESULT_REDIRECT_LIMIT_REACHED, response_code, response_headers, PackedByteArray());
@@ -244,12 +244,12 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
}
if (!new_request.is_empty()) {
- // Process redirect
+ // Process redirect.
client->close();
- int new_redirs = redirections + 1; // Because _request() will clear it
+ int new_redirs = redirections + 1; // Because _request() will clear it.
Error err;
if (new_request.begins_with("http")) {
- // New url, request all again
+ // New url, new request.
_parse_url(new_request);
} else {
request_string = new_request;
@@ -260,7 +260,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
request_sent = false;
got_response = false;
body_len = -1;
- body.resize(0);
+ body.clear();
downloaded.set(0);
redirections = new_redirs;
*ret_value = false;
@@ -276,11 +276,11 @@ bool HTTPRequest::_update_connection() {
switch (client->get_status()) {
case HTTPClient::STATUS_DISCONNECTED: {
call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
- return true; // End it, since it's doing something
+ return true; // End it, since it's disconnected.
} break;
case HTTPClient::STATUS_RESOLVING: {
client->poll();
- // Must wait
+ // Must wait.
return false;
} break;
case HTTPClient::STATUS_CANT_RESOLVE: {
@@ -290,9 +290,9 @@ bool HTTPRequest::_update_connection() {
} break;
case HTTPClient::STATUS_CONNECTING: {
client->poll();
- // Must wait
+ // Must wait.
return false;
- } break; // Connecting to IP
+ } break; // Connecting to IP.
case HTTPClient::STATUS_CANT_CONNECT: {
call_deferred(SNAME("_request_done"), RESULT_CANT_CONNECT, 0, PackedStringArray(), PackedByteArray());
return true;
@@ -301,7 +301,7 @@ bool HTTPRequest::_update_connection() {
case HTTPClient::STATUS_CONNECTED: {
if (request_sent) {
if (!got_response) {
- // No body
+ // No body.
bool ret_value;
@@ -313,16 +313,16 @@ bool HTTPRequest::_update_connection() {
return true;
}
if (body_len < 0) {
- // Chunked transfer is done
+ // Chunked transfer is done.
call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
call_deferred(SNAME("_request_done"), RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray());
return true;
- // Request might have been done
+ // Request might have been done.
} else {
- // Did not request yet, do request
+ // Did not request yet, do request.
int size = request_data.size();
Error err = client->request(method, request_string, headers, size > 0 ? request_data.ptr() : nullptr, size);
@@ -334,13 +334,13 @@ bool HTTPRequest::_update_connection() {
request_sent = true;
return false;
}
- } break; // Connected: break requests only accepted here
+ } break; // Connected: break requests only accepted here.
case HTTPClient::STATUS_REQUESTING: {
- // Must wait, still requesting
+ // Must wait, still requesting.
client->poll();
return false;
- } break; // Request in progress
+ } break; // Request in progress.
case HTTPClient::STATUS_BODY: {
if (!got_response) {
bool ret_value;
@@ -411,7 +411,7 @@ bool HTTPRequest::_update_connection() {
return false;
- } break; // Request resulted in body: break which must be read
+ } break; // Request resulted in body: break which must be read.
case HTTPClient::STATUS_CONNECTION_ERROR: {
call_deferred(SNAME("_request_done"), RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray());
return true;
@@ -428,7 +428,7 @@ bool HTTPRequest::_update_connection() {
void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data) {
cancel_request();
- // Determine if the request body is compressed
+ // 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;
@@ -452,11 +452,11 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra
} 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
+ // Just return the raw data if we failed to decompress it.
} 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
+ // Just return the raw data if we failed to decompress it.
}
}
@@ -471,7 +471,6 @@ void HTTPRequest::_notification(int p_what) {
bool done = _update_connection();
if (done) {
set_process_internal(false);
- // cancel_request(); called from _request done now
}
}
@@ -619,7 +618,6 @@ void HTTPRequest::_bind_methods() {
ADD_SIGNAL(MethodInfo("request_completed", PropertyInfo(Variant::INT, "result"), PropertyInfo(Variant::INT, "response_code"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "headers"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "body")));
BIND_ENUM_CONSTANT(RESULT_SUCCESS);
- //BIND_ENUM_CONSTANT( RESULT_NO_BODY );
BIND_ENUM_CONSTANT(RESULT_CHUNKED_BODY_SIZE_MISMATCH);
BIND_ENUM_CONSTANT(RESULT_CANT_CONNECT);
BIND_ENUM_CONSTANT(RESULT_CANT_RESOLVE);
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 0c92dcae11..45f04b28b9 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -130,7 +130,7 @@ SceneTree::Group *SceneTree::add_to_group(const StringName &p_group, Node *p_nod
E = group_map.insert(p_group, Group());
}
- ERR_FAIL_COND_V_MSG(E->get().nodes.find(p_node) != -1, &E->get(), "Already in group: " + p_group + ".");
+ ERR_FAIL_COND_V_MSG(E->get().nodes.has(p_node), &E->get(), "Already in group: " + p_group + ".");
E->get().nodes.push_back(p_node);
//E->get().last_tree_version=0;
E->get().changed = true;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 1244e0c028..bde68f0b3d 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -492,20 +492,26 @@ void Viewport::_notification(int p_what) {
}
#endif // _3D_DISABLED
} break;
+ case NOTIFICATION_WM_MOUSE_ENTER: {
+ gui.mouse_in_window = true;
+ } break;
case NOTIFICATION_WM_MOUSE_EXIT: {
+ gui.mouse_in_window = false;
_drop_physics_mouseover();
-
- // Unlike on loss of focus (NOTIFICATION_WM_WINDOW_FOCUS_OUT), do not
- // drop the gui mouseover here, as a scrollbar may be dragged while the
- // mouse is outside the window (without the window having lost focus).
- // See bug #39634
+ _drop_mouse_over();
+ // When the mouse exits the window, we want to end mouse_over, but
+ // not mouse_focus, because, for example, we want to continue
+ // dragging a scrollbar even if the mouse has left the window.
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
_drop_physics_mouseover();
-
if (gui.mouse_focus && !gui.forced_mouse_focus) {
_drop_mouse_focus();
}
+ // When the window focus changes, we want to end mouse_focus, but
+ // not the mouse_over. Note: The OS will trigger a separate mouse
+ // exit event if the change in focus results in the mouse exiting
+ // the window.
} break;
}
}
@@ -1447,8 +1453,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (mb.is_valid()) {
gui.key_event_accepted = false;
- Control *over = nullptr;
-
Point2 mpos = mb->get_position();
gui.last_mouse_pos = mpos;
if (mb->is_pressed()) {
@@ -1594,6 +1598,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
// it is different, rather than wait for it to be updated the next time the
// mouse is moved, notify the control so that it can e.g. drop the highlight.
// This code is duplicated from the mm.is_valid()-case further below.
+ Control *over = nullptr;
if (gui.mouse_focus) {
over = gui.mouse_focus;
} else {
@@ -1601,10 +1606,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
if (gui.mouse_focus_mask == MouseButton::NONE && over != gui.mouse_over) {
- if (gui.mouse_over) {
- _gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT);
- }
-
+ _drop_mouse_over();
_gui_cancel_tooltip();
if (over) {
@@ -1625,8 +1627,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.last_mouse_pos = mpos;
- Control *over = nullptr;
-
// Drag & drop.
if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
gui.drag_accum += mm->get_relative();
@@ -1674,29 +1674,23 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
- // These sections of code are reused in the mb.is_valid() case further up
- // for the purpose of notifying controls about potential changes in focus
- // when the mousebutton is released.
+ Control *over = nullptr;
if (gui.mouse_focus) {
over = gui.mouse_focus;
- } else {
+ } else if (gui.mouse_in_window) {
over = gui_find_control(mpos);
}
if (over != gui.mouse_over) {
- if (gui.mouse_over) {
- _gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT);
- }
-
+ _drop_mouse_over();
_gui_cancel_tooltip();
if (over) {
_gui_call_notification(over, Control::NOTIFICATION_MOUSE_ENTER);
+ gui.mouse_over = over;
}
}
- gui.mouse_over = over;
-
DisplayServer::CursorShape ds_cursor_shape = (DisplayServer::CursorShape)Input::get_singleton()->get_default_cursor_shape();
if (over) {
@@ -2183,6 +2177,13 @@ void Viewport::_gui_accept_event() {
}
}
+void Viewport::_drop_mouse_over() {
+ if (gui.mouse_over) {
+ _gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT);
+ gui.mouse_over = nullptr;
+ }
+}
+
void Viewport::_drop_mouse_focus() {
Control *c = gui.mouse_focus;
MouseButton mask = gui.mouse_focus_mask;
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index a3127811f5..2541474cf3 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -335,6 +335,7 @@ private:
// info used when this is a window
bool forced_mouse_focus = false; //used for menu buttons
+ bool mouse_in_window = true;
bool key_event_accepted = false;
Control *mouse_focus = nullptr;
Control *last_mouse_focus = nullptr;
@@ -433,6 +434,7 @@ private:
void _canvas_layer_add(CanvasLayer *p_canvas_layer);
void _canvas_layer_remove(CanvasLayer *p_canvas_layer);
+ void _drop_mouse_over();
void _drop_mouse_focus();
void _drop_physics_mouseover(bool p_paused_only = false);
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 69b06c1803..838cef824b 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -555,11 +555,13 @@ void register_scene_types() {
GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeResizableBase);
GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeGroupBase);
GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeConstant);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeVectorBase);
GDREGISTER_CLASS(VisualShaderNodeComment);
GDREGISTER_CLASS(VisualShaderNodeFloatConstant);
GDREGISTER_CLASS(VisualShaderNodeIntConstant);
GDREGISTER_CLASS(VisualShaderNodeBooleanConstant);
GDREGISTER_CLASS(VisualShaderNodeColorConstant);
+ GDREGISTER_CLASS(VisualShaderNodeVec2Constant);
GDREGISTER_CLASS(VisualShaderNodeVec3Constant);
GDREGISTER_CLASS(VisualShaderNodeTransformConstant);
GDREGISTER_CLASS(VisualShaderNodeFloatOp);
@@ -577,8 +579,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeDotProduct);
GDREGISTER_CLASS(VisualShaderNodeVectorLen);
GDREGISTER_CLASS(VisualShaderNodeDeterminant);
- GDREGISTER_CLASS(VisualShaderNodeScalarDerivativeFunc);
- GDREGISTER_CLASS(VisualShaderNodeVectorDerivativeFunc);
+ GDREGISTER_CLASS(VisualShaderNodeDerivativeFunc);
GDREGISTER_CLASS(VisualShaderNodeClamp);
GDREGISTER_CLASS(VisualShaderNodeFaceForward);
GDREGISTER_CLASS(VisualShaderNodeOuterProduct);
@@ -604,6 +605,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeIntUniform);
GDREGISTER_CLASS(VisualShaderNodeBooleanUniform);
GDREGISTER_CLASS(VisualShaderNodeColorUniform);
+ GDREGISTER_CLASS(VisualShaderNodeVec2Uniform);
GDREGISTER_CLASS(VisualShaderNodeVec3Uniform);
GDREGISTER_CLASS(VisualShaderNodeTransformUniform);
GDREGISTER_CLASS(VisualShaderNodeTextureUniform);
@@ -1024,6 +1026,8 @@ void register_scene_types() {
ClassDB::add_compatibility_class("VisualShaderNodeVectorScalarStep", "VisualShaderNodeStep");
ClassDB::add_compatibility_class("VisualShaderNodeScalarSwitch", "VisualShaderNodeSwitch");
ClassDB::add_compatibility_class("VisualShaderNodeScalarTransformMult", "VisualShaderNodeTransformOp");
+ ClassDB::add_compatibility_class("VisualShaderNodeScalarDerivativeFunc", "VisualShaderNodeDerivativeFunc");
+ ClassDB::add_compatibility_class("VisualShaderNodeVectorDerivativeFunc", "VisualShaderNodeDerivativeFunc");
ClassDB::add_compatibility_class("World", "World3D");
#endif /* DISABLE_DEPRECATED */
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index d2cd76b796..6485c1ac77 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -661,8 +661,8 @@ void Curve2D::_bake() const {
baked_cache_dirty = false;
if (points.size() == 0) {
- baked_point_cache.resize(0);
- baked_dist_cache.resize(0);
+ baked_point_cache.clear();
+ baked_dist_cache.clear();
return;
}
@@ -1164,10 +1164,10 @@ void Curve3D::_bake() const {
baked_cache_dirty = false;
if (points.size() == 0) {
- baked_point_cache.resize(0);
- baked_tilt_cache.resize(0);
- baked_up_vector_cache.resize(0);
- baked_dist_cache.resize(0);
+ baked_point_cache.clear();
+ baked_tilt_cache.clear();
+ baked_up_vector_cache.clear();
+ baked_dist_cache.clear();
return;
}
@@ -1183,7 +1183,7 @@ void Curve3D::_bake() const {
baked_up_vector_cache.resize(1);
baked_up_vector_cache.set(0, Vector3(0, 1, 0));
} else {
- baked_up_vector_cache.resize(0);
+ baked_up_vector_cache.clear();
}
return;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 12ea1683c8..670b141080 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -113,6 +113,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
const Color control_font_hover_color = Color(0.95, 0.95, 0.95);
const Color control_font_focus_color = Color(0.95, 0.95, 0.95);
const Color control_font_disabled_color = control_font_color * Color(1, 1, 1, 0.5);
+ const Color control_font_placeholder_color = Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.6f);
const Color control_font_pressed_color = Color(1, 1, 1);
const Color control_selection_color = Color(0.5, 0.5, 0.5);
@@ -385,6 +386,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
theme->set_color("font_color", "LineEdit", control_font_color);
theme->set_color("font_selected_color", "LineEdit", control_font_pressed_color);
theme->set_color("font_uneditable_color", "LineEdit", control_font_disabled_color);
+ theme->set_color("font_placeholder_color", "LineEdit", control_font_placeholder_color);
theme->set_color("font_outline_color", "LineEdit", Color(1, 1, 1));
theme->set_color("caret_color", "LineEdit", control_font_hover_color);
theme->set_color("selection_color", "LineEdit", control_selection_color);
@@ -427,6 +429,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
theme->set_color("font_color", "TextEdit", control_font_color);
theme->set_color("font_selected_color", "TextEdit", control_font_pressed_color);
theme->set_color("font_readonly_color", "TextEdit", control_font_disabled_color);
+ theme->set_color("font_placeholder_color", "TextEdit", control_font_placeholder_color);
theme->set_color("font_outline_color", "TextEdit", Color(1, 1, 1));
theme->set_color("selection_color", "TextEdit", control_selection_color);
theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8));
@@ -468,6 +471,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
theme->set_color("font_color", "CodeEdit", control_font_color);
theme->set_color("font_selected_color", "CodeEdit", Color(0, 0, 0));
theme->set_color("font_readonly_color", "CodeEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
+ theme->set_color("font_placeholder_color", "CodeEdit", control_font_placeholder_color);
theme->set_color("font_outline_color", "CodeEdit", Color(1, 1, 1));
theme->set_color("selection_color", "CodeEdit", control_selection_color);
theme->set_color("bookmark_color", "CodeEdit", Color(0.5, 0.64, 1, 0.8));
@@ -817,8 +821,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
theme->set_stylebox("tab_selected", "TabBar", style_tab_selected);
theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected);
theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled);
- theme->set_stylebox("close_bg_pressed", "TabBar", button_pressed);
- theme->set_stylebox("close_bg_highlight", "TabBar", button_normal);
+ theme->set_stylebox("button_pressed", "TabBar", button_pressed);
+ theme->set_stylebox("button_highlight", "TabBar", button_normal);
theme->set_icon("increment", "TabBar", icons["scroll_button_right"]);
theme->set_icon("increment_highlight", "TabBar", icons["scroll_button_right_hl"]);
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index d2d96b1f06..441e84eccc 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -1475,12 +1475,12 @@ void ArrayMesh::add_blend_shape(const StringName &p_name) {
StringName name = p_name;
- if (blend_shapes.find(name) != -1) {
+ if (blend_shapes.has(name)) {
int count = 2;
do {
name = String(p_name) + " " + itos(count);
count++;
- } while (blend_shapes.find(name) != -1);
+ } while (blend_shapes.has(name));
}
blend_shapes.push_back(name);
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index f3752053c0..c3b5bd3564 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -55,7 +55,7 @@ void TextLine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bidi_override", "override"), &TextLine::set_bidi_override);
- ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language"), &TextLine::add_string, DEFVAL(Dictionary()), DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language", "meta"), &TextLine::add_string, DEFVAL(Dictionary()), DEFVAL(""), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextLine::add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1));
ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align"), &TextLine::resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER));
@@ -200,9 +200,9 @@ void TextLine::set_bidi_override(const Array &p_override) {
dirty = true;
}
-bool TextLine::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) {
+bool TextLine::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
ERR_FAIL_COND_V(p_fonts.is_null(), false);
- bool res = TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language);
+ bool res = TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language, p_meta);
spacing_top = p_fonts->get_spacing(TextServer::SPACING_TOP);
spacing_bottom = p_fonts->get_spacing(TextServer::SPACING_BOTTOM);
dirty = true;
diff --git a/scene/resources/text_line.h b/scene/resources/text_line.h
index e68049ee45..c5762db0f2 100644
--- a/scene/resources/text_line.h
+++ b/scene/resources/text_line.h
@@ -86,7 +86,7 @@ public:
void set_preserve_control(bool p_enabled);
bool get_preserve_control() const;
- bool add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "");
+ bool add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant());
bool add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1);
bool resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER);
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index c3bdef7b01..4d75874199 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -63,7 +63,7 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_dropcap", "text", "fonts", "size", "dropcap_margins", "opentype_features", "language"), &TextParagraph::set_dropcap, DEFVAL(Rect2()), DEFVAL(Dictionary()), DEFVAL(""));
ClassDB::bind_method(D_METHOD("clear_dropcap"), &TextParagraph::clear_dropcap);
- ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language"), &TextParagraph::add_string, DEFVAL(Dictionary()), DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language", "meta"), &TextParagraph::add_string, DEFVAL(Dictionary()), DEFVAL(""), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextParagraph::add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1));
ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align"), &TextParagraph::resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER));
@@ -344,9 +344,9 @@ void TextParagraph::clear_dropcap() {
lines_dirty = true;
}
-bool TextParagraph::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) {
+bool TextParagraph::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
ERR_FAIL_COND_V(p_fonts.is_null(), false);
- bool res = TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language);
+ bool res = TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language, p_meta);
spacing_top = p_fonts->get_spacing(TextServer::SPACING_TOP);
spacing_bottom = p_fonts->get_spacing(TextServer::SPACING_BOTTOM);
lines_dirty = true;
diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h
index 773cc1a858..8a8a53943b 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -102,7 +102,7 @@ public:
bool set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "");
void clear_dropcap();
- bool add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "");
+ bool add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant());
bool add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1);
bool resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER);
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 331674d248..ee66a61da8 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -2103,8 +2103,8 @@ void GradientTexture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &GradientTexture2D::_update);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT), "set_gradient", "get_gradient");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_width", "get_width");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_height", "get_height");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr");
ADD_GROUP("Fill", "fill_");
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index c3f29ad417..8075497c42 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -595,7 +595,7 @@ public:
private:
mutable RID _texture;
Ref<Curve> _curve;
- int _width = 2048;
+ int _width = 256;
int _current_width = 0;
TextureMode texture_mode = TEXTURE_MODE_RGB;
TextureMode _current_texture_mode = TEXTURE_MODE_RGB;
@@ -637,7 +637,7 @@ private:
Ref<Curve> _curve_x;
Ref<Curve> _curve_y;
Ref<Curve> _curve_z;
- int _width = 2048;
+ int _width = 256;
int _current_width = 0;
void _update();
@@ -685,7 +685,7 @@ private:
Ref<Gradient> gradient;
bool update_pending = false;
RID texture;
- int width = 2048;
+ int width = 256;
bool use_hdr = false;
void _queue_update();
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 4bc62e7617..f41058d59c 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -53,8 +53,98 @@ int VisualShaderNode::get_output_port_for_preview() const {
return port_preview;
}
-void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p_value) {
- default_input_values[p_port] = p_value;
+void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value) {
+ Variant value = p_value;
+
+ if (p_prev_value.get_type() != Variant::NIL) {
+ switch (p_value.get_type()) {
+ case Variant::FLOAT: {
+ switch (p_prev_value.get_type()) {
+ case Variant::INT: {
+ value = (float)p_prev_value;
+ } break;
+ case Variant::FLOAT: {
+ value = p_prev_value;
+ } break;
+ case Variant::VECTOR2: {
+ Vector2 pv = p_prev_value;
+ value = pv.x;
+ } break;
+ case Variant::VECTOR3: {
+ Vector3 pv = p_prev_value;
+ value = pv.x;
+ } break;
+ default:
+ break;
+ }
+ } break;
+ case Variant::INT: {
+ switch (p_prev_value.get_type()) {
+ case Variant::INT: {
+ value = p_prev_value;
+ } break;
+ case Variant::FLOAT: {
+ value = (int)p_prev_value;
+ } break;
+ case Variant::VECTOR2: {
+ Vector2 pv = p_prev_value;
+ value = (int)pv.x;
+ } break;
+ case Variant::VECTOR3: {
+ Vector3 pv = p_prev_value;
+ value = (int)pv.x;
+ } break;
+ default:
+ break;
+ }
+ } break;
+ case Variant::VECTOR2: {
+ switch (p_prev_value.get_type()) {
+ case Variant::INT: {
+ float pv = (float)(int)p_prev_value;
+ value = Vector2(pv, pv);
+ } break;
+ case Variant::FLOAT: {
+ float pv = p_prev_value;
+ value = Vector2(pv, pv);
+ } break;
+ case Variant::VECTOR2: {
+ value = p_prev_value;
+ } break;
+ case Variant::VECTOR3: {
+ Vector3 pv = p_prev_value;
+ value = Vector2(pv.x, pv.y);
+ } break;
+ default:
+ break;
+ }
+ } break;
+ case Variant::VECTOR3: {
+ switch (p_prev_value.get_type()) {
+ case Variant::INT: {
+ float pv = (float)(int)p_prev_value;
+ value = Vector3(pv, pv, pv);
+ } break;
+ case Variant::FLOAT: {
+ float pv = p_prev_value;
+ value = Vector3(pv, pv, pv);
+ } break;
+ case Variant::VECTOR2: {
+ Vector2 pv = p_prev_value;
+ value = Vector3(pv.x, pv.y, 0.0);
+ } break;
+ case Variant::VECTOR3: {
+ value = p_prev_value;
+ } break;
+ default:
+ break;
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+ default_input_values[p_port] = value;
emit_changed();
}
@@ -156,8 +246,15 @@ int VisualShaderNode::get_expanded_output_port_count() const {
int count2 = count;
for (int i = 0; i < count; i++) {
if (is_output_port_expandable(i) && _is_output_port_expanded(i)) {
- if (get_output_port_type(i) == PORT_TYPE_VECTOR) {
- count2 += 3;
+ switch (get_output_port_type(i)) {
+ case PORT_TYPE_VECTOR_2D: {
+ count2 += 2;
+ } break;
+ case PORT_TYPE_VECTOR: {
+ count2 += 3;
+ } break;
+ default:
+ break;
}
}
}
@@ -245,7 +342,7 @@ void VisualShaderNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_output_ports_expanded", "values"), &VisualShaderNode::_set_output_ports_expanded);
ClassDB::bind_method(D_METHOD("_get_output_ports_expanded"), &VisualShaderNode::_get_output_ports_expanded);
- ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value"), &VisualShaderNode::set_input_port_default_value);
+ ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value", "prev_value"), &VisualShaderNode::set_input_port_default_value, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("get_input_port_default_value", "port"), &VisualShaderNode::get_input_port_default_value);
ClassDB::bind_method(D_METHOD("remove_input_port_default_value", "port"), &VisualShaderNode::remove_input_port_default_value);
@@ -261,6 +358,7 @@ void VisualShaderNode::_bind_methods() {
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR);
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_INT);
+ BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR);
BIND_ENUM_CONSTANT(PORT_TYPE_BOOLEAN);
BIND_ENUM_CONSTANT(PORT_TYPE_TRANSFORM);
@@ -385,9 +483,9 @@ String VisualShaderNodeCustom::generate_global_per_node(Shader::Mode p_mode, Vis
return "";
}
-void VisualShaderNodeCustom::set_input_port_default_value(int p_port, const Variant &p_value) {
+void VisualShaderNodeCustom::set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value) {
if (!is_initialized) {
- VisualShaderNode::set_input_port_default_value(p_port, p_value);
+ VisualShaderNode::set_input_port_default_value(p_port, p_value, p_prev_value);
}
}
@@ -484,24 +582,48 @@ void VisualShader::update_engine_version(const Dictionary &p_new_version) {
if (expression.is_valid()) {
for (int j = 0; j < expression->get_input_port_count(); j++) {
int type = expression->get_input_port_type(j);
- if (type > 0) { // + PORT_TYPE_SCALAR_INT
- type += 1;
+ if (type > 0) { // + PORT_TYPE_SCALAR_INT + PORT_TYPE_VECTOR_2D
+ type += 2;
}
expression->set_input_port_type(j, type);
}
for (int j = 0; j < expression->get_output_port_count(); j++) {
int type = expression->get_output_port_type(j);
- if (type > 0) { // + PORT_TYPE_SCALAR_INT
- type += 1;
+ if (type > 0) { // + PORT_TYPE_SCALAR_INT + PORT_TYPE_VECTOR_2D
+ type += 2;
}
expression->set_output_port_type(j, type);
}
}
+ Ref<VisualShaderNodeStep> step = Object::cast_to<VisualShaderNodeStep>(E.value.node.ptr());
+ if (step.is_valid()) {
+ int op_type = int(step->get_op_type());
+ if (int(op_type) > 0) { // + OP_TYPE_VECTOR_2D + OP_TYPE_VECTOR_2D_SCALAR
+ op_type += 2;
+ }
+ step->set_op_type(VisualShaderNodeStep::OpType(op_type));
+ }
+ Ref<VisualShaderNodeSmoothStep> sstep = Object::cast_to<VisualShaderNodeSmoothStep>(E.value.node.ptr());
+ if (sstep.is_valid()) {
+ int op_type = int(sstep->get_op_type());
+ if (int(op_type) > 0) { // + OP_TYPE_VECTOR_2D + OP_TYPE_VECTOR_2D_SCALAR
+ op_type += 2;
+ }
+ sstep->set_op_type(VisualShaderNodeSmoothStep::OpType(op_type));
+ }
+ Ref<VisualShaderNodeMix> mix = Object::cast_to<VisualShaderNodeMix>(E.value.node.ptr());
+ if (mix.is_valid()) {
+ int op_type = int(mix->get_op_type());
+ if (int(op_type) > 0) { // + OP_TYPE_VECTOR_2D + OP_TYPE_VECTOR_2D_SCALAR
+ op_type += 2;
+ }
+ mix->set_op_type(VisualShaderNodeMix::OpType(op_type));
+ }
Ref<VisualShaderNodeCompare> compare = Object::cast_to<VisualShaderNodeCompare>(E.value.node.ptr());
if (compare.is_valid()) {
int ctype = int(compare->get_comparison_type());
- if (int(ctype) > 0) { // + PORT_TYPE_SCALAR_INT
- ctype += 1;
+ if (int(ctype) > 0) { // + CTYPE_SCALAR_INT + CTYPE_VECTOR_2D
+ ctype += 2;
}
compare->set_comparison_type(VisualShaderNodeCompare::ComparisonType(ctype));
}
@@ -719,7 +841,7 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
}
bool VisualShader::is_port_types_compatible(int p_a, int p_b) const {
- return MAX(0, p_a - 3) == (MAX(0, p_b - 3));
+ return MAX(0, p_a - 4) == (MAX(0, p_b - 4));
}
void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
@@ -953,15 +1075,27 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
Error err = _write_node(p_type, global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, p_node, processed, true, classes);
ERR_FAIL_COND_V(err != OK, String());
- if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_SCALAR) {
- code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " );\n";
- } else if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_SCALAR_INT) {
- code += " COLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n";
- } else if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_BOOLEAN) {
- code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0);\n";
- } else {
- code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n";
+ switch (node->get_output_port_type(p_port)) {
+ case VisualShaderNode::PORT_TYPE_SCALAR: {
+ code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + ");\n";
+ } break;
+ case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
+ code += " COLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n";
+ } break;
+ case VisualShaderNode::PORT_TYPE_BOOLEAN: {
+ code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0);\n";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + ", 0.0);\n";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n";
+ } break;
+ default: {
+ code += " COLOR.rgb = vec3(0.0);\n";
+ } break;
}
+
code += "}\n";
//set code secretly
@@ -1406,30 +1540,102 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
}
} else if (in_type == out_type) {
inputs[i] = src_var;
- } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_VECTOR) {
- inputs[i] = "dot(" + src_var + ", vec3(0.333333, 0.333333, 0.333333))";
- } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_VECTOR) {
- inputs[i] = "dot(float(" + src_var + "), vec3(0.333333, 0.333333, 0.333333))";
- } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_SCALAR) {
- inputs[i] = "vec3(" + src_var + ")";
- } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) {
- inputs[i] = "vec3(float(" + src_var + "))";
- } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_VECTOR) {
- inputs[i] = "all(bvec3(" + src_var + "))";
- } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_SCALAR) {
- inputs[i] = src_var + " > 0.0 ? true : false";
- } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) {
- inputs[i] = src_var + " > 0 ? true : false";
- } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) {
- inputs[i] = "(" + src_var + " ? 1.0 : 0.0)";
- } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) {
- inputs[i] = "(" + src_var + " ? 1 : 0)";
- } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) {
- inputs[i] = "vec3(" + src_var + " ? 1.0 : 0.0)";
- } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) {
- inputs[i] = "float(" + src_var + ")";
- } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_SCALAR) {
- inputs[i] = "int(" + src_var + ")";
+ } else {
+ switch (in_type) {
+ case VisualShaderNode::PORT_TYPE_SCALAR: {
+ switch (out_type) {
+ case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
+ inputs[i] = "float(" + src_var + ")";
+ } break;
+ case VisualShaderNode::PORT_TYPE_BOOLEAN: {
+ inputs[i] = "(" + src_var + " ? 1.0 : 0.0)";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ inputs[i] = "dot(" + src_var + ", vec2(0.333333, 0.333333))";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ inputs[i] = "dot(" + src_var + ", vec3(0.333333, 0.333333, 0.333333))";
+ } break;
+ default:
+ break;
+ }
+ } break;
+ case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
+ switch (out_type) {
+ case VisualShaderNode::PORT_TYPE_SCALAR: {
+ inputs[i] = "int(" + src_var + ")";
+ } break;
+ case VisualShaderNode::PORT_TYPE_BOOLEAN: {
+ inputs[i] = "(" + src_var + " ? 1 : 0)";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ inputs[i] = "dot(float(" + src_var + "), vec2(0.333333, 0.333333))";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ inputs[i] = "dot(float(" + src_var + "), vec3(0.333333, 0.333333, 0.333333))";
+ } break;
+ default:
+ break;
+ }
+ } break;
+ case VisualShaderNode::PORT_TYPE_BOOLEAN: {
+ switch (out_type) {
+ case VisualShaderNode::PORT_TYPE_SCALAR: {
+ inputs[i] = src_var + " > 0.0 ? true : false";
+ } break;
+ case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
+ inputs[i] = src_var + " > 0 ? true : false";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ inputs[i] = "all(bvec2(" + src_var + "))";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ inputs[i] = "all(bvec3(" + src_var + "))";
+ } break;
+ default:
+ break;
+ }
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ switch (out_type) {
+ case VisualShaderNode::PORT_TYPE_SCALAR: {
+ inputs[i] = "vec2(" + src_var + ")";
+ } break;
+ case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
+ inputs[i] = "vec2(float(" + src_var + "))";
+ } break;
+ case VisualShaderNode::PORT_TYPE_BOOLEAN: {
+ inputs[i] = "vec2(" + src_var + " ? 1.0 : 0.0)";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ inputs[i] = "vec2(" + src_var + ".xy)";
+ } break;
+ default:
+ break;
+ }
+ } break;
+
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ switch (out_type) {
+ case VisualShaderNode::PORT_TYPE_SCALAR: {
+ inputs[i] = "vec3(" + src_var + ")";
+ } break;
+ case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
+ inputs[i] = "vec3(float(" + src_var + "))";
+ } break;
+ case VisualShaderNode::PORT_TYPE_BOOLEAN: {
+ inputs[i] = "vec3(" + src_var + " ? 1.0 : 0.0)";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ inputs[i] = "vec3(" + src_var + ", 0.0)";
+ } break;
+ default:
+ break;
+ }
+ } break;
+ default:
+ break;
+ }
}
} else {
if (!vsnode->is_generate_input_var(i)) {
@@ -1449,6 +1655,10 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
bool val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
node_code += " bool " + inputs[i] + " = " + (val ? "true" : "false") + ";\n";
+ } else if (defval.get_type() == Variant::VECTOR2) {
+ Vector2 val = defval;
+ inputs[i] = "n_in" + itos(node) + "p" + itos(i);
+ node_code += " vec2 " + inputs[i] + " = " + vformat("vec2(%.5f, %.5f);\n", val.x, val.y);
} else if (defval.get_type() == Variant::VECTOR3) {
Vector3 val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
@@ -1485,8 +1695,15 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
if (vsnode->is_output_port_expandable(i) && vsnode->_is_output_port_expanded(i)) {
expanded = true;
- if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
- output_count += 3;
+ switch (vsnode->get_output_port_type(i)) {
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ output_count += 2;
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ output_count += 3;
+ } break;
+ default:
+ break;
}
}
expanded_output_ports.insert(i, expanded);
@@ -1506,6 +1723,9 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
outputs[i] = "int " + var_name;
break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D:
+ outputs[i] = "vec2 " + var_name;
+ break;
case VisualShaderNode::PORT_TYPE_VECTOR:
outputs[i] = "vec3 " + var_name;
break;
@@ -1515,12 +1735,19 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
case VisualShaderNode::PORT_TYPE_TRANSFORM:
outputs[i] = "mat4 " + var_name;
break;
- default: {
- }
+ default:
+ break;
}
if (expanded_output_ports[i]) {
- if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
- j += 3;
+ switch (vsnode->get_output_port_type(i)) {
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ j += 2;
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ j += 3;
+ } break;
+ default:
+ break;
}
}
}
@@ -1535,6 +1762,9 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
code += " int " + outputs[i] + ";\n";
break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D:
+ code += " vec2 " + outputs[i] + ";\n";
+ break;
case VisualShaderNode::PORT_TYPE_VECTOR:
code += " vec3 " + outputs[i] + ";\n";
break;
@@ -1544,12 +1774,19 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
case VisualShaderNode::PORT_TYPE_TRANSFORM:
code += " mat4 " + outputs[i] + ";\n";
break;
- default: {
- }
+ default:
+ break;
}
if (expanded_output_ports[i]) {
- if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
- j += 3;
+ switch (vsnode->get_output_port_type(i)) {
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ j += 2;
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ j += 3;
+ } break;
+ default:
+ break;
}
}
}
@@ -1565,38 +1802,65 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
for (int i = 0; i < output_count; i++) {
bool new_line_inserted = false;
if (expanded_output_ports[i]) {
- if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
- if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
- if (!new_line_inserted) {
- code += "\n";
- new_line_inserted = true;
+ switch (vsnode->get_output_port_type(i)) {
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String r = "n_out" + itos(node) + "p" + itos(i + 1);
+ code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
+ outputs[i + 1] = r;
}
- String r = "n_out" + itos(node) + "p" + itos(i + 1);
- code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
- outputs[i + 1] = r;
- }
- if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
- if (!new_line_inserted) {
- code += "\n";
- new_line_inserted = true;
+ if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String g = "n_out" + itos(node) + "p" + itos(i + 2);
+ code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
+ outputs[i + 2] = g;
+ }
+
+ i += 2;
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR: {
+ if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String r = "n_out" + itos(node) + "p" + itos(i + 1);
+ code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
+ outputs[i + 1] = r;
}
- String g = "n_out" + itos(node) + "p" + itos(i + 2);
- code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
- outputs[i + 2] = g;
- }
- if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
- if (!new_line_inserted) {
- code += "\n";
- new_line_inserted = true;
+ if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String g = "n_out" + itos(node) + "p" + itos(i + 2);
+ code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
+ outputs[i + 2] = g;
}
- String b = "n_out" + itos(node) + "p" + itos(i + 3);
- code += " float " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
- outputs[i + 3] = b;
- }
- i += 3;
+ if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
+ if (!new_line_inserted) {
+ code += "\n";
+ new_line_inserted = true;
+ }
+ String b = "n_out" + itos(node) + "p" + itos(i + 3);
+ code += " float " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
+ outputs[i + 3] = b;
+ }
+
+ i += 3;
+ } break;
+ default:
+ break;
}
}
}
@@ -2066,8 +2330,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "TANGENT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "BINORMAL" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
@@ -2082,7 +2346,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection", "PROJECTION_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection", "INV_PROJECTION_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(VIEWPORT_SIZE, 0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
// Node3D, Fragment
@@ -2092,19 +2356,19 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "TANGENT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "BINORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "view", "VIEW" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "world", "WORLD_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_camera", "INV_CAMERA_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "camera", "CAMERA_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection", "PROJECTION_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection", "INV_PROJECTION_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(VIEWPORT_SIZE, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "front_facing", "FRONT_FACING" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" },
@@ -2114,8 +2378,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
// Node3D, Light
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.xyz" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV2, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "view", "VIEW" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_color", "LIGHT_COLOR" },
@@ -2132,18 +2396,18 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection", "PROJECTION_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection", "INV_PROJECTION_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(VIEWPORT_SIZE, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
// Canvas Item
// Canvas Item, Vertex
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX, 0.0)" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "world", "WORLD_MATRIX" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "canvas", "CANVAS_MATRIX" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "screen", "SCREEN_MATRIX" },
@@ -2154,13 +2418,13 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
// Canvas Item, Fragment
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.xyz" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_pixel_size", "vec3(SCREEN_PIXEL_SIZE, 1.0)" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_pixel_size", "SCREEN_PIXEL_SIZE" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" },
@@ -2169,11 +2433,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "specular_shininess", "SPECULAR_SHININESS.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "specular_shininess_alpha", "SPECULAR_SHININESS.a" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
// Canvas Item, Light
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.xyz" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
@@ -2185,9 +2449,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_vertex", "LIGHT_VERTEX" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "shadow", "SHADOW_MODULATE.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "shadow_alpha", "SHADOW_MODULATE.a" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" },
{ 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" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "specular_shininess", "SPECULAR_SHININESS.rgb" },
@@ -2302,8 +2566,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "quarter_res_color", "QUARTER_RES_COLOR.rgb" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "quarter_res_alpha", "QUARTER_RES_COLOR.a" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SAMPLER, "radiance", "RADIANCE" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "sky_coords", "vec3(SKY_COORDS, 0.0)" },
+ { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
+ { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "sky_coords", "SKY_COORDS" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Fog, Fog
@@ -2324,11 +2588,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "vec3(0.0, 1.0, 0.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "vec3(1.0, 0.0, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(1.0, 1.0, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Spatial, Fragment
@@ -2337,27 +2601,27 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "vec3(0.0, 1.0, 0.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "vec3(1.0, 0.0, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(1.0, 1.0, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Spatial, Light
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.rgb" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "vec3(UV, 0.0)" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "viewport_size", "vec3(1.0, 1.0, 0.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Canvas Item, Vertex
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "vec3(VERTEX, 0.0)" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
@@ -2365,20 +2629,20 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
// Canvas Item, Fragment
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Canvas Item, Light
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "fragcoord", "FRAGCOORD.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "vec3(UV, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "vec3(0.0, 0.0, 1.0)" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "vec3(1.0)" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Particles
@@ -2391,7 +2655,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
// Sky
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" },
+ { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Fog
@@ -2455,6 +2719,9 @@ String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::T
case PORT_TYPE_SCALAR_INT: {
code = " " + p_output_vars[0] + " = 0;\n";
} break;
+ case PORT_TYPE_VECTOR_2D: {
+ code = " " + p_output_vars[0] + " = vec2(0.0);\n";
+ } break;
case PORT_TYPE_VECTOR: {
code = " " + p_output_vars[0] + " = vec3(0.0);\n";
} break;
@@ -2670,7 +2937,9 @@ int VisualShaderNodeUniformRef::get_output_port_count() const {
return 1;
case UniformType::UNIFORM_TYPE_BOOLEAN:
return 1;
- case UniformType::UNIFORM_TYPE_VECTOR:
+ case UniformType::UNIFORM_TYPE_VECTOR2:
+ return 1;
+ case UniformType::UNIFORM_TYPE_VECTOR3:
return 1;
case UniformType::UNIFORM_TYPE_TRANSFORM:
return 1;
@@ -2692,7 +2961,9 @@ VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_output_port
return PortType::PORT_TYPE_SCALAR_INT;
case UniformType::UNIFORM_TYPE_BOOLEAN:
return PortType::PORT_TYPE_BOOLEAN;
- case UniformType::UNIFORM_TYPE_VECTOR:
+ case UniformType::UNIFORM_TYPE_VECTOR2:
+ return PortType::PORT_TYPE_VECTOR_2D;
+ case UniformType::UNIFORM_TYPE_VECTOR3:
return PortType::PORT_TYPE_VECTOR;
case UniformType::UNIFORM_TYPE_TRANSFORM:
return PortType::PORT_TYPE_TRANSFORM;
@@ -2719,7 +2990,9 @@ String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const {
return "";
case UniformType::UNIFORM_TYPE_BOOLEAN:
return "";
- case UniformType::UNIFORM_TYPE_VECTOR:
+ case UniformType::UNIFORM_TYPE_VECTOR2:
+ return "";
+ case UniformType::UNIFORM_TYPE_VECTOR3:
return "";
case UniformType::UNIFORM_TYPE_TRANSFORM:
return "";
@@ -2789,7 +3062,9 @@ VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_b
return PORT_TYPE_SCALAR_INT;
case UniformType::UNIFORM_TYPE_SAMPLER:
return PORT_TYPE_SAMPLER;
- case UniformType::UNIFORM_TYPE_VECTOR:
+ case UniformType::UNIFORM_TYPE_VECTOR2:
+ return PORT_TYPE_VECTOR_2D;
+ case UniformType::UNIFORM_TYPE_VECTOR3:
return PORT_TYPE_VECTOR;
case UniformType::UNIFORM_TYPE_TRANSFORM:
return PORT_TYPE_TRANSFORM;
@@ -2808,26 +3083,19 @@ String VisualShaderNodeUniformRef::generate_code(Shader::Mode p_mode, VisualShad
if (uniform_name == "[None]") {
return " " + p_output_vars[0] + " = 0.0;\n";
}
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
- case UniformType::UNIFORM_TYPE_INT:
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
- case UniformType::UNIFORM_TYPE_BOOLEAN:
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
- case UniformType::UNIFORM_TYPE_VECTOR:
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
- case UniformType::UNIFORM_TYPE_TRANSFORM:
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ break;
case UniformType::UNIFORM_TYPE_COLOR: {
String code = " " + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n";
code += " " + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n";
return code;
} break;
case UniformType::UNIFORM_TYPE_SAMPLER:
- break;
+ return String();
default:
break;
}
- return "";
+
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
}
void VisualShaderNodeUniformRef::_set_uniform_type(int p_uniform_type) {
@@ -2871,8 +3139,8 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "normal", "NORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "tangent", "TANGENT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "binormal", "BINORMAL" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "UV:xy" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv2", "UV2:xy" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
@@ -2897,7 +3165,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "clearcoat", "CLEARCOAT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "clearcoat_gloss", "CLEARCOAT_GLOSS" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "anisotropy", "ANISOTROPY" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "anisotropy_flow", "ANISOTROPY_FLOW:xy" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "anisotropy_flow", "ANISOTROPY_FLOW" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "subsurf_scatter", "SSS_STRENGTH" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "backlight", "BACKLIGHT" },
@@ -2915,8 +3183,8 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
////////////////////////////////////////////////////////////////////////
// Canvas Item, Vertex.
////////////////////////////////////////////////////////////////////////
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "vertex", "VERTEX:xy" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "uv", "UV:xy" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
@@ -2929,7 +3197,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "normal_map", "NORMAL_MAP" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "normal_map_depth", "NORMAL_MAP_DEPTH" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light_vertex", "LIGHT_VERTEX" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "shadow_vertex", "SHADOW_VERTEX:xy" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "shadow_vertex", "SHADOW_VERTEX" },
////////////////////////////////////////////////////////////////////////
// Canvas Item, Light.
////////////////////////////////////////////////////////////////////////
@@ -3880,6 +4148,9 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad
case PORT_TYPE_SCALAR_INT:
tk = "0";
break;
+ case PORT_TYPE_VECTOR_2D:
+ tk = "vec2(0.0, 0.0)";
+ break;
case PORT_TYPE_VECTOR:
tk = "vec3(0.0, 0.0, 0.0)";
break;
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index acb33efd30..9f877e08a5 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -214,6 +214,7 @@ public:
enum PortType {
PORT_TYPE_SCALAR,
PORT_TYPE_SCALAR_INT,
+ PORT_TYPE_VECTOR_2D,
PORT_TYPE_VECTOR,
PORT_TYPE_BOOLEAN,
PORT_TYPE_TRANSFORM,
@@ -229,7 +230,7 @@ public:
virtual PortType get_input_port_type(int p_port) const = 0;
virtual String get_input_port_name(int p_port) const = 0;
- virtual void set_input_port_default_value(int p_port, const Variant &p_value);
+ virtual void set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value = Variant());
Variant get_input_port_default_value(int p_port) const; // if NIL (default if node does not set anything) is returned, it means no default value is wanted if disconnected, thus no input var must be supplied (empty string will be supplied)
Array get_default_input_values() const;
virtual void set_default_input_values(const Array &p_values);
@@ -311,7 +312,7 @@ protected:
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual void set_input_port_default_value(int p_port, const Variant &p_value) override;
+ virtual void set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value = Variant()) override;
virtual void set_default_input_values(const Array &p_values) override;
virtual void remove_input_port_default_value(int p_port) override;
virtual void clear_default_input_values() override;
@@ -492,7 +493,8 @@ public:
UNIFORM_TYPE_FLOAT,
UNIFORM_TYPE_INT,
UNIFORM_TYPE_BOOLEAN,
- UNIFORM_TYPE_VECTOR,
+ UNIFORM_TYPE_VECTOR2,
+ UNIFORM_TYPE_VECTOR3,
UNIFORM_TYPE_TRANSFORM,
UNIFORM_TYPE_COLOR,
UNIFORM_TYPE_SAMPLER,
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 0cfa9f31f7..9a714fd3dd 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -30,6 +30,65 @@
#include "visual_shader_nodes.h"
+////////////// Vector Base
+
+VisualShaderNodeVectorBase::PortType VisualShaderNodeVectorBase::get_input_port_type(int p_port) const {
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
+ return PORT_TYPE_VECTOR;
+ default:
+ break;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+VisualShaderNodeVectorBase::PortType VisualShaderNodeVectorBase::get_output_port_type(int p_port) const {
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
+ return PORT_TYPE_VECTOR;
+ default:
+ break;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+void VisualShaderNodeVectorBase::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
+VisualShaderNodeVectorBase::OpType VisualShaderNodeVectorBase::get_op_type() const {
+ return op_type;
+}
+
+void VisualShaderNodeVectorBase::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeVectorBase::set_op_type);
+ ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeVectorBase::get_op_type);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Vector2,Vector3"), "set_op_type", "get_op_type");
+
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_MAX);
+}
+
+Vector<StringName> VisualShaderNodeVectorBase::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("op_type");
+ return props;
+}
+
+VisualShaderNodeVectorBase::VisualShaderNodeVectorBase() {
+}
+
////////////// Constants Base
VisualShaderNodeConstant::VisualShaderNodeConstant() {
@@ -294,10 +353,72 @@ void VisualShaderNodeColorConstant::_bind_methods() {
VisualShaderNodeColorConstant::VisualShaderNodeColorConstant() {
}
-////////////// Vector
+////////////// Vector2
+
+String VisualShaderNodeVec2Constant::get_caption() const {
+ return "Vector2Constant";
+}
+
+int VisualShaderNodeVec2Constant::get_input_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeVec2Constant::PortType VisualShaderNodeVec2Constant::get_input_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR_2D;
+}
+
+String VisualShaderNodeVec2Constant::get_input_port_name(int p_port) const {
+ return String();
+}
+
+int VisualShaderNodeVec2Constant::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeVec2Constant::PortType VisualShaderNodeVec2Constant::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR_2D;
+}
+
+String VisualShaderNodeVec2Constant::get_output_port_name(int p_port) const {
+ return ""; //no output port means the editor will be used as port
+}
+
+String VisualShaderNodeVec2Constant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + vformat("vec2(%.6f, %.6f)", constant.x, constant.y) + ";\n";
+}
+
+void VisualShaderNodeVec2Constant::set_constant(const Vector2 &p_constant) {
+ if (constant.is_equal_approx(p_constant)) {
+ return;
+ }
+ constant = p_constant;
+ emit_changed();
+}
+
+Vector2 VisualShaderNodeVec2Constant::get_constant() const {
+ return constant;
+}
+
+Vector<StringName> VisualShaderNodeVec2Constant::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("constant");
+ return props;
+}
+
+void VisualShaderNodeVec2Constant::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeVec2Constant::set_constant);
+ ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeVec2Constant::get_constant);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant"), "set_constant", "get_constant");
+}
+
+VisualShaderNodeVec2Constant::VisualShaderNodeVec2Constant() {
+}
+
+////////////// Vector3
String VisualShaderNodeVec3Constant::get_caption() const {
- return "VectorConstant";
+ return "Vector3Constant";
}
int VisualShaderNodeVec3Constant::get_input_port_count() const {
@@ -439,7 +560,7 @@ int VisualShaderNodeTexture::get_input_port_count() const {
VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_input_port_type(int p_port) const {
switch (p_port) {
case 0:
- return PORT_TYPE_VECTOR;
+ return PORT_TYPE_VECTOR_2D;
case 1:
return PORT_TYPE_SCALAR;
case 2:
@@ -529,7 +650,7 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade
String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String default_uv;
if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
- default_uv = "UV.xy";
+ default_uv = "UV";
} else {
default_uv = "vec2(0.0)";
}
@@ -547,9 +668,9 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n";
@@ -575,9 +696,9 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n";
@@ -599,9 +720,9 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, 0.0);\n";
+ code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", 0.0);\n";
} else {
- code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
code += " " + p_output_vars[0] + " = _tex_read.rgb;\n";
@@ -622,9 +743,9 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
code += " " + p_output_vars[0] + " = _tex_read.rgb;\n";
@@ -1730,10 +1851,6 @@ int VisualShaderNodeVectorOp::get_input_port_count() const {
return 2;
}
-VisualShaderNodeVectorOp::PortType VisualShaderNodeVectorOp::get_input_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeVectorOp::get_input_port_name(int p_port) const {
return p_port == 0 ? "a" : "b";
}
@@ -1742,12 +1859,8 @@ int VisualShaderNodeVectorOp::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVectorOp::PortType VisualShaderNodeVectorOp::get_output_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeVectorOp::get_output_port_name(int p_port) const {
- return "op"; //no output port means the editor will be used as port
+ return "op";
}
String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
@@ -1778,13 +1891,21 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader
code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
break;
case OP_CROSS:
- code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ if (op_type == OP_TYPE_VECTOR_2D) { // not supported
+ code += "vec2(0.0);\n";
+ } else {
+ code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ }
break;
case OP_ATAN2:
code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
break;
case OP_REFLECT:
- code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ if (op_type == OP_TYPE_VECTOR_2D) { // not supported
+ code += "vec2(0.0);\n";
+ } else {
+ code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ }
break;
case OP_STEP:
code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
@@ -1796,6 +1917,27 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader
return code;
}
+void VisualShaderNodeVectorOp::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ switch (p_op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
void VisualShaderNodeVectorOp::set_operator(Operator p_op) {
ERR_FAIL_INDEX(int(p_op), int(OP_ENUM_SIZE));
if (op == p_op) {
@@ -1810,11 +1952,27 @@ VisualShaderNodeVectorOp::Operator VisualShaderNodeVectorOp::get_operator() cons
}
Vector<StringName> VisualShaderNodeVectorOp::get_editable_properties() const {
- Vector<StringName> props;
+ Vector<StringName> props = VisualShaderNodeVectorBase::get_editable_properties();
props.push_back("operator");
return props;
}
+String VisualShaderNodeVectorOp::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
+ bool invalid_type = false;
+
+ if (op_type == OP_TYPE_VECTOR_2D) {
+ if (op == OP_CROSS || op == OP_REFLECT) {
+ invalid_type = true;
+ }
+ }
+
+ if (invalid_type) {
+ return TTR("Invalid operator for that type.");
+ }
+
+ return String();
+}
+
void VisualShaderNodeVectorOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeVectorOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeVectorOp::get_operator);
@@ -1837,8 +1995,18 @@ void VisualShaderNodeVectorOp::_bind_methods() {
}
VisualShaderNodeVectorOp::VisualShaderNodeVectorOp() {
- set_input_port_default_value(0, Vector3());
- set_input_port_default_value(1, Vector3());
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2());
+ set_input_port_default_value(1, Vector2());
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3());
+ set_input_port_default_value(1, Vector3());
+ } break;
+ default:
+ break;
+ }
}
////////////// Color Op
@@ -2412,10 +2580,6 @@ int VisualShaderNodeVectorFunc::get_input_port_count() const {
return 1;
}
-VisualShaderNodeVectorFunc::PortType VisualShaderNodeVectorFunc::get_input_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeVectorFunc::get_input_port_name(int p_port) const {
return "";
}
@@ -2424,22 +2588,18 @@ int VisualShaderNodeVectorFunc::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVectorFunc::PortType VisualShaderNodeVectorFunc::get_output_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeVectorFunc::get_output_port_name(int p_port) const {
- return ""; //no output port means the editor will be used as port
+ return "result";
}
String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- static const char *vec_func_id[FUNC_MAX] = {
+ static const char *funcs[FUNC_MAX] = {
"normalize($)",
- "max(min($, vec3(1.0)), vec3(0.0))",
+ "", // FUNC_SATURATE
"-($)",
"1.0 / ($)",
- "",
- "",
+ "", // FUNC_RGB2HSV
+ "", // FUNC_HSV2RGB
"abs($)",
"acos($)",
"acosh($)",
@@ -2468,12 +2628,37 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad
"tan($)",
"tanh($)",
"trunc($)",
- "vec3(1.0, 1.0, 1.0) - $"
+ "" // FUNC_ONEMINUS
};
+ if (func == FUNC_SATURATE) {
+ String code;
+
+ if (op_type == OP_TYPE_VECTOR_2D) {
+ code = "max(min($, vec2(1.0)), vec2(0.0))";
+ } else {
+ code = "max(min($, vec3(1.0)), vec3(0.0))";
+ }
+ return " " + p_output_vars[0] + " = " + code.replace("$", p_input_vars[0]) + ";\n";
+ }
+
+ if (func == FUNC_ONEMINUS) {
+ String code;
+
+ if (op_type == OP_TYPE_VECTOR_2D) {
+ code = "vec2(1.0, 1.0) - $";
+ } else {
+ code = "vec3(1.0, 1.0, 1.0) - $";
+ }
+ return " " + p_output_vars[0] + " = " + code.replace("$", p_input_vars[0]) + ";\n";
+ }
+
String code;
if (func == FUNC_RGB2HSV) {
+ if (op_type == OP_TYPE_VECTOR_2D) { // not supported
+ return " " + p_output_vars[0] + " = vec2(0.0);\n";
+ }
code += " {\n";
code += " vec3 c = " + p_input_vars[0] + ";\n";
code += " vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n";
@@ -2484,6 +2669,9 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad
code += " " + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n";
code += " }\n";
} else if (func == FUNC_HSV2RGB) {
+ if (op_type == OP_TYPE_VECTOR_2D) { // not supported
+ return " " + p_output_vars[0] + " = vec2(0.0);\n";
+ }
code += " {\n";
code += " vec3 c = " + p_input_vars[0] + ";\n";
code += " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n";
@@ -2492,12 +2680,31 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad
code += " }\n";
} else {
- code += " " + p_output_vars[0] + " = " + String(vec_func_id[func]).replace("$", p_input_vars[0]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
}
return code;
}
+void VisualShaderNodeVectorFunc::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ switch (p_op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
void VisualShaderNodeVectorFunc::set_function(Function p_func) {
ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX));
if (func == p_func) {
@@ -2519,11 +2726,27 @@ VisualShaderNodeVectorFunc::Function VisualShaderNodeVectorFunc::get_function()
}
Vector<StringName> VisualShaderNodeVectorFunc::get_editable_properties() const {
- Vector<StringName> props;
+ Vector<StringName> props = VisualShaderNodeVectorBase::get_editable_properties();
props.push_back("function");
return props;
}
+String VisualShaderNodeVectorFunc::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
+ bool invalid_type = false;
+
+ if (op_type == OP_TYPE_VECTOR_2D) {
+ if (func == FUNC_RGB2HSV || func == FUNC_HSV2RGB) {
+ invalid_type = true;
+ }
+ }
+
+ if (invalid_type) {
+ return TTR("Invalid function for that type.");
+ }
+
+ return String();
+}
+
void VisualShaderNodeVectorFunc::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeVectorFunc::set_function);
ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeVectorFunc::get_function);
@@ -2569,7 +2792,16 @@ void VisualShaderNodeVectorFunc::_bind_methods() {
}
VisualShaderNodeVectorFunc::VisualShaderNodeVectorFunc() {
- set_input_port_default_value(0, Vector3());
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2());
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3());
+ } break;
+ default:
+ break;
+ }
}
////////////// ColorFunc
@@ -2754,11 +2986,11 @@ int VisualShaderNodeUVFunc::get_input_port_count() const {
VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_input_port_type(int p_port) const {
switch (p_port) {
case 0:
- [[fallthrough]]; // uv
+ return PORT_TYPE_VECTOR_2D; // uv
case 1:
- return PORT_TYPE_VECTOR; // scale
+ return PORT_TYPE_VECTOR_2D; // scale
case 2:
- return PORT_TYPE_VECTOR; // offset & pivot
+ return PORT_TYPE_VECTOR_2D; // offset & pivot
default:
break;
}
@@ -2801,7 +3033,7 @@ int VisualShaderNodeUVFunc::get_output_port_count() const {
}
VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_output_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
+ return PORT_TYPE_VECTOR_2D;
}
String VisualShaderNodeUVFunc::get_output_port_name(int p_port) const {
@@ -2818,9 +3050,9 @@ String VisualShaderNodeUVFunc::generate_code(Shader::Mode p_mode, VisualShader::
String uv;
if (p_input_vars[0].is_empty()) {
if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
- uv = "vec3(UV.xy, 0.0)";
+ uv = "UV";
} else {
- uv = "vec3(0.0)";
+ uv = "vec2(0.0)";
}
} else {
uv = vformat("%s", p_input_vars[0]);
@@ -2847,9 +3079,9 @@ void VisualShaderNodeUVFunc::set_function(VisualShaderNodeUVFunc::Function p_fun
return;
}
if (p_func == FUNC_PANNING) {
- set_input_port_default_value(2, Vector3()); // offset
+ set_input_port_default_value(2, Vector2()); // offset
} else { // FUNC_SCALING
- set_input_port_default_value(2, Vector3(0.5, 0.5, 0.0)); // pivot
+ set_input_port_default_value(2, Vector2(0.5, 0.5)); // pivot
}
func = p_func;
emit_changed();
@@ -2877,8 +3109,8 @@ void VisualShaderNodeUVFunc::_bind_methods() {
}
VisualShaderNodeUVFunc::VisualShaderNodeUVFunc() {
- set_input_port_default_value(1, Vector3(1.0, 1.0, 0.0)); // scale
- set_input_port_default_value(2, Vector3()); // offset
+ set_input_port_default_value(1, Vector2(1.0, 1.0)); // scale
+ set_input_port_default_value(2, Vector2()); // offset
}
////////////// Dot Product
@@ -2930,10 +3162,6 @@ int VisualShaderNodeVectorLen::get_input_port_count() const {
return 1;
}
-VisualShaderNodeVectorLen::PortType VisualShaderNodeVectorLen::get_input_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeVectorLen::get_input_port_name(int p_port) const {
return "";
}
@@ -2950,12 +3178,31 @@ String VisualShaderNodeVectorLen::get_output_port_name(int p_port) const {
return "length";
}
+void VisualShaderNodeVectorLen::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ switch (p_op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
String VisualShaderNodeVectorLen::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
return " " + p_output_vars[0] + " = length(" + p_input_vars[0] + ");\n";
}
VisualShaderNodeVectorLen::VisualShaderNodeVectorLen() {
- set_input_port_default_value(0, Vector3());
+ set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
}
////////////// Determinant
@@ -2996,37 +3243,53 @@ VisualShaderNodeDeterminant::VisualShaderNodeDeterminant() {
set_input_port_default_value(0, Transform3D());
}
-////////////// Scalar Derivative Function
+////////////// Derivative Function
-String VisualShaderNodeScalarDerivativeFunc::get_caption() const {
- return "ScalarDerivativeFunc";
+String VisualShaderNodeDerivativeFunc::get_caption() const {
+ return "DerivativeFunc";
}
-int VisualShaderNodeScalarDerivativeFunc::get_input_port_count() const {
+int VisualShaderNodeDerivativeFunc::get_input_port_count() const {
return 1;
}
-VisualShaderNodeScalarDerivativeFunc::PortType VisualShaderNodeScalarDerivativeFunc::get_input_port_type(int p_port) const {
+VisualShaderNodeDerivativeFunc::PortType VisualShaderNodeDerivativeFunc::get_input_port_type(int p_port) const {
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
+ return PORT_TYPE_VECTOR;
+ default:
+ break;
+ }
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeScalarDerivativeFunc::get_input_port_name(int p_port) const {
- return "";
+String VisualShaderNodeDerivativeFunc::get_input_port_name(int p_port) const {
+ return "p";
}
-int VisualShaderNodeScalarDerivativeFunc::get_output_port_count() const {
+int VisualShaderNodeDerivativeFunc::get_output_port_count() const {
return 1;
}
-VisualShaderNodeScalarDerivativeFunc::PortType VisualShaderNodeScalarDerivativeFunc::get_output_port_type(int p_port) const {
+VisualShaderNodeDerivativeFunc::PortType VisualShaderNodeDerivativeFunc::get_output_port_type(int p_port) const {
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
+ return PORT_TYPE_VECTOR;
+ default:
+ break;
+ }
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeScalarDerivativeFunc::get_output_port_name(int p_port) const {
- return "";
+String VisualShaderNodeDerivativeFunc::get_output_port_name(int p_port) const {
+ return "result";
}
-String VisualShaderNodeScalarDerivativeFunc::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+String VisualShaderNodeDerivativeFunc::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
static const char *functions[FUNC_MAX] = {
"fwidth($)",
"dFdx($)",
@@ -3038,84 +3301,33 @@ String VisualShaderNodeScalarDerivativeFunc::generate_code(Shader::Mode p_mode,
return code;
}
-void VisualShaderNodeScalarDerivativeFunc::set_function(Function p_func) {
- ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX));
- if (func == p_func) {
+void VisualShaderNodeDerivativeFunc::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX((int)p_op_type, int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
return;
}
- func = p_func;
+ switch (p_op_type) {
+ case OP_TYPE_SCALAR: {
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
+ } break;
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
emit_changed();
}
-VisualShaderNodeScalarDerivativeFunc::Function VisualShaderNodeScalarDerivativeFunc::get_function() const {
- return func;
-}
-
-Vector<StringName> VisualShaderNodeScalarDerivativeFunc::get_editable_properties() const {
- Vector<StringName> props;
- props.push_back("function");
- return props;
-}
-
-void VisualShaderNodeScalarDerivativeFunc::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeScalarDerivativeFunc::set_function);
- ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeScalarDerivativeFunc::get_function);
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Sum,X,Y"), "set_function", "get_function");
-
- BIND_ENUM_CONSTANT(FUNC_SUM);
- BIND_ENUM_CONSTANT(FUNC_X);
- BIND_ENUM_CONSTANT(FUNC_Y);
- BIND_ENUM_CONSTANT(FUNC_MAX);
-}
-
-VisualShaderNodeScalarDerivativeFunc::VisualShaderNodeScalarDerivativeFunc() {
- set_input_port_default_value(0, 0.0);
-}
-
-////////////// Vector Derivative Function
-
-String VisualShaderNodeVectorDerivativeFunc::get_caption() const {
- return "VectorDerivativeFunc";
-}
-
-int VisualShaderNodeVectorDerivativeFunc::get_input_port_count() const {
- return 1;
-}
-
-VisualShaderNodeVectorDerivativeFunc::PortType VisualShaderNodeVectorDerivativeFunc::get_input_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
-String VisualShaderNodeVectorDerivativeFunc::get_input_port_name(int p_port) const {
- return "";
-}
-
-int VisualShaderNodeVectorDerivativeFunc::get_output_port_count() const {
- return 1;
-}
-
-VisualShaderNodeVectorDerivativeFunc::PortType VisualShaderNodeVectorDerivativeFunc::get_output_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
-String VisualShaderNodeVectorDerivativeFunc::get_output_port_name(int p_port) const {
- return "";
-}
-
-String VisualShaderNodeVectorDerivativeFunc::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- static const char *functions[FUNC_MAX] = {
- "fwidth($)",
- "dFdx($)",
- "dFdy($)"
- };
-
- String code;
- code += " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n";
- return code;
+VisualShaderNodeDerivativeFunc::OpType VisualShaderNodeDerivativeFunc::get_op_type() const {
+ return op_type;
}
-void VisualShaderNodeVectorDerivativeFunc::set_function(Function p_func) {
+void VisualShaderNodeDerivativeFunc::set_function(Function p_func) {
ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX));
if (func == p_func) {
return;
@@ -3124,30 +3336,40 @@ void VisualShaderNodeVectorDerivativeFunc::set_function(Function p_func) {
emit_changed();
}
-VisualShaderNodeVectorDerivativeFunc::Function VisualShaderNodeVectorDerivativeFunc::get_function() const {
+VisualShaderNodeDerivativeFunc::Function VisualShaderNodeDerivativeFunc::get_function() const {
return func;
}
-Vector<StringName> VisualShaderNodeVectorDerivativeFunc::get_editable_properties() const {
+Vector<StringName> VisualShaderNodeDerivativeFunc::get_editable_properties() const {
Vector<StringName> props;
+ props.push_back("op_type");
props.push_back("function");
return props;
}
-void VisualShaderNodeVectorDerivativeFunc::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeVectorDerivativeFunc::set_function);
- ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeVectorDerivativeFunc::get_function);
+void VisualShaderNodeDerivativeFunc::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeDerivativeFunc::set_op_type);
+ ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeDerivativeFunc::get_op_type);
+
+ ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeDerivativeFunc::set_function);
+ ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeDerivativeFunc::get_function);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3"), "set_op_type", "get_op_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Sum,X,Y"), "set_function", "get_function");
+ BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_MAX);
+
BIND_ENUM_CONSTANT(FUNC_SUM);
BIND_ENUM_CONSTANT(FUNC_X);
BIND_ENUM_CONSTANT(FUNC_Y);
BIND_ENUM_CONSTANT(FUNC_MAX);
}
-VisualShaderNodeVectorDerivativeFunc::VisualShaderNodeVectorDerivativeFunc() {
- set_input_port_default_value(0, Vector3());
+VisualShaderNodeDerivativeFunc::VisualShaderNodeDerivativeFunc() {
+ set_input_port_default_value(0, 0.0);
}
////////////// Clamp
@@ -3164,7 +3386,9 @@ VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_input_port_type(int p
switch (op_type) {
case OP_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
default:
break;
@@ -3191,7 +3415,9 @@ VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_output_port_type(int
switch (op_type) {
case OP_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
default:
break;
@@ -3214,19 +3440,24 @@ void VisualShaderNodeClamp::set_op_type(OpType p_op_type) {
}
switch (p_op_type) {
case OP_TYPE_FLOAT:
- set_input_port_default_value(0, 0.0);
- set_input_port_default_value(1, 0.0);
- set_input_port_default_value(2, 0.0);
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1));
+ set_input_port_default_value(2, 0.0, get_input_port_default_value(2));
break;
case OP_TYPE_INT:
- set_input_port_default_value(0, 0);
- set_input_port_default_value(1, 0);
- set_input_port_default_value(2, 0);
+ set_input_port_default_value(0, 0, get_input_port_default_value(0));
+ set_input_port_default_value(1, 0, get_input_port_default_value(1));
+ set_input_port_default_value(2, 0, get_input_port_default_value(2));
break;
- case OP_TYPE_VECTOR:
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
- set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0));
- set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0));
+ case OP_TYPE_VECTOR_2D:
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Vector2(), get_input_port_default_value(2));
+ break;
+ case OP_TYPE_VECTOR_3D:
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Vector3(), get_input_port_default_value(2));
break;
default:
break;
@@ -3249,11 +3480,12 @@ void VisualShaderNodeClamp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeClamp::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeClamp::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_FLOAT);
BIND_ENUM_CONSTANT(OP_TYPE_INT);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
@@ -3273,10 +3505,6 @@ int VisualShaderNodeFaceForward::get_input_port_count() const {
return 3;
}
-VisualShaderNodeFaceForward::PortType VisualShaderNodeFaceForward::get_input_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeFaceForward::get_input_port_name(int p_port) const {
switch (p_port) {
case 0:
@@ -3294,14 +3522,33 @@ int VisualShaderNodeFaceForward::get_output_port_count() const {
return 1;
}
-VisualShaderNodeFaceForward::PortType VisualShaderNodeFaceForward::get_output_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeFaceForward::get_output_port_name(int p_port) const {
return "";
}
+void VisualShaderNodeFaceForward::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ switch (p_op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Vector2(), get_input_port_default_value(2));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Vector3(), get_input_port_default_value(2));
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
String VisualShaderNodeFaceForward::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
return " " + p_output_vars[0] + " = faceforward(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
}
@@ -3370,9 +3617,16 @@ int VisualShaderNodeStep::get_input_port_count() const {
VisualShaderNodeStep::PortType VisualShaderNodeStep::get_input_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_2D_SCALAR:
+ if (p_port == 1) {
+ return PORT_TYPE_VECTOR_2D;
+ }
+ break;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
- case OP_TYPE_VECTOR_SCALAR:
+ case OP_TYPE_VECTOR_3D_SCALAR:
if (p_port == 1) {
return PORT_TYPE_VECTOR;
}
@@ -3384,12 +3638,13 @@ VisualShaderNodeStep::PortType VisualShaderNodeStep::get_input_port_type(int p_p
}
String VisualShaderNodeStep::get_input_port_name(int p_port) const {
- if (p_port == 0) {
- return "edge";
- } else if (p_port == 1) {
- return "x";
+ switch (p_port) {
+ case 0:
+ return "edge";
+ case 1:
+ return "x";
}
- return "";
+ return String();
}
int VisualShaderNodeStep::get_output_port_count() const {
@@ -3398,9 +3653,13 @@ int VisualShaderNodeStep::get_output_port_count() const {
VisualShaderNodeStep::PortType VisualShaderNodeStep::get_output_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_2D_SCALAR:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
- case OP_TYPE_VECTOR_SCALAR:
+ case OP_TYPE_VECTOR_3D_SCALAR:
return PORT_TYPE_VECTOR;
default:
break;
@@ -3418,30 +3677,26 @@ void VisualShaderNodeStep::set_op_type(OpType p_op_type) {
return;
}
switch (p_op_type) {
- case OP_TYPE_SCALAR:
- if (op_type == OP_TYPE_VECTOR) {
- set_input_port_default_value(0, 0.0); // edge
- }
- if (op_type == OP_TYPE_VECTOR || op_type == OP_TYPE_VECTOR_SCALAR) {
- set_input_port_default_value(1, 0.0); // x
- }
- break;
- case OP_TYPE_VECTOR:
- if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) {
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // edge
- }
- if (op_type == OP_TYPE_SCALAR) {
- set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // x
- }
- break;
- case OP_TYPE_VECTOR_SCALAR:
- if (op_type == OP_TYPE_VECTOR) {
- set_input_port_default_value(0, 0.0); // edge
- }
- if (op_type == OP_TYPE_SCALAR) {
- set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // x
- }
- break;
+ case OP_TYPE_SCALAR: {
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1));
+ } break;
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1));
+ } break;
+ case OP_TYPE_VECTOR_2D_SCALAR: {
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
+ } break;
+ case OP_TYPE_VECTOR_3D_SCALAR: {
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
+ } break;
default:
break;
}
@@ -3467,11 +3722,13 @@ void VisualShaderNodeStep::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeStep::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeStep::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
@@ -3492,9 +3749,16 @@ int VisualShaderNodeSmoothStep::get_input_port_count() const {
VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_input_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_2D_SCALAR:
+ if (p_port == 2) {
+ return PORT_TYPE_VECTOR_2D; // x
+ }
+ break;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
- case OP_TYPE_VECTOR_SCALAR:
+ case OP_TYPE_VECTOR_3D_SCALAR:
if (p_port == 2) {
return PORT_TYPE_VECTOR; // x
}
@@ -3506,14 +3770,15 @@ VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_input_port_
}
String VisualShaderNodeSmoothStep::get_input_port_name(int p_port) const {
- if (p_port == 0) {
- return "edge0";
- } else if (p_port == 1) {
- return "edge1";
- } else if (p_port == 2) {
- return "x";
+ switch (p_port) {
+ case 0:
+ return "edge0";
+ case 1:
+ return "edge1";
+ case 2:
+ return "x";
}
- return "";
+ return String();
}
int VisualShaderNodeSmoothStep::get_output_port_count() const {
@@ -3522,9 +3787,13 @@ int VisualShaderNodeSmoothStep::get_output_port_count() const {
VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_output_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_2D_SCALAR:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
- case OP_TYPE_VECTOR_SCALAR:
+ case OP_TYPE_VECTOR_3D_SCALAR:
return PORT_TYPE_VECTOR;
default:
break;
@@ -3543,31 +3812,29 @@ void VisualShaderNodeSmoothStep::set_op_type(OpType p_op_type) {
}
switch (p_op_type) {
case OP_TYPE_SCALAR:
- if (op_type == OP_TYPE_VECTOR) {
- set_input_port_default_value(0, 0.0); // edge0
- set_input_port_default_value(1, 0.0); // edge1
- }
- if (op_type == OP_TYPE_VECTOR || op_type == OP_TYPE_VECTOR_SCALAR) {
- set_input_port_default_value(2, 0.0); // x
- }
- break;
- case OP_TYPE_VECTOR:
- if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) {
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // edge0
- set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // edge1
- }
- if (op_type == OP_TYPE_SCALAR) {
- set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); // x
- }
- break;
- case OP_TYPE_VECTOR_SCALAR:
- if (op_type == OP_TYPE_VECTOR) {
- set_input_port_default_value(0, 0.0); // edge0
- set_input_port_default_value(1, 0.0); // edge1
- }
- if (op_type == OP_TYPE_SCALAR) {
- set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); // x
- }
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // edge0
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // edge1
+ set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // x
+ break;
+ case OP_TYPE_VECTOR_2D:
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); // edge0
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); // edge1
+ set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // x
+ break;
+ case OP_TYPE_VECTOR_2D_SCALAR:
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // edge0
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // edge1
+ set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // x
+ break;
+ case OP_TYPE_VECTOR_3D:
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // edge0
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // edge1
+ set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); // x
+ break;
+ case OP_TYPE_VECTOR_3D_SCALAR:
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // edge0
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // edge1
+ set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); // x
break;
default:
break;
@@ -3594,18 +3861,20 @@ void VisualShaderNodeSmoothStep::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeSmoothStep::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeSmoothStep::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
VisualShaderNodeSmoothStep::VisualShaderNodeSmoothStep() {
- set_input_port_default_value(0, 0.0);
- set_input_port_default_value(1, 0.0);
- set_input_port_default_value(2, 0.0);
+ set_input_port_default_value(0, 0.0); // edge0
+ set_input_port_default_value(1, 1.0); // edge1
+ set_input_port_default_value(2, 0.5); // x
}
////////////// Distance
@@ -3618,17 +3887,14 @@ int VisualShaderNodeVectorDistance::get_input_port_count() const {
return 2;
}
-VisualShaderNodeVectorDistance::PortType VisualShaderNodeVectorDistance::get_input_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeVectorDistance::get_input_port_name(int p_port) const {
- if (p_port == 0) {
- return "p0";
- } else if (p_port == 1) {
- return "p1";
+ switch (p_port) {
+ case 0:
+ return "a";
+ case 1:
+ return "b";
}
- return "";
+ return String();
}
int VisualShaderNodeVectorDistance::get_output_port_count() const {
@@ -3643,13 +3909,34 @@ String VisualShaderNodeVectorDistance::get_output_port_name(int p_port) const {
return "";
}
+void VisualShaderNodeVectorDistance::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ switch (p_op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); // b
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // b
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
String VisualShaderNodeVectorDistance::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
return " " + p_output_vars[0] + " = distance(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
VisualShaderNodeVectorDistance::VisualShaderNodeVectorDistance() {
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
- set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0));
+ set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // a
+ set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // b
}
////////////// Refract Vector
@@ -3671,14 +3958,15 @@ VisualShaderNodeVectorRefract::PortType VisualShaderNodeVectorRefract::get_input
}
String VisualShaderNodeVectorRefract::get_input_port_name(int p_port) const {
- if (p_port == 0) {
- return "I";
- } else if (p_port == 1) {
- return "N";
- } else if (p_port == 2) {
- return "eta";
+ switch (p_port) {
+ case 0:
+ return "I";
+ case 1:
+ return "N";
+ case 2:
+ return "eta";
}
- return "";
+ return String();
}
int VisualShaderNodeVectorRefract::get_output_port_count() const {
@@ -3715,9 +4003,16 @@ int VisualShaderNodeMix::get_input_port_count() const {
VisualShaderNodeMix::PortType VisualShaderNodeMix::get_input_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_2D_SCALAR:
+ if (p_port == 2) {
+ break;
+ }
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
- case OP_TYPE_VECTOR_SCALAR:
+ case OP_TYPE_VECTOR_3D_SCALAR:
if (p_port == 2) {
break;
}
@@ -3744,9 +4039,13 @@ int VisualShaderNodeMix::get_output_port_count() const {
VisualShaderNodeMix::PortType VisualShaderNodeMix::get_output_port_type(int p_port) const {
switch (op_type) {
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_2D_SCALAR:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
- case OP_TYPE_VECTOR_SCALAR:
+ case OP_TYPE_VECTOR_3D_SCALAR:
return PORT_TYPE_VECTOR;
default:
break;
@@ -3764,27 +4063,31 @@ void VisualShaderNodeMix::set_op_type(OpType p_op_type) {
return;
}
switch (p_op_type) {
- case OP_TYPE_SCALAR:
- set_input_port_default_value(0, 0.0); // a
- set_input_port_default_value(1, 1.0); // b
- if (op_type == OP_TYPE_VECTOR) {
- set_input_port_default_value(2, 0.5); // weight
- }
- break;
- case OP_TYPE_VECTOR:
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // a
- set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); // b
- if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) {
- set_input_port_default_value(2, Vector3(0.5, 0.5, 0.5)); // weight
- }
- break;
- case OP_TYPE_VECTOR_SCALAR:
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // a
- set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); // b
- if (op_type == OP_TYPE_VECTOR) {
- set_input_port_default_value(2, 0.5); // weight
- }
- break;
+ case OP_TYPE_SCALAR: {
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // b
+ set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // weight
+ } break;
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); // b
+ set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // weight
+ } break;
+ case OP_TYPE_VECTOR_2D_SCALAR: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); // b
+ set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // weight
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // b
+ set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); // weight
+ } break;
+ case OP_TYPE_VECTOR_3D_SCALAR: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // b
+ set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // weight
+ } break;
default:
break;
}
@@ -3810,11 +4113,13 @@ void VisualShaderNodeMix::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeMix::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeMix::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
@@ -3831,7 +4136,15 @@ String VisualShaderNodeVectorCompose::get_caption() const {
}
int VisualShaderNodeVectorCompose::get_input_port_count() const {
- return 3;
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D:
+ return 2;
+ case OP_TYPE_VECTOR_3D:
+ return 3;
+ default:
+ break;
+ }
+ return 0;
}
VisualShaderNodeVectorCompose::PortType VisualShaderNodeVectorCompose::get_input_port_type(int p_port) const {
@@ -3839,29 +4152,80 @@ VisualShaderNodeVectorCompose::PortType VisualShaderNodeVectorCompose::get_input
}
String VisualShaderNodeVectorCompose::get_input_port_name(int p_port) const {
- if (p_port == 0) {
- return "x";
- } else if (p_port == 1) {
- return "y";
- } else {
- return "z";
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ switch (p_port) {
+ case 0:
+ return "x";
+ case 1:
+ return "y";
+ }
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ switch (p_port) {
+ case 0:
+ return "x";
+ case 1:
+ return "y";
+ case 2:
+ return "z";
+ }
+ } break;
+ default:
+ break;
}
+ return String();
}
int VisualShaderNodeVectorCompose::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVectorCompose::PortType VisualShaderNodeVectorCompose::get_output_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeVectorCompose::get_output_port_name(int p_port) const {
return "vec";
}
+void VisualShaderNodeVectorCompose::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ switch (p_op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ float p1 = get_input_port_default_value(0);
+ float p2 = get_input_port_default_value(1);
+
+ set_input_port_default_value(0, p1);
+ set_input_port_default_value(1, p2);
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ float p1 = get_input_port_default_value(0);
+ float p2 = get_input_port_default_value(1);
+
+ set_input_port_default_value(0, p1);
+ set_input_port_default_value(1, p2);
+ set_input_port_default_value(2, 0.0);
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
+ emit_changed();
+}
+
String VisualShaderNodeVectorCompose::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ String code;
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ code += " " + p_output_vars[0] + " = vec2(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ code += " " + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
+ } break;
+ default:
+ break;
+ }
+ return code;
}
VisualShaderNodeVectorCompose::VisualShaderNodeVectorCompose() {
@@ -3928,16 +4292,20 @@ int VisualShaderNodeVectorDecompose::get_input_port_count() const {
return 1;
}
-VisualShaderNodeVectorDecompose::PortType VisualShaderNodeVectorDecompose::get_input_port_type(int p_port) const {
- return PORT_TYPE_VECTOR;
-}
-
String VisualShaderNodeVectorDecompose::get_input_port_name(int p_port) const {
return "vec";
}
int VisualShaderNodeVectorDecompose::get_output_port_count() const {
- return 3;
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D:
+ return 2;
+ case OP_TYPE_VECTOR_3D:
+ return 3;
+ default:
+ break;
+ }
+ return 0;
}
VisualShaderNodeVectorDecompose::PortType VisualShaderNodeVectorDecompose::get_output_port_type(int p_port) const {
@@ -3945,25 +4313,70 @@ VisualShaderNodeVectorDecompose::PortType VisualShaderNodeVectorDecompose::get_o
}
String VisualShaderNodeVectorDecompose::get_output_port_name(int p_port) const {
- if (p_port == 0) {
- return "x";
- } else if (p_port == 1) {
- return "y";
- } else {
- return "z";
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ switch (p_port) {
+ case 0:
+ return "x";
+ case 1:
+ return "y";
+ }
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ switch (p_port) {
+ case 0:
+ return "x";
+ case 1:
+ return "y";
+ case 2:
+ return "z";
+ }
+ } break;
+ default:
+ break;
}
+ return String();
+}
+
+void VisualShaderNodeVectorDecompose::set_op_type(OpType p_op_type) {
+ ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX));
+ if (op_type == p_op_type) {
+ return;
+ }
+ switch (p_op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ } break;
+ default:
+ break;
+ }
+ op_type = p_op_type;
+ emit_changed();
}
String VisualShaderNodeVectorDecompose::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String code;
- code += " " + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n";
- code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n";
- code += " " + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n";
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D: {
+ code += " " + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n";
+ code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n";
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ code += " " + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n";
+ code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n";
+ code += " " + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n";
+ } break;
+ default:
+ break;
+ }
return code;
}
VisualShaderNodeVectorDecompose::VisualShaderNodeVectorDecompose() {
- set_input_port_default_value(0, Vector3());
+ set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
}
////////////// Transform Decompose
@@ -4613,10 +5026,110 @@ Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const
VisualShaderNodeColorUniform::VisualShaderNodeColorUniform() {
}
-////////////// Vector Uniform
+////////////// Vector2 Uniform
+
+String VisualShaderNodeVec2Uniform::get_caption() const {
+ return "Vector2Uniform";
+}
+
+int VisualShaderNodeVec2Uniform::get_input_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeVec2Uniform::PortType VisualShaderNodeVec2Uniform::get_input_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR_2D;
+}
+
+String VisualShaderNodeVec2Uniform::get_input_port_name(int p_port) const {
+ return String();
+}
+
+int VisualShaderNodeVec2Uniform::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeVec2Uniform::PortType VisualShaderNodeVec2Uniform::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR_2D;
+}
+
+String VisualShaderNodeVec2Uniform::get_output_port_name(int p_port) const {
+ return String();
+}
+
+void VisualShaderNodeVec2Uniform::set_default_value_enabled(bool p_enabled) {
+ default_value_enabled = p_enabled;
+ emit_changed();
+}
+
+bool VisualShaderNodeVec2Uniform::is_default_value_enabled() const {
+ return default_value_enabled;
+}
+
+void VisualShaderNodeVec2Uniform::set_default_value(const Vector2 &p_value) {
+ default_value = p_value;
+ emit_changed();
+}
+
+Vector2 VisualShaderNodeVec2Uniform::get_default_value() const {
+ return default_value;
+}
+
+String VisualShaderNodeVec2Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform vec2 " + get_uniform_name();
+ if (default_value_enabled) {
+ code += vformat(" = vec2(%.6f, %.6f)", default_value.x, default_value.y);
+ }
+ code += ";\n";
+ return code;
+}
+
+String VisualShaderNodeVec2Uniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+}
+
+void VisualShaderNodeVec2Uniform::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec2Uniform::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec2Uniform::is_default_value_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec2Uniform::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec2Uniform::get_default_value);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "default_value"), "set_default_value", "get_default_value");
+}
+
+bool VisualShaderNodeVec2Uniform::is_show_prop_names() const {
+ return true;
+}
+
+bool VisualShaderNodeVec2Uniform::is_use_prop_slots() const {
+ return true;
+}
+
+bool VisualShaderNodeVec2Uniform::is_qualifier_supported(Qualifier p_qual) const {
+ return true; // all qualifiers are supported
+}
+
+bool VisualShaderNodeVec2Uniform::is_convertible_to_constant() const {
+ return true; // conversion is allowed
+}
+
+Vector<StringName> VisualShaderNodeVec2Uniform::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+ props.push_back("default_value_enabled");
+ if (default_value_enabled) {
+ props.push_back("default_value");
+ }
+ return props;
+}
+
+VisualShaderNodeVec2Uniform::VisualShaderNodeVec2Uniform() {
+}
+
+////////////// Vector3 Uniform
String VisualShaderNodeVec3Uniform::get_caption() const {
- return "VectorUniform";
+ return "Vector3Uniform";
}
int VisualShaderNodeVec3Uniform::get_input_port_count() const {
@@ -4831,7 +5344,7 @@ int VisualShaderNodeTextureUniform::get_input_port_count() const {
}
VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_input_port_type(int p_port) const {
- return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
+ return p_port == 0 ? PORT_TYPE_VECTOR_2D : PORT_TYPE_SCALAR;
}
String VisualShaderNodeTextureUniform::get_input_port_name(int p_port) const {
@@ -4979,7 +5492,7 @@ bool VisualShaderNodeTextureUniform::is_code_generated() const {
String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String default_uv;
if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
- default_uv = "UV.xy";
+ default_uv = "UV";
} else {
default_uv = "vec2(0.0)";
}
@@ -4994,9 +5507,9 @@ String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, Visual
}
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n";
+ code += " vec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " vec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
code += " " + p_output_vars[0] + " = n_tex_read.rgb;\n";
@@ -5562,7 +6075,9 @@ VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_input_port_type(int
switch (op_type) {
case OP_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
case OP_TYPE_BOOLEAN:
return PORT_TYPE_BOOLEAN;
@@ -5596,7 +6111,9 @@ VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_output_port_type(in
switch (op_type) {
case OP_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
- case OP_TYPE_VECTOR:
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
case OP_TYPE_BOOLEAN:
return PORT_TYPE_BOOLEAN;
@@ -5619,16 +6136,20 @@ void VisualShaderNodeSwitch::set_op_type(OpType p_op_type) {
}
switch (p_op_type) {
case OP_TYPE_FLOAT:
- set_input_port_default_value(1, 1.0);
- set_input_port_default_value(2, 0.0);
+ set_input_port_default_value(1, 1.0, get_input_port_default_value(1));
+ set_input_port_default_value(2, 0.0, get_input_port_default_value(2));
break;
case OP_TYPE_INT:
- set_input_port_default_value(1, 1);
- set_input_port_default_value(2, 0);
+ set_input_port_default_value(1, 1, get_input_port_default_value(1));
+ set_input_port_default_value(2, 0, get_input_port_default_value(2));
+ break;
+ case OP_TYPE_VECTOR_2D:
+ set_input_port_default_value(1, Vector2(1.0, 1.0), get_input_port_default_value(1));
+ set_input_port_default_value(2, Vector2(0.0, 0.0), get_input_port_default_value(2));
break;
- case OP_TYPE_VECTOR:
- 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));
+ case OP_TYPE_VECTOR_3D:
+ set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0), get_input_port_default_value(1));
+ set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0), get_input_port_default_value(2));
break;
case OP_TYPE_BOOLEAN:
set_input_port_default_value(1, true);
@@ -5659,11 +6180,12 @@ void VisualShaderNodeSwitch::_bind_methods() { // static
ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeSwitch::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeSwitch::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector,Boolean,Transform"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Boolean,Transform"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_FLOAT);
BIND_ENUM_CONSTANT(OP_TYPE_INT);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
BIND_ENUM_CONSTANT(OP_TYPE_BOOLEAN);
BIND_ENUM_CONSTANT(OP_TYPE_TRANSFORM);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
@@ -5893,7 +6415,9 @@ VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(i
return PORT_TYPE_SCALAR;
case CTYPE_SCALAR_INT:
return PORT_TYPE_SCALAR_INT;
- case CTYPE_VECTOR:
+ case CTYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case CTYPE_VECTOR_3D:
return PORT_TYPE_VECTOR;
case CTYPE_BOOLEAN:
return PORT_TYPE_BOOLEAN;
@@ -5965,7 +6489,7 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader:
String code;
switch (comparison_type) {
- case CTYPE_SCALAR:
+ case CTYPE_SCALAR: {
if (func == FUNC_EQUAL) {
code += " " + p_output_vars[0] + " = (abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");";
} else if (func == FUNC_NOT_EQUAL) {
@@ -5973,33 +6497,34 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader:
} else {
code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n";
}
- break;
-
- case CTYPE_SCALAR_INT:
+ } break;
+ case CTYPE_SCALAR_INT: {
code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n";
- break;
-
- case CTYPE_VECTOR:
+ } break;
+ case CTYPE_VECTOR_2D: {
+ code += " {\n";
+ code += " bvec2 _bv = " + String(functions[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(conditions[condition]).replace("$", "_bv") + ";\n";
+ code += " }\n";
+ } break;
+ case CTYPE_VECTOR_3D: {
code += " {\n";
code += " bvec3 _bv = " + String(functions[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n";
code += " " + p_output_vars[0] + " = " + String(conditions[condition]).replace("$", "_bv") + ";\n";
code += " }\n";
- break;
-
- case CTYPE_BOOLEAN:
+ } break;
+ case CTYPE_BOOLEAN: {
if (func > FUNC_NOT_EQUAL) {
return " " + p_output_vars[0] + " = false;\n";
}
code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n";
- break;
-
- case CTYPE_TRANSFORM:
+ } break;
+ case CTYPE_TRANSFORM: {
if (func > FUNC_NOT_EQUAL) {
return " " + p_output_vars[0] + " = false;\n";
}
code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n";
- break;
-
+ } break;
default:
break;
}
@@ -6013,18 +6538,23 @@ void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_comparison_ty
}
switch (p_comparison_type) {
case CTYPE_SCALAR:
- set_input_port_default_value(0, 0.0);
- set_input_port_default_value(1, 0.0);
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1));
simple_decl = true;
break;
case CTYPE_SCALAR_INT:
- set_input_port_default_value(0, 0);
- set_input_port_default_value(1, 0);
+ set_input_port_default_value(0, 0, get_input_port_default_value(0));
+ set_input_port_default_value(1, 0, get_input_port_default_value(1));
simple_decl = true;
break;
- case CTYPE_VECTOR:
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
- set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0));
+ case CTYPE_VECTOR_2D:
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1));
+ simple_decl = false;
+ break;
+ case CTYPE_VECTOR_3D:
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
simple_decl = false;
break;
case CTYPE_BOOLEAN:
@@ -6078,7 +6608,7 @@ Vector<StringName> VisualShaderNodeCompare::get_editable_properties() const {
Vector<StringName> props;
props.push_back("type");
props.push_back("function");
- if (comparison_type == CTYPE_VECTOR) {
+ if (comparison_type == CTYPE_VECTOR_2D || comparison_type == CTYPE_VECTOR_3D) {
props.push_back("condition");
}
return props;
@@ -6094,13 +6624,14 @@ void VisualShaderNodeCompare::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_condition", "condition"), &VisualShaderNodeCompare::set_condition);
ClassDB::bind_method(D_METHOD("get_condition"), &VisualShaderNodeCompare::get_condition);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Float,Int,Vector,Boolean,Transform"), "set_comparison_type", "get_comparison_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Boolean,Transform"), "set_comparison_type", "get_comparison_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "a == b,a != b,a > b,a >= b,a < b,a <= b"), "set_function", "get_function");
ADD_PROPERTY(PropertyInfo(Variant::INT, "condition", PROPERTY_HINT_ENUM, "All,Any"), "set_condition", "get_condition");
BIND_ENUM_CONSTANT(CTYPE_SCALAR);
BIND_ENUM_CONSTANT(CTYPE_SCALAR_INT);
- BIND_ENUM_CONSTANT(CTYPE_VECTOR);
+ BIND_ENUM_CONSTANT(CTYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(CTYPE_VECTOR_3D);
BIND_ENUM_CONSTANT(CTYPE_BOOLEAN);
BIND_ENUM_CONSTANT(CTYPE_TRANSFORM);
BIND_ENUM_CONSTANT(CTYPE_MAX);
@@ -6135,8 +6666,13 @@ int VisualShaderNodeMultiplyAdd::get_input_port_count() const {
}
VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_input_port_type(int p_port) const {
- if (op_type == OP_TYPE_VECTOR) {
- return PORT_TYPE_VECTOR;
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
+ return PORT_TYPE_VECTOR;
+ default:
+ break;
}
return PORT_TYPE_SCALAR;
}
@@ -6157,11 +6693,15 @@ int VisualShaderNodeMultiplyAdd::get_output_port_count() const {
}
VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_output_port_type(int p_port) const {
- if (op_type == OP_TYPE_SCALAR) {
- return PORT_TYPE_SCALAR;
- } else {
- return PORT_TYPE_VECTOR;
+ switch (op_type) {
+ case OP_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case OP_TYPE_VECTOR_3D:
+ return PORT_TYPE_VECTOR;
+ default:
+ break;
}
+ return PORT_TYPE_SCALAR;
}
String VisualShaderNodeMultiplyAdd::get_output_port_name(int p_port) const {
@@ -6178,16 +6718,21 @@ void VisualShaderNodeMultiplyAdd::set_op_type(OpType p_op_type) {
return;
}
switch (p_op_type) {
- case OP_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);
- break;
- case OP_TYPE_VECTOR:
- set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0));
- set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0));
- set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0));
- break;
+ case OP_TYPE_SCALAR: {
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1));
+ set_input_port_default_value(2, 0.0, get_input_port_default_value(2));
+ } break;
+ case OP_TYPE_VECTOR_2D: {
+ set_input_port_default_value(0, Vector2(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector2(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Vector2(), get_input_port_default_value(2));
+ } break;
+ case OP_TYPE_VECTOR_3D: {
+ set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Vector3(), get_input_port_default_value(2));
+ } break;
default:
break;
}
@@ -6209,10 +6754,11 @@ void VisualShaderNodeMultiplyAdd::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeMultiplyAdd::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeMultiplyAdd::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
- BIND_ENUM_CONSTANT(OP_TYPE_VECTOR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index bf5777a3fb..5c7a674d34 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -34,6 +34,49 @@
#include "scene/resources/visual_shader.h"
///////////////////////////////////////
+/// Vector Base Node
+///////////////////////////////////////
+
+class VisualShaderNodeVectorBase : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeVectorBase, VisualShaderNode);
+
+public:
+ enum OpType {
+ OP_TYPE_VECTOR_2D,
+ OP_TYPE_VECTOR_3D,
+ OP_TYPE_MAX,
+ };
+
+protected:
+ OpType op_type = OP_TYPE_VECTOR_3D;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override = 0;
+
+ virtual int get_input_port_count() const override = 0;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override = 0;
+
+ virtual int get_output_port_count() const override = 0;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override = 0;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override = 0;
+
+ virtual void set_op_type(OpType p_op_type);
+ OpType get_op_type() const;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+
+ VisualShaderNodeVectorBase();
+};
+
+VARIANT_ENUM_CAST(VisualShaderNodeVectorBase::OpType)
+
+///////////////////////////////////////
/// CONSTANTS
///////////////////////////////////////
@@ -177,6 +220,36 @@ public:
///////////////////////////////////////
+class VisualShaderNodeVec2Constant : public VisualShaderNodeConstant {
+ GDCLASS(VisualShaderNodeVec2Constant, VisualShaderNodeConstant);
+ Vector2 constant;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ void set_constant(const Vector2 &p_constant);
+ Vector2 get_constant() const;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+
+ VisualShaderNodeVec2Constant();
+};
+
+///////////////////////////////////////
+
class VisualShaderNodeVec3Constant : public VisualShaderNodeConstant {
GDCLASS(VisualShaderNodeVec3Constant, VisualShaderNodeConstant);
Vector3 constant;
@@ -615,8 +688,8 @@ public:
VARIANT_ENUM_CAST(VisualShaderNodeIntOp::Operator)
-class VisualShaderNodeVectorOp : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVectorOp, VisualShaderNode);
+class VisualShaderNodeVectorOp : public VisualShaderNodeVectorBase {
+ GDCLASS(VisualShaderNodeVectorOp, VisualShaderNodeVectorBase);
public:
enum Operator {
@@ -644,19 +717,20 @@ public:
virtual String get_caption() const override;
virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+ virtual void set_op_type(OpType p_op_type) override;
+
void set_operator(Operator p_op);
Operator get_operator() const;
virtual Vector<StringName> get_editable_properties() const override;
+ String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
VisualShaderNodeVectorOp();
};
@@ -923,8 +997,10 @@ VARIANT_ENUM_CAST(VisualShaderNodeIntFunc::Function)
/// VECTOR FUNC
///////////////////////////////////////
-class VisualShaderNodeVectorFunc : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVectorFunc, VisualShaderNode);
+class VisualShaderNodeVectorFunc : public VisualShaderNodeVectorBase {
+ GDCLASS(VisualShaderNodeVectorFunc, VisualShaderNodeVectorBase);
+
+ void _update_default_input_values();
public:
enum Function {
@@ -975,19 +1051,20 @@ public:
virtual String get_caption() const override;
virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+ virtual void set_op_type(OpType p_op_type) override;
+
void set_function(Function p_func);
Function get_function() const;
virtual Vector<StringName> get_editable_properties() const override;
+ String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
VisualShaderNodeVectorFunc();
};
@@ -1150,20 +1227,20 @@ public:
/// LENGTH
///////////////////////////////////////
-class VisualShaderNodeVectorLen : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVectorLen, VisualShaderNode);
+class VisualShaderNodeVectorLen : public VisualShaderNodeVectorBase {
+ GDCLASS(VisualShaderNodeVectorLen, VisualShaderNodeVectorBase);
public:
virtual String get_caption() const override;
virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual void set_op_type(OpType p_op_type) override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorLen();
@@ -1203,7 +1280,8 @@ public:
enum OpType {
OP_TYPE_FLOAT,
OP_TYPE_INT,
- OP_TYPE_VECTOR,
+ OP_TYPE_VECTOR_2D,
+ OP_TYPE_VECTOR_3D,
OP_TYPE_MAX,
};
@@ -1235,54 +1313,20 @@ public:
VARIANT_ENUM_CAST(VisualShaderNodeClamp::OpType)
///////////////////////////////////////
-/// DERIVATIVE FUNCTIONS
+/// DERIVATIVE FUNCTION
///////////////////////////////////////
-class VisualShaderNodeScalarDerivativeFunc : public VisualShaderNode {
- GDCLASS(VisualShaderNodeScalarDerivativeFunc, VisualShaderNode);
+class VisualShaderNodeDerivativeFunc : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeDerivativeFunc, VisualShaderNode);
public:
- enum Function {
- FUNC_SUM,
- FUNC_X,
- FUNC_Y,
- FUNC_MAX,
+ enum OpType {
+ OP_TYPE_SCALAR,
+ OP_TYPE_VECTOR_2D,
+ OP_TYPE_VECTOR_3D,
+ OP_TYPE_MAX,
};
-protected:
- Function func = FUNC_SUM;
-
- static void _bind_methods();
-
-public:
- virtual String get_caption() const override;
-
- virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
- virtual String get_input_port_name(int p_port) const override;
-
- virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
- virtual String get_output_port_name(int p_port) const override;
-
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
-
- void set_function(Function p_func);
- Function get_function() const;
-
- virtual Vector<StringName> get_editable_properties() const override;
-
- VisualShaderNodeScalarDerivativeFunc();
-};
-
-VARIANT_ENUM_CAST(VisualShaderNodeScalarDerivativeFunc::Function)
-
-///////////////////////////////////////
-
-class VisualShaderNodeVectorDerivativeFunc : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVectorDerivativeFunc, VisualShaderNode);
-
-public:
enum Function {
FUNC_SUM,
FUNC_X,
@@ -1291,8 +1335,10 @@ public:
};
protected:
+ OpType op_type = OP_TYPE_SCALAR;
Function func = FUNC_SUM;
+protected:
static void _bind_methods();
public:
@@ -1308,34 +1354,37 @@ public:
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+ void set_op_type(OpType p_op_type);
+ OpType get_op_type() const;
+
void set_function(Function p_func);
Function get_function() const;
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeVectorDerivativeFunc();
+ VisualShaderNodeDerivativeFunc();
};
-VARIANT_ENUM_CAST(VisualShaderNodeVectorDerivativeFunc::Function)
+VARIANT_ENUM_CAST(VisualShaderNodeDerivativeFunc::OpType)
+VARIANT_ENUM_CAST(VisualShaderNodeDerivativeFunc::Function)
///////////////////////////////////////
/// FACEFORWARD
///////////////////////////////////////
-class VisualShaderNodeFaceForward : public VisualShaderNode {
- GDCLASS(VisualShaderNodeFaceForward, VisualShaderNode);
+class VisualShaderNodeFaceForward : public VisualShaderNodeVectorBase {
+ GDCLASS(VisualShaderNodeFaceForward, VisualShaderNodeVectorBase);
public:
virtual String get_caption() const override;
virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual void set_op_type(OpType p_op_type) override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeFaceForward();
@@ -1374,8 +1423,10 @@ class VisualShaderNodeStep : public VisualShaderNode {
public:
enum OpType {
OP_TYPE_SCALAR,
- OP_TYPE_VECTOR,
- OP_TYPE_VECTOR_SCALAR,
+ OP_TYPE_VECTOR_2D,
+ OP_TYPE_VECTOR_2D_SCALAR,
+ OP_TYPE_VECTOR_3D,
+ OP_TYPE_VECTOR_3D_SCALAR,
OP_TYPE_MAX,
};
@@ -1416,8 +1467,10 @@ class VisualShaderNodeSmoothStep : public VisualShaderNode {
public:
enum OpType {
OP_TYPE_SCALAR,
- OP_TYPE_VECTOR,
- OP_TYPE_VECTOR_SCALAR,
+ OP_TYPE_VECTOR_2D,
+ OP_TYPE_VECTOR_2D_SCALAR,
+ OP_TYPE_VECTOR_3D,
+ OP_TYPE_VECTOR_3D_SCALAR,
OP_TYPE_MAX,
};
@@ -1452,20 +1505,20 @@ VARIANT_ENUM_CAST(VisualShaderNodeSmoothStep::OpType)
/// DISTANCE
///////////////////////////////////////
-class VisualShaderNodeVectorDistance : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVectorDistance, VisualShaderNode);
+class VisualShaderNodeVectorDistance : public VisualShaderNodeVectorBase {
+ GDCLASS(VisualShaderNodeVectorDistance, VisualShaderNodeVectorBase);
public:
virtual String get_caption() const override;
virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual void set_op_type(OpType p_op_type) override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorDistance();
@@ -1504,8 +1557,10 @@ class VisualShaderNodeMix : public VisualShaderNode {
public:
enum OpType {
OP_TYPE_SCALAR,
- OP_TYPE_VECTOR,
- OP_TYPE_VECTOR_SCALAR,
+ OP_TYPE_VECTOR_2D,
+ OP_TYPE_VECTOR_2D_SCALAR,
+ OP_TYPE_VECTOR_3D,
+ OP_TYPE_VECTOR_3D_SCALAR,
OP_TYPE_MAX,
};
@@ -1540,8 +1595,8 @@ VARIANT_ENUM_CAST(VisualShaderNodeMix::OpType)
/// COMPOSE
///////////////////////////////////////
-class VisualShaderNodeVectorCompose : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVectorCompose, VisualShaderNode);
+class VisualShaderNodeVectorCompose : public VisualShaderNodeVectorBase {
+ GDCLASS(VisualShaderNodeVectorCompose, VisualShaderNodeVectorBase);
public:
virtual String get_caption() const override;
@@ -1551,9 +1606,9 @@ public:
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual void set_op_type(OpType p_op_type) override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorCompose();
@@ -1584,20 +1639,20 @@ public:
/// DECOMPOSE
///////////////////////////////////////
-class VisualShaderNodeVectorDecompose : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVectorDecompose, VisualShaderNode);
+class VisualShaderNodeVectorDecompose : public VisualShaderNodeVectorBase {
+ GDCLASS(VisualShaderNodeVectorDecompose, VisualShaderNodeVectorBase);
public:
virtual String get_caption() const override;
virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual void set_op_type(OpType p_op_type) override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeVectorDecompose();
@@ -1849,6 +1904,49 @@ public:
///////////////////////////////////////
+class VisualShaderNodeVec2Uniform : public VisualShaderNodeUniform {
+ GDCLASS(VisualShaderNodeVec2Uniform, VisualShaderNodeUniform);
+
+private:
+ bool default_value_enabled = false;
+ Vector2 default_value;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ virtual bool is_show_prop_names() const override;
+ virtual bool is_use_prop_slots() const override;
+
+ void set_default_value_enabled(bool p_enabled);
+ bool is_default_value_enabled() const;
+
+ void set_default_value(const Vector2 &p_value);
+ Vector2 get_default_value() const;
+
+ bool is_qualifier_supported(Qualifier p_qual) const override;
+ bool is_convertible_to_constant() const override;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+
+ VisualShaderNodeVec2Uniform();
+};
+
+///////////////////////////////////////
+
class VisualShaderNodeVec3Uniform : public VisualShaderNodeUniform {
GDCLASS(VisualShaderNodeVec3Uniform, VisualShaderNodeUniform);
@@ -2148,7 +2246,8 @@ public:
enum OpType {
OP_TYPE_FLOAT,
OP_TYPE_INT,
- OP_TYPE_VECTOR,
+ OP_TYPE_VECTOR_2D,
+ OP_TYPE_VECTOR_3D,
OP_TYPE_BOOLEAN,
OP_TYPE_TRANSFORM,
OP_TYPE_MAX,
@@ -2261,7 +2360,8 @@ public:
enum ComparisonType {
CTYPE_SCALAR,
CTYPE_SCALAR_INT,
- CTYPE_VECTOR,
+ CTYPE_VECTOR_2D,
+ CTYPE_VECTOR_3D,
CTYPE_BOOLEAN,
CTYPE_TRANSFORM,
CTYPE_MAX,
@@ -2329,7 +2429,8 @@ class VisualShaderNodeMultiplyAdd : public VisualShaderNode {
public:
enum OpType {
OP_TYPE_SCALAR,
- OP_TYPE_VECTOR,
+ OP_TYPE_VECTOR_2D,
+ OP_TYPE_VECTOR_3D,
OP_TYPE_MAX,
};