summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/collision_shape_2d.cpp22
-rw-r--r--scene/2d/ray_cast_2d.cpp19
-rw-r--r--scene/gui/graph_node.cpp4
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--scene/register_scene_types.cpp3
-rw-r--r--scene/resources/visual_shader.cpp41
-rw-r--r--scene/resources/visual_shader.h4
-rw-r--r--scene/resources/visual_shader_nodes.cpp406
-rw-r--r--scene/resources/visual_shader_nodes.h130
9 files changed, 604 insertions, 29 deletions
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 5440a1d8c3..f79d79d039 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -97,15 +97,8 @@ void CollisionShape2D::_notification(int p_what) {
}
owner_id = 0;
parent = NULL;
- } break;
- /*
- case NOTIFICATION_TRANSFORM_CHANGED: {
-
- if (!is_inside_scene())
- break;
- _update_parent();
- } break;*/
+ } break;
case NOTIFICATION_DRAW: {
if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
@@ -131,10 +124,13 @@ void CollisionShape2D::_notification(int p_what) {
rect = rect.grow(3);
if (one_way_collision) {
- Color dcol = get_tree()->get_debug_collisions_color(); //0.9,0.2,0.2,0.4);
- dcol.a = 1.0;
+ // Draw an arrow indicating the one-way collision direction
+ draw_col = get_tree()->get_debug_collisions_color().inverted();
+ if (disabled) {
+ draw_col = draw_col.darkened(0.25);
+ }
Vector2 line_to(0, 20);
- draw_line(Vector2(), line_to, dcol, 3);
+ draw_line(Vector2(), line_to, draw_col, 2, true);
Vector<Vector2> pts;
float tsize = 8;
pts.push_back(line_to + (Vector2(0, tsize)));
@@ -142,9 +138,9 @@ void CollisionShape2D::_notification(int p_what) {
pts.push_back(line_to + (Vector2(-0.707 * tsize, 0)));
Vector<Color> cols;
for (int i = 0; i < 3; i++)
- cols.push_back(dcol);
+ cols.push_back(draw_col);
- draw_primitive(pts, cols, Vector<Vector2>()); //small arrow
+ draw_primitive(pts, cols, Vector<Vector2>());
}
} break;
}
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index 57dfe5176d..bf8d008bb2 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -100,6 +100,7 @@ Vector2 RayCast2D::get_collision_normal() const {
void RayCast2D::set_enabled(bool p_enabled) {
enabled = p_enabled;
+ update();
if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint())
set_physics_process_internal(p_enabled);
if (!p_enabled)
@@ -167,19 +168,25 @@ void RayCast2D::_notification(int p_what) {
xf.rotate(cast_to.angle());
xf.translate(Vector2(cast_to.length(), 0));
- //Vector2 tip = Vector2(0,s->get_length());
- Color dcol = get_tree()->get_debug_collisions_color(); //0.9,0.2,0.2,0.4);
- draw_line(Vector2(), cast_to, dcol, 3);
+ // Draw an arrow indicating where the RayCast is pointing to
+ Color draw_col = get_tree()->get_debug_collisions_color();
+ if (!enabled) {
+ float g = draw_col.get_v();
+ draw_col.r = g;
+ draw_col.g = g;
+ draw_col.b = g;
+ }
+ draw_line(Vector2(), cast_to, draw_col, 2, true);
Vector<Vector2> pts;
- float tsize = 4;
+ float tsize = 8;
pts.push_back(xf.xform(Vector2(tsize, 0)));
pts.push_back(xf.xform(Vector2(0, 0.707 * tsize)));
pts.push_back(xf.xform(Vector2(0, -0.707 * tsize)));
Vector<Color> cols;
for (int i = 0; i < 3; i++)
- cols.push_back(dcol);
+ cols.push_back(draw_col);
- draw_primitive(pts, cols, Vector<Vector2>()); //small arrow
+ draw_primitive(pts, cols, Vector<Vector2>());
} break;
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 6463ee5ad5..222c75b21d 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -599,6 +599,8 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
Vector2 mpos = Vector2(mb->get_position().x, mb->get_position().y);
if (close_rect.size != Size2() && close_rect.has_point(mpos)) {
+ //send focus to parent
+ get_parent_control()->grab_focus();
emit_signal("close_request");
accept_event();
return;
@@ -615,9 +617,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
return;
}
- //send focus to parent
emit_signal("raise_request");
- get_parent_control()->grab_focus();
}
if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 24c8ee31b2..d147d43f50 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2579,7 +2579,7 @@ void Viewport::_drop_physics_mouseover() {
List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) {
- gui.modal_stack.push_back(p_control);
+ List<Control *>::Element *node = gui.modal_stack.push_back(p_control);
if (gui.key_focus)
p_control->_modal_set_prev_focus_owner(gui.key_focus->get_instance_id());
else
@@ -2590,7 +2590,7 @@ List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) {
_drop_mouse_focus();
}
- return gui.modal_stack.back();
+ return node;
}
Control *Viewport::_gui_get_focus_owner() {
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 0423fcb5f0..2533d91156 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -522,11 +522,14 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeVec3Uniform>();
ClassDB::register_class<VisualShaderNodeTransformUniform>();
ClassDB::register_class<VisualShaderNodeTextureUniform>();
+ ClassDB::register_class<VisualShaderNodeTextureUniformTriplanar>();
ClassDB::register_class<VisualShaderNodeCubeMapUniform>();
ClassDB::register_class<VisualShaderNodeIf>();
ClassDB::register_class<VisualShaderNodeSwitch>();
ClassDB::register_class<VisualShaderNodeFresnel>();
ClassDB::register_class<VisualShaderNodeExpression>();
+ ClassDB::register_class<VisualShaderNodeIs>();
+ ClassDB::register_class<VisualShaderNodeCompare>();
ClassDB::register_class<ShaderMaterial>();
ClassDB::register_virtual_class<CanvasItem>();
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 7265c9b457..8475a34818 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -67,6 +67,14 @@ String VisualShaderNode::generate_global(Shader::Mode p_mode, VisualShader::Type
return String();
}
+String VisualShaderNode::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ return String();
+}
+
+String VisualShaderNode::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ return String();
+}
+
Vector<StringName> VisualShaderNode::get_editable_properties() const {
return Vector<StringName>();
}
@@ -449,7 +457,10 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
ERR_FAIL_COND_V(node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_TRANSFORM, String());
StringBuilder global_code;
+ StringBuilder global_code_per_node;
+ Map<Type, StringBuilder> global_code_per_func;
StringBuilder code;
+ Set<StringName> classes;
global_code += String() + "shader_type canvas_item;\n";
@@ -474,7 +485,7 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
code += "\nvoid fragment() {\n";
Set<int> processed;
- Error err = _write_node(p_type, global_code, code, default_tex_params, input_connections, output_connections, p_node, processed, true);
+ 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) {
@@ -489,6 +500,7 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
//set code secretly
global_code += "\n\n";
String final_code = global_code;
+ final_code += global_code_per_node;
final_code += code;
return final_code;
}
@@ -833,7 +845,7 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
-Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview) const {
+Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const {
const Ref<VisualShaderNode> vsnode = graph[type].nodes[node].node;
@@ -850,7 +862,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
continue;
}
- Error err = _write_node(type, global_code, code, def_tex_params, input_connections, output_connections, from_node, processed, for_preview);
+ Error err = _write_node(type, global_code, global_code_per_node, global_code_per_func, code, def_tex_params, input_connections, output_connections, from_node, processed, for_preview, r_classes);
if (err)
return err;
}
@@ -958,6 +970,14 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
if (!skip_global) {
global_code += vsnode->generate_global(get_mode(), type, node);
+
+ if (!r_classes.has(vsnode->get_class_name())) {
+ global_code_per_node += vsnode->generate_global_per_node(get_mode(), type, node);
+ for (int i = 0; i < TYPE_MAX; i++) {
+ global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node);
+ }
+ r_classes.insert(vsnode->get_class_name());
+ }
}
//handle normally
@@ -976,8 +996,12 @@ void VisualShader::_update_shader() const {
dirty = false;
StringBuilder global_code;
+ StringBuilder global_code_per_node;
+ Map<Type, StringBuilder> global_code_per_func;
StringBuilder code;
Vector<VisualShader::DefaultTextureParam> default_tex_params;
+ Set<StringName> classes;
+ List<int> insertion_pos;
static const char *shader_mode_str[Shader::MODE_MAX] = { "spatial", "canvas_item", "particles" };
global_code += String() + "shader_type " + shader_mode_str[shader_mode] + ";\n";
@@ -1056,8 +1080,9 @@ void VisualShader::_update_shader() const {
code += "\nvoid " + String(func_name[i]) + "() {\n";
Set<int> processed;
- Error err = _write_node(Type(i), global_code, code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false);
+ Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
ERR_FAIL_COND(err != OK);
+ insertion_pos.push_back(code.get_string_length());
code += "}\n";
}
@@ -1065,7 +1090,13 @@ void VisualShader::_update_shader() const {
//set code secretly
global_code += "\n\n";
String final_code = global_code;
- final_code += code;
+ final_code += global_code_per_node;
+ String tcode = code;
+ for (int i = 0; i < TYPE_MAX; i++) {
+ tcode = tcode.insert(insertion_pos[i], global_code_per_func[Type(i)]);
+ }
+ final_code += tcode;
+
const_cast<VisualShader *>(this)->set_code(final_code);
for (int i = 0; i < default_tex_params.size(); i++) {
const_cast<VisualShader *>(this)->set_default_texture_param(default_tex_params[i].name, default_tex_params[i].param);
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 83db51b1b0..b3c0ab6e0b 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -103,7 +103,7 @@ private:
}
};
- Error _write_node(Type p_type, StringBuilder &global_code, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview) const;
+ Error _write_node(Type p_type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const;
void _input_type_changed(Type p_type, int p_id);
@@ -208,6 +208,8 @@ public:
virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
+ virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
+ virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
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 = 0; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 746edc65b0..06f18472ce 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -2968,6 +2968,98 @@ VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() {
color_default = COLOR_DEFAULT_WHITE;
}
+////////////// Texture Uniform (Triplanar)
+
+String VisualShaderNodeTextureUniformTriplanar::get_caption() const {
+ return "TextureUniformTriplanar";
+}
+
+int VisualShaderNodeTextureUniformTriplanar::get_input_port_count() const {
+ return 2;
+}
+
+VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniformTriplanar::get_input_port_type(int p_port) const {
+ if (p_port == 0) {
+ return PORT_TYPE_VECTOR;
+ } else if (p_port == 1) {
+ return PORT_TYPE_VECTOR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeTextureUniformTriplanar::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "weights";
+ } else if (p_port == 1) {
+ return "pos";
+ }
+ return "";
+}
+
+String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+
+ String code;
+
+ code += "// TRIPLANAR FUNCTION GLOBAL CODE\n";
+ code += "\tvec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {\n";
+ code += "\t\tvec4 samp = vec4(0.0);\n";
+ code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;\n";
+ code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;\n";
+ code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;\n";
+ code += "\t\treturn samp;\n";
+ code += "\t}\n";
+ code += "\n";
+ code += "\tuniform vec3 triplanar_scale = vec3(1.0, 1.0, 1.0);\n";
+ code += "\tuniform vec3 triplanar_offset;\n";
+ code += "\tuniform float triplanar_sharpness = 0.5;\n";
+ code += "\n";
+ code += "\tvarying vec3 triplanar_power_normal;\n";
+ code += "\tvarying vec3 triplanar_pos;\n";
+
+ return code;
+}
+
+String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+
+ String code;
+
+ if (p_type == VisualShader::TYPE_VERTEX) {
+
+ code += "\t// TRIPLANAR FUNCTION VERTEX CODE\n";
+ code += "\t\ttriplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n";
+ code += "\t\ttriplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n";
+ code += "\t\ttriplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n";
+ code += "\t\ttriplanar_pos *= vec3(1.0, -1.0, 1.0);\n";
+ }
+
+ return code;
+}
+
+String VisualShaderNodeTextureUniformTriplanar::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 id = get_uniform_name();
+ String code = "\t{\n";
+
+ if (p_input_vars[0] == String() && p_input_vars[1] == String()) {
+ code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal, triplanar_pos );\n";
+ } else if (p_input_vars[0] != String() && p_input_vars[1] == String()) {
+ code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", triplanar_pos );\n";
+ } else if (p_input_vars[0] == String() && p_input_vars[1] != String()) {
+ code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal," + p_input_vars[1] + " );\n";
+ } else {
+ code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + " );\n";
+ }
+
+ code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n";
+ code += "\t\t" + p_output_vars[1] + " = n_tex_read.a;\n";
+ code += "\t}\n";
+
+ return code;
+}
+
+VisualShaderNodeTextureUniformTriplanar::VisualShaderNodeTextureUniformTriplanar() {
+}
+
////////////// CubeMap Uniform
String VisualShaderNodeCubeMapUniform::get_caption() const {
@@ -3200,3 +3292,317 @@ VisualShaderNodeFresnel::VisualShaderNodeFresnel() {
set_input_port_default_value(2, false);
set_input_port_default_value(3, 1.0);
}
+
+////////////// Is
+
+String VisualShaderNodeIs::get_caption() const {
+
+ return "Is";
+}
+
+int VisualShaderNodeIs::get_input_port_count() const {
+
+ return 1;
+}
+
+VisualShaderNodeIs::PortType VisualShaderNodeIs::get_input_port_type(int p_port) const {
+
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeIs::get_input_port_name(int p_port) const {
+
+ return "";
+}
+
+int VisualShaderNodeIs::get_output_port_count() const {
+
+ return 1;
+}
+
+VisualShaderNodeIs::PortType VisualShaderNodeIs::get_output_port_type(int p_port) const {
+
+ return PORT_TYPE_BOOLEAN;
+}
+
+String VisualShaderNodeIs::get_output_port_name(int p_port) const {
+
+ return "";
+}
+
+String VisualShaderNodeIs::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 *funcs[FUNC_IS_NAN + 1] = {
+ "isinf($)",
+ "isnan($)"
+ };
+
+ String code;
+ code += "\t" + p_output_vars[0] + "=" + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n";
+ return code;
+}
+
+void VisualShaderNodeIs::set_function(Function p_func) {
+
+ func = p_func;
+ emit_changed();
+}
+
+VisualShaderNodeIs::Function VisualShaderNodeIs::get_function() const {
+
+ return func;
+}
+
+Vector<StringName> VisualShaderNodeIs::get_editable_properties() const {
+
+ Vector<StringName> props;
+ props.push_back("function");
+ return props;
+}
+
+void VisualShaderNodeIs::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeIs::set_function);
+ ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeIs::get_function);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Inf,NaN"), "set_function", "get_function");
+
+ BIND_ENUM_CONSTANT(FUNC_IS_INF);
+ BIND_ENUM_CONSTANT(FUNC_IS_NAN);
+}
+
+VisualShaderNodeIs::VisualShaderNodeIs() {
+
+ func = FUNC_IS_INF;
+ set_input_port_default_value(0, 0.0);
+}
+
+////////////// Compare
+
+String VisualShaderNodeCompare::get_caption() const {
+
+ return "Compare";
+}
+
+int VisualShaderNodeCompare::get_input_port_count() const {
+
+ if (ctype == CTYPE_SCALAR && (func == FUNC_EQUAL || func == FUNC_NOT_EQUAL)) {
+ return 3;
+ }
+ return 2;
+}
+
+VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(int p_port) const {
+
+ if (p_port == 2)
+ return PORT_TYPE_SCALAR;
+ switch (ctype) {
+ case CTYPE_SCALAR:
+ return PORT_TYPE_SCALAR;
+ case CTYPE_VECTOR:
+ return PORT_TYPE_VECTOR;
+ case CTYPE_BOOLEAN:
+ return PORT_TYPE_BOOLEAN;
+ case CTYPE_TRANSFORM:
+ return PORT_TYPE_TRANSFORM;
+ }
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeCompare::get_input_port_name(int p_port) const {
+ if (p_port == 0)
+ return "a";
+ else if (p_port == 1)
+ return "b";
+ else if (p_port == 2)
+ return "tolerance";
+ return "";
+}
+
+int VisualShaderNodeCompare::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_output_port_type(int p_port) const {
+ return PORT_TYPE_BOOLEAN;
+}
+
+String VisualShaderNodeCompare::get_output_port_name(int p_port) const {
+ if (p_port == 0)
+ return "result";
+ return "";
+}
+
+String VisualShaderNodeCompare::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
+
+ if (ctype == CTYPE_BOOLEAN || ctype == CTYPE_TRANSFORM) {
+ if (func > FUNC_NOT_EQUAL) {
+ return TTR("Invalid comparsion function for that type.");
+ }
+ }
+
+ return "";
+}
+
+String VisualShaderNodeCompare::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 *ops[FUNC_LESS_THAN_EQUAL + 1] = {
+ "==",
+ "!=",
+ ">",
+ ">=",
+ "<",
+ "<=",
+ };
+
+ static const char *funcs[FUNC_LESS_THAN_EQUAL + 1] = {
+ "equal($)",
+ "notEqual($)",
+ "greaterThan($)",
+ "greaterThanEqual($)",
+ "lessThan($)",
+ "lessThanEqual($)",
+ };
+
+ static const char *conds[COND_ANY + 1] = {
+ "all($)",
+ "any($)",
+ };
+
+ String code;
+ switch (ctype) {
+ case CTYPE_SCALAR:
+ if (func == FUNC_EQUAL) {
+ code += "\t" + p_output_vars[0] + "=(abs(" + p_input_vars[0] + "-" + p_input_vars[1] + ")<" + p_input_vars[2] + ");";
+ } else if (func == FUNC_NOT_EQUAL) {
+ code += "\t" + p_output_vars[0] + "=!(abs(" + p_input_vars[0] + "-" + p_input_vars[1] + ")<" + p_input_vars[2] + ");";
+ } else {
+ code += "\t" + p_output_vars[0] + "=" + (p_input_vars[0] + "$" + p_input_vars[1]).replace("$", ops[func]) + ";\n";
+ }
+ break;
+
+ case CTYPE_VECTOR:
+ code += "\t{\n";
+ code += "\t\tbvec3 _bv=" + String(funcs[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n";
+ code += "\t\t" + p_output_vars[0] + "=" + String(conds[condition]).replace("$", "_bv") + ";\n";
+ code += "\t}\n";
+ break;
+
+ case CTYPE_BOOLEAN:
+ if (func > FUNC_NOT_EQUAL)
+ return "\t" + p_output_vars[0] + "=false;\n";
+ code += "\t" + p_output_vars[0] + "=" + (p_input_vars[0] + "$" + p_input_vars[1]).replace("$", ops[func]) + ";\n";
+ break;
+
+ case CTYPE_TRANSFORM:
+ if (func > FUNC_NOT_EQUAL)
+ return "\t" + p_output_vars[0] + "=false;\n";
+ code += "\t" + p_output_vars[0] + "=" + (p_input_vars[0] + "$" + p_input_vars[1]).replace("$", ops[func]) + ";\n";
+ break;
+
+ default:
+ break;
+ }
+ return code;
+}
+
+void VisualShaderNodeCompare::set_comparsion_type(ComparsionType p_type) {
+
+ ctype = p_type;
+
+ switch (ctype) {
+ case CTYPE_SCALAR:
+ set_input_port_default_value(0, 0.0);
+ set_input_port_default_value(1, 0.0);
+ 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));
+ break;
+ case CTYPE_BOOLEAN:
+ set_input_port_default_value(0, false);
+ set_input_port_default_value(1, false);
+ break;
+ case CTYPE_TRANSFORM:
+ set_input_port_default_value(0, Transform());
+ set_input_port_default_value(1, Transform());
+ break;
+ }
+ emit_changed();
+}
+
+VisualShaderNodeCompare::ComparsionType VisualShaderNodeCompare::get_comparsion_type() const {
+
+ return ctype;
+}
+
+void VisualShaderNodeCompare::set_function(Function p_func) {
+
+ func = p_func;
+ emit_changed();
+}
+
+VisualShaderNodeCompare::Function VisualShaderNodeCompare::get_function() const {
+
+ return func;
+}
+
+void VisualShaderNodeCompare::set_condition(Condition p_cond) {
+
+ condition = p_cond;
+ emit_changed();
+}
+
+VisualShaderNodeCompare::Condition VisualShaderNodeCompare::get_condition() const {
+
+ return condition;
+}
+
+Vector<StringName> VisualShaderNodeCompare::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("type");
+ props.push_back("function");
+ if (ctype == CTYPE_VECTOR)
+ props.push_back("condition");
+ return props;
+}
+
+void VisualShaderNodeCompare::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_comparsion_type", "type"), &VisualShaderNodeCompare::set_comparsion_type);
+ ClassDB::bind_method(D_METHOD("get_comparsion_type"), &VisualShaderNodeCompare::get_comparsion_type);
+
+ ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeCompare::set_function);
+ ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeCompare::get_function);
+
+ 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, "Scalar,Vector,Boolean,Transform"), "set_comparsion_type", "get_comparsion_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_VECTOR);
+ BIND_ENUM_CONSTANT(CTYPE_BOOLEAN);
+ BIND_ENUM_CONSTANT(CTYPE_TRANSFORM);
+
+ BIND_ENUM_CONSTANT(FUNC_EQUAL);
+ BIND_ENUM_CONSTANT(FUNC_NOT_EQUAL);
+ BIND_ENUM_CONSTANT(FUNC_GREATER_THAN);
+ BIND_ENUM_CONSTANT(FUNC_GREATER_THAN_EQUAL);
+ BIND_ENUM_CONSTANT(FUNC_LESS_THAN);
+ BIND_ENUM_CONSTANT(FUNC_LESS_THAN_EQUAL);
+
+ BIND_ENUM_CONSTANT(COND_ALL);
+ BIND_ENUM_CONSTANT(COND_ANY);
+}
+
+VisualShaderNodeCompare::VisualShaderNodeCompare() {
+ ctype = CTYPE_SCALAR;
+ func = FUNC_EQUAL;
+ condition = COND_ALL;
+ set_input_port_default_value(0, 0.0);
+ set_input_port_default_value(1, 0.0);
+ set_input_port_default_value(2, CMP_EPSILON);
+}
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 235714f697..cafc7a0f00 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -1425,6 +1425,25 @@ VARIANT_ENUM_CAST(VisualShaderNodeTextureUniform::ColorDefault)
///////////////////////////////////////
+class VisualShaderNodeTextureUniformTriplanar : public VisualShaderNodeTextureUniform {
+ GDCLASS(VisualShaderNodeTextureUniformTriplanar, VisualShaderNodeTextureUniform);
+
+public:
+ virtual String get_caption() const;
+
+ virtual int get_input_port_count() const;
+ virtual PortType get_input_port_type(int p_port) const;
+ virtual String get_input_port_name(int p_port) const;
+
+ virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
+ virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
+ 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+
+ VisualShaderNodeTextureUniformTriplanar();
+};
+
+///////////////////////////////////////
+
class VisualShaderNodeCubeMapUniform : public VisualShaderNode {
GDCLASS(VisualShaderNodeCubeMapUniform, VisualShaderNode);
@@ -1513,4 +1532,115 @@ public:
VisualShaderNodeFresnel();
};
+///////////////////////////////////////
+/// Is
+///////////////////////////////////////
+
+class VisualShaderNodeIs : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeIs, VisualShaderNode);
+
+public:
+ enum Function {
+ FUNC_IS_INF,
+ FUNC_IS_NAN,
+ };
+
+protected:
+ Function func;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const;
+
+ virtual int get_input_port_count() const;
+ virtual PortType get_input_port_type(int p_port) const;
+ virtual String get_input_port_name(int p_port) const;
+
+ virtual int get_output_port_count() const;
+ virtual PortType get_output_port_type(int p_port) const;
+ virtual String get_output_port_name(int p_port) const;
+
+ 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+
+ void set_function(Function p_func);
+ Function get_function() const;
+
+ virtual Vector<StringName> get_editable_properties() const;
+
+ VisualShaderNodeIs();
+};
+
+VARIANT_ENUM_CAST(VisualShaderNodeIs::Function)
+
+///////////////////////////////////////
+/// Compare
+///////////////////////////////////////
+
+class VisualShaderNodeCompare : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeCompare, VisualShaderNode);
+
+public:
+ enum ComparsionType {
+ CTYPE_SCALAR,
+ CTYPE_VECTOR,
+ CTYPE_BOOLEAN,
+ CTYPE_TRANSFORM
+ };
+
+ enum Function {
+ FUNC_EQUAL,
+ FUNC_NOT_EQUAL,
+ FUNC_GREATER_THAN,
+ FUNC_GREATER_THAN_EQUAL,
+ FUNC_LESS_THAN,
+ FUNC_LESS_THAN_EQUAL,
+ };
+
+ enum Condition {
+ COND_ALL,
+ COND_ANY,
+ };
+
+protected:
+ ComparsionType ctype;
+ Function func;
+ Condition condition;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const;
+
+ virtual int get_input_port_count() const;
+ virtual PortType get_input_port_type(int p_port) const;
+ virtual String get_input_port_name(int p_port) const;
+
+ virtual int get_output_port_count() const;
+ virtual PortType get_output_port_type(int p_port) const;
+ virtual String get_output_port_name(int p_port) const;
+
+ 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
+
+ void set_comparsion_type(ComparsionType p_func);
+ ComparsionType get_comparsion_type() const;
+
+ void set_function(Function p_func);
+ Function get_function() const;
+
+ void set_condition(Condition p_mode);
+ Condition get_condition() const;
+
+ virtual Vector<StringName> get_editable_properties() const;
+ virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const;
+
+ VisualShaderNodeCompare();
+};
+
+VARIANT_ENUM_CAST(VisualShaderNodeCompare::ComparsionType)
+VARIANT_ENUM_CAST(VisualShaderNodeCompare::Function)
+VARIANT_ENUM_CAST(VisualShaderNodeCompare::Condition)
+
#endif // VISUAL_SHADER_NODES_H