diff options
-rw-r--r-- | doc/classes/VisualShaderNodeMultiplyAdd.xml | 29 | ||||
-rw-r--r-- | drivers/gles2/shader_compiler_gles2.cpp | 2 | ||||
-rw-r--r-- | drivers/gles2/shaders/stdlib.glsl | 20 | ||||
-rw-r--r-- | editor/editor_asset_installer.cpp | 25 | ||||
-rw-r--r-- | editor/editor_asset_installer.h | 1 | ||||
-rw-r--r-- | editor/editor_node.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/visual_shader_editor_plugin.cpp | 8 | ||||
-rw-r--r-- | methods.py | 5 | ||||
-rw-r--r-- | scene/2d/camera_2d.cpp | 19 | ||||
-rw-r--r-- | scene/2d/camera_2d.h | 1 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 1 | ||||
-rw-r--r-- | scene/resources/visual_shader_nodes.cpp | 93 | ||||
-rw-r--r-- | scene/resources/visual_shader_nodes.h | 39 | ||||
-rw-r--r-- | servers/rendering/shader_language.cpp | 7 |
14 files changed, 242 insertions, 10 deletions
diff --git a/doc/classes/VisualShaderNodeMultiplyAdd.xml b/doc/classes/VisualShaderNodeMultiplyAdd.xml new file mode 100644 index 0000000000..ba79b3fe8f --- /dev/null +++ b/doc/classes/VisualShaderNodeMultiplyAdd.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeMultiplyAdd" inherits="VisualShaderNode" version="4.0"> + <brief_description> + Performs a fused multiply-add operation within the visual shader graph. + </brief_description> + <description> + Uses three operands to compute [code](a * b + c)[/code] expression. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <members> + <member name="type" type="int" setter="set_type" getter="get_type" enum="VisualShaderNodeMultiplyAdd.Type" default="0"> + A type of operands and returned value. + </member> + </members> + <constants> + <constant name="TYPE_SCALAR" value="0" enum="Type"> + A scalar type. + </constant> + <constant name="TYPE_VECTOR" value="1" enum="Type"> + A vector type. + </constant> + <constant name="TYPE_MAX" value="2" enum="Type"> + Represents the size of the [enum Type] enum. + </constant> + </constants> +</class> diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index a5e85424b7..1e30f0dfa1 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -1016,6 +1016,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[RS::SHADER_CANVAS_ITEM].usage_defines["isinf"] = "#define IS_INF_USED\n"; actions[RS::SHADER_CANVAS_ITEM].usage_defines["isnan"] = "#define IS_NAN_USED\n"; actions[RS::SHADER_CANVAS_ITEM].usage_defines["trunc"] = "#define TRUNC_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["fma"] = "#define FMA_USED\n"; /** SPATIAL SHADER **/ @@ -1126,6 +1127,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[RS::SHADER_SPATIAL].usage_defines["isinf"] = "#define IS_INF_USED\n"; actions[RS::SHADER_SPATIAL].usage_defines["isnan"] = "#define IS_NAN_USED\n"; actions[RS::SHADER_SPATIAL].usage_defines["trunc"] = "#define TRUNC_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["fma"] = "#define FMA_USED\n"; actions[RS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions[RS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; diff --git a/drivers/gles2/shaders/stdlib.glsl b/drivers/gles2/shaders/stdlib.glsl index 9c74418743..807036dda6 100644 --- a/drivers/gles2/shaders/stdlib.glsl +++ b/drivers/gles2/shaders/stdlib.glsl @@ -417,4 +417,24 @@ highp mat4 outerProduct(highp vec4 c, highp vec4 r) { #endif +#if defined(FMA_USED) + +highp float fma(highp float a, highp float b, highp float c) { + return a * b + c; +} + +highp vec2 fma(highp vec2 a, highp vec2 b, highp vec2 c) { + return a * b + c; +} + +highp vec3 fma(highp vec3 a, highp vec3 b, highp vec3 c) { + return a * b + c; +} + +highp vec4 fma(highp vec4 a, highp vec4 b, highp vec4 c) { + return a * b + c; +} + +#endif + #endif diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index edb299bb90..8aeeba52ed 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -54,6 +54,27 @@ void EditorAssetInstaller::_update_subitems(TreeItem *p_item, bool p_check, bool } } +void EditorAssetInstaller::_uncheck_parent(TreeItem *p_item) { + if (!p_item) { + return; + } + + bool any_checked = false; + TreeItem *item = p_item->get_children(); + while (item) { + if (item->is_checked(0)) { + any_checked = true; + break; + } + item = item->get_next(); + } + + if (!any_checked) { + p_item->set_checked(0, false); + _uncheck_parent(p_item->get_parent()); + } +} + void EditorAssetInstaller::_item_edited() { if (updating) { return; @@ -67,7 +88,7 @@ void EditorAssetInstaller::_item_edited() { String path = item->get_metadata(0); updating = true; - if (path == String()) { //a dir + if (path == String() || item == tree->get_root()) { //a dir or root _update_subitems(item, item->is_checked(0), true); } @@ -76,6 +97,8 @@ void EditorAssetInstaller::_item_edited() { item->set_checked(0, true); item = item->get_parent(); } + } else { + _uncheck_parent(item->get_parent()); } updating = false; } diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h index b8c632bb5a..e31cff8845 100644 --- a/editor/editor_asset_installer.h +++ b/editor/editor_asset_installer.h @@ -42,6 +42,7 @@ class EditorAssetInstaller : public ConfirmationDialog { Map<String, TreeItem *> status_map; bool updating; void _update_subitems(TreeItem *p_item, bool p_check, bool p_first = false); + void _uncheck_parent(TreeItem *p_item); void _item_edited(); virtual void ok_pressed() override; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index fe68797483..f768a2cacf 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -456,8 +456,6 @@ void EditorNode::_notification(int p_what) { editor_selection->update(); - //scene_root->set_size_override(true, Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"))); - { //TODO should only happen on settings changed int current_filter = GLOBAL_GET("rendering/canvas_textures/default_texture_filter"); if (current_filter != scene_root->get_default_canvas_item_texture_filter()) { diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 13d8f0c856..c19140ae7c 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -1392,6 +1392,12 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { if (vderFunc) { vderFunc->set_function((VisualShaderNodeVectorDerivativeFunc::Function)p_op_idx); } + + VisualShaderNodeMultiplyAdd *fmaFunc = Object::cast_to<VisualShaderNodeMultiplyAdd>(vsn); + + if (fmaFunc) { + fmaFunc->set_type((VisualShaderNodeMultiplyAdd::Type)p_op_idx); + } } vsnode = Ref<VisualShaderNode>(vsn); @@ -2711,6 +2717,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Max", "Scalar", "Functions", "VisualShaderNodeFloatOp", TTR("Returns the greater of two values."), VisualShaderNodeFloatOp::OP_MAX, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("Min", "Scalar", "Functions", "VisualShaderNodeFloatOp", TTR("Returns the lesser of two values."), VisualShaderNodeFloatOp::OP_MIN, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("Mix", "Scalar", "Functions", "VisualShaderNodeScalarInterp", TTR("Linear interpolation between two scalars."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("MultiplyAdd", "Scalar", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on scalars."), VisualShaderNodeMultiplyAdd::TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("Negate", "Scalar", "Functions", "VisualShaderNodeFloatFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeFloatFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("Negate", "Scalar", "Functions", "VisualShaderNodeIntFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeIntFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_SCALAR_INT)); add_options.push_back(AddOption("OneMinus", "Scalar", "Functions", "VisualShaderNodeFloatFunc", TTR("1.0 - scalar"), VisualShaderNodeFloatFunc::FUNC_ONEMINUS, VisualShaderNode::PORT_TYPE_SCALAR)); @@ -2813,6 +2820,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), VisualShaderNodeVectorOp::OP_MIN, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeVectorInterp", TTR("Linear interpolation between two vectors."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeVectorScalarMix", TTR("Linear interpolation between two vectors using scalar."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("MultiplyAdd", "Vector", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), VisualShaderNodeMultiplyAdd::TYPE_VECTOR, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNode::PORT_TYPE_VECTOR)); diff --git a/methods.py b/methods.py index ca6756f95f..7b853b7821 100644 --- a/methods.py +++ b/methods.py @@ -217,14 +217,15 @@ void unregister_module_types() { def convert_custom_modules_path(path): if not path: return path + path = os.path.realpath(os.path.expanduser(os.path.expandvars(path))) err_msg = "Build option 'custom_modules' must %s" if not os.path.isdir(path): raise ValueError(err_msg % "point to an existing directory.") - if os.path.realpath(path) == os.path.realpath("modules"): + if path == os.path.realpath("modules"): raise ValueError(err_msg % "be a directory other than built-in `modules` directory.") if is_module(path): raise ValueError(err_msg % "point to a directory with modules, not a single module.") - return os.path.realpath(os.path.expanduser(path)) + return path def disable_module(self): diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 68e99445d8..992c86d632 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -32,6 +32,7 @@ #include "core/engine.h" #include "core/math/math_funcs.h" +#include "editor/editor_node.h" #include "scene/scene_string_names.h" #include "servers/rendering_server.h" @@ -56,7 +57,7 @@ void Camera2D::_update_scroll() { viewport->set_canvas_transform(xform); - Size2 screen_size = viewport->get_visible_rect().size; + Size2 screen_size = get_camera_screen_size(); Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2()); get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_camera_moved", xform, screen_offset); @@ -94,7 +95,7 @@ Transform2D Camera2D::get_camera_transform() { ERR_FAIL_COND_V(custom_viewport && !ObjectDB::get_instance(custom_viewport_id), Transform2D()); - Size2 screen_size = viewport->get_visible_rect().size; + Size2 screen_size = get_camera_screen_size(); Point2 new_camera_pos = get_global_transform().get_origin(); Point2 ret_camera_pos; @@ -274,7 +275,7 @@ void Camera2D::_notification(int p_what) { } Transform2D inv_camera_transform = get_camera_transform().affine_inverse(); - Size2 screen_size = get_viewport_rect().size; + Size2 screen_size = get_camera_screen_size(); Vector2 screen_endpoints[4] = { inv_camera_transform.xform(Vector2(0, 0)), @@ -321,7 +322,7 @@ void Camera2D::_notification(int p_what) { } Transform2D inv_camera_transform = get_camera_transform().affine_inverse(); - Size2 screen_size = get_viewport_rect().size; + Size2 screen_size = get_camera_screen_size(); Vector2 margin_endpoints[4] = { inv_camera_transform.xform(Vector2((screen_size.width / 2) - ((screen_size.width / 2) * drag_margin[MARGIN_LEFT]), (screen_size.height / 2) - ((screen_size.height / 2) * drag_margin[MARGIN_TOP]))), @@ -469,7 +470,7 @@ void Camera2D::reset_smoothing() { void Camera2D::align() { ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id)); - Size2 screen_size = viewport->get_visible_rect().size; + Size2 screen_size = get_camera_screen_size(); Point2 current_camera_pos = get_global_transform().get_origin(); if (anchor_mode == ANCHOR_MODE_DRAG_CENTER) { @@ -507,6 +508,14 @@ Point2 Camera2D::get_camera_screen_center() const { return camera_screen_center; } +Size2 Camera2D::get_camera_screen_size() const { + // special case if the camera2D is in the root viewport + if (Engine::get_singleton()->is_editor_hint() && get_viewport() == EditorNode::get_singleton()->get_scene_root()) { + return Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); + } + return get_viewport_rect().size; +} + void Camera2D::set_h_drag_enabled(bool p_enabled) { h_drag_enabled = p_enabled; } diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 0a4e269c40..4d34b51e97 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -147,6 +147,7 @@ public: Vector2 get_zoom() const; Point2 get_camera_screen_center() const; + Size2 get_camera_screen_size() const; void set_custom_viewport(Node *p_viewport); Node *get_custom_viewport() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 86ea0406e1..f40fb78056 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -562,6 +562,7 @@ void register_scene_types() { ClassDB::register_class<VisualShaderNodeGlobalExpression>(); ClassDB::register_class<VisualShaderNodeIs>(); ClassDB::register_class<VisualShaderNodeCompare>(); + ClassDB::register_class<VisualShaderNodeMultiplyAdd>(); ClassDB::register_class<ShaderMaterial>(); ClassDB::register_virtual_class<CanvasItem>(); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 5c6b13a527..88f5287831 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -4794,3 +4794,96 @@ VisualShaderNodeCompare::VisualShaderNodeCompare() { set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); } + +////////////// Fma + +String VisualShaderNodeMultiplyAdd::get_caption() const { + return "MultiplyAdd"; +} + +int VisualShaderNodeMultiplyAdd::get_input_port_count() const { + return 3; +} + +VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_input_port_type(int p_port) const { + if (type == TYPE_SCALAR) { + return PORT_TYPE_SCALAR; + } + return PORT_TYPE_VECTOR; +} + +String VisualShaderNodeMultiplyAdd::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 "c(+)"; + } + return ""; +} + +int VisualShaderNodeMultiplyAdd::get_output_port_count() const { + return 1; +} + +VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_output_port_type(int p_port) const { + if (type == TYPE_SCALAR) { + return PORT_TYPE_SCALAR; + } else { + return PORT_TYPE_VECTOR; + } +} + +String VisualShaderNodeMultiplyAdd::get_output_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeMultiplyAdd::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 "\t" + p_output_vars[0] + " = fma(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; +} + +void VisualShaderNodeMultiplyAdd::set_type(Type p_type) { + ERR_FAIL_INDEX((int)p_type, TYPE_MAX); + if (p_type != type) { + if (p_type == TYPE_SCALAR) { + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 0.0); + } else { + 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)); + } + } + type = p_type; + emit_changed(); +} + +VisualShaderNodeMultiplyAdd::Type VisualShaderNodeMultiplyAdd::get_type() const { + return type; +} + +Vector<StringName> VisualShaderNodeMultiplyAdd::get_editable_properties() const { + Vector<StringName> props; + props.push_back("type"); + return props; +} + +void VisualShaderNodeMultiplyAdd::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_type", "type"), &VisualShaderNodeMultiplyAdd::set_type); + ClassDB::bind_method(D_METHOD("get_type"), &VisualShaderNodeMultiplyAdd::get_type); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Scalar,Vector"), "set_type", "get_type"); + + BIND_ENUM_CONSTANT(TYPE_SCALAR); + BIND_ENUM_CONSTANT(TYPE_VECTOR); + BIND_ENUM_CONSTANT(TYPE_MAX); +} + +VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() { + type = TYPE_SCALAR; + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 0.0); +} diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index de6e196655..a7f252234d 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -1992,4 +1992,43 @@ VARIANT_ENUM_CAST(VisualShaderNodeCompare::ComparisonType) VARIANT_ENUM_CAST(VisualShaderNodeCompare::Function) VARIANT_ENUM_CAST(VisualShaderNodeCompare::Condition) +class VisualShaderNodeMultiplyAdd : public VisualShaderNode { + GDCLASS(VisualShaderNodeMultiplyAdd, VisualShaderNode); + +public: + enum Type { + TYPE_SCALAR, + TYPE_VECTOR, + TYPE_MAX, + }; + +protected: + Type type; + +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_type(Type p_type); + Type get_type() const; + + virtual Vector<StringName> get_editable_properties() const; + + VisualShaderNodeMultiplyAdd(); +}; + +VARIANT_ENUM_CAST(VisualShaderNodeMultiplyAdd::Type) + #endif // VISUAL_SHADER_NODES_H diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 99cc76b2e3..1f30048a51 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -2135,6 +2135,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { //array { "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY, true }, + // modern functions + + { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { nullptr, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false } }; |