diff options
93 files changed, 2903 insertions, 1124 deletions
diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index 2e941b8037..9c4fc4e1b7 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -247,6 +247,7 @@ StringName::StringName(const char *p_name, bool p_static) { _data->cname = nullptr; _data->next = _table[idx]; _data->prev = nullptr; + #ifdef DEBUG_ENABLED if (unlikely(debug_stringname)) { // Keep in memory, force static. diff --git a/core/string/string_name.h b/core/string/string_name.h index f4233854ac..ff4c41af94 100644 --- a/core/string/string_name.h +++ b/core/string/string_name.h @@ -35,6 +35,8 @@ #include "core/string/ustring.h" #include "core/templates/safe_refcount.h" +#define UNIQUE_NODE_PREFIX "%" + class Main; struct StaticCString { @@ -100,6 +102,17 @@ public: bool operator==(const String &p_name) const; bool operator==(const char *p_name) const; bool operator!=(const String &p_name) const; + + _FORCE_INLINE_ bool is_node_unique_name() const { + if (!_data) { + return false; + } + if (_data->cname != nullptr) { + return (char32_t)_data->cname[0] == (char32_t)UNIQUE_NODE_PREFIX[0]; + } else { + return (char32_t)_data->name[0] == (char32_t)UNIQUE_NODE_PREFIX[0]; + } + } _FORCE_INLINE_ bool operator<(const StringName &p_name) const { return _data < p_name._data; } diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 7cfd34b53e..7199121932 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -35,6 +35,7 @@ #include "core/math/math_funcs.h" #include "core/os/memory.h" #include "core/string/print_string.h" +#include "core/string/string_name.h" #include "core/string/translation.h" #include "core/string/ucaps.h" #include "core/variant/variant.h" @@ -4357,7 +4358,7 @@ String String::property_name_encode() const { } // Changes made to the set of invalid characters must also be reflected in the String documentation. -const String String::invalid_node_name_characters = ". : @ / \""; +const String String::invalid_node_name_characters = ". : @ / \" " UNIQUE_NODE_PREFIX; String String::validate_node_name() const { Vector<String> chars = String::invalid_node_name_characters.split(" "); diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index ae7b0afaa7..4b6f6eec67 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -63,6 +63,9 @@ <member name="albedo_tex_force_srgb" type="bool" setter="set_flag" getter="get_flag" default="false"> Forces a conversion of the [member albedo_texture] from sRGB space to linear space. </member> + <member name="albedo_tex_msdf" type="bool" setter="set_flag" getter="get_flag" default="false"> + Enables multichannel signed distance field rendering shader. Use [member msdf_pixel_range] and [member msdf_outline_size] to configure MSDF paramenters. + </member> <member name="albedo_texture" type="Texture2D" setter="set_texture" getter="get_texture"> Texture to multiply by [member albedo_color]. Used for basic texturing of objects. </member> @@ -243,6 +246,12 @@ <member name="metallic_texture_channel" type="int" setter="set_metallic_texture_channel" getter="get_metallic_texture_channel" enum="BaseMaterial3D.TextureChannel" default="0"> Specifies the channel of the [member metallic_texture] in which the metallic information is stored. This is useful when you store the information for multiple effects in a single texture. For example if you stored metallic in the red channel, roughness in the blue, and ambient occlusion in the green you could reduce the number of textures you use. </member> + <member name="msdf_outline_size" type="float" setter="set_msdf_outline_size" getter="get_msdf_outline_size" default="0.0"> + The width of the shape outine. + </member> + <member name="msdf_pixel_range" type="float" setter="set_msdf_pixel_range" getter="get_msdf_pixel_range" default="4.0"> + The width of the range around the shape between the minimum and maximum representable signed distance. + </member> <member name="no_depth_test" type="bool" setter="set_flag" getter="get_flag" default="false"> If [code]true[/code], depth testing is disabled and the object will be drawn in render order. </member> @@ -647,7 +656,10 @@ </constant> <constant name="FLAG_PARTICLE_TRAILS_MODE" value="19" enum="Flags"> </constant> - <constant name="FLAG_MAX" value="20" enum="Flags"> + <constant name="FLAG_ALBEDO_TEXTURE_MSDF" value="20" enum="Flags"> + Enables multichannel signed distance field rendering shader. + </constant> + <constant name="FLAG_MAX" value="21" enum="Flags"> Represents the size of the [enum Flags] enum. </constant> <constant name="DIFFUSE_BURLEY" value="0" enum="DiffuseMode"> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 78150af9dd..7e1bceb888 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -1358,27 +1358,5 @@ <constant name="TEXT_DIRECTION_RTL" value="2" enum="TextDirection"> Right-to-left text writing direction. </constant> - <constant name="STRUCTURED_TEXT_DEFAULT" value="0" enum="StructuredTextParser"> - Use default behavior. Same as [code]STRUCTURED_TEXT_NONE[/code] unless specified otherwise in the control description. - </constant> - <constant name="STRUCTURED_TEXT_URI" value="1" enum="StructuredTextParser"> - BiDi override for URI. - </constant> - <constant name="STRUCTURED_TEXT_FILE" value="2" enum="StructuredTextParser"> - BiDi override for file path. - </constant> - <constant name="STRUCTURED_TEXT_EMAIL" value="3" enum="StructuredTextParser"> - BiDi override for email. - </constant> - <constant name="STRUCTURED_TEXT_LIST" value="4" enum="StructuredTextParser"> - BiDi override for lists. - Structured text options: list separator [code]String[/code]. - </constant> - <constant name="STRUCTURED_TEXT_NONE" value="5" enum="StructuredTextParser"> - Use default Unicode BiDi algorithm. - </constant> - <constant name="STRUCTURED_TEXT_CUSTOM" value="6" enum="StructuredTextParser"> - User defined structured text BiDi override function. - </constant> </constants> </class> diff --git a/doc/classes/FontData.xml b/doc/classes/FontData.xml index 313e3e31fc..a423d7a4e4 100644 --- a/doc/classes/FontData.xml +++ b/doc/classes/FontData.xml @@ -582,6 +582,9 @@ <member name="force_autohinter" type="bool" setter="set_force_autohinter" getter="is_force_autohinter" default="false"> If set to [code]true[/code], auto-hinting is supported and preferred over font built-in hinting. Used by dynamic fonts only. </member> + <member name="generate_mipmaps" type="bool" setter="set_generate_mipmaps" getter="get_generate_mipmaps" default="false"> + If set to [code]true[/code], generate mipmaps for the font textures. + </member> <member name="hinting" type="int" setter="set_hinting" getter="get_hinting" enum="TextServer.Hinting" default="1"> Font hinting mode. Used by dynamic fonts only. </member> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index b1046dea6b..d5744bbc42 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -85,7 +85,7 @@ [b]Note:[/b] Setting this property updates [member visible_characters] based on current [method get_total_character_count]. </member> <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="4" /> - <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0"> + <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. </member> <member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]"> diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml new file mode 100644 index 0000000000..c95b691bf3 --- /dev/null +++ b/doc/classes/Label3D.xml @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="Label3D" inherits="GeometryInstance3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Displays plain text in a 3D world. + </brief_description> + <description> + Label3D displays plain text in a 3D world. It gives you control over the horizontal and vertical alignment. + </description> + <tutorials> + </tutorials> + <methods> + <method name="clear_opentype_features"> + <return type="void" /> + <description> + Removes all OpenType features. + </description> + </method> + <method name="generate_triangle_mesh" qualifiers="const"> + <return type="TriangleMesh" /> + <description> + Returns a [TriangleMesh] with the label's vertices following its current configuration (such as its [member pixel_size]). + </description> + </method> + <method name="get_draw_flag" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="flag" type="int" enum="Label3D.DrawFlags" /> + <description> + Returns the value of the specified flag. + </description> + </method> + <method name="get_opentype_feature" qualifiers="const"> + <return type="int" /> + <argument index="0" name="tag" type="String" /> + <description> + Returns OpenType feature [code]tag[/code]. + </description> + </method> + <method name="set_draw_flag"> + <return type="void" /> + <argument index="0" name="flag" type="int" enum="Label3D.DrawFlags" /> + <argument index="1" name="enabled" type="bool" /> + <description> + If [code]true[/code], the specified flag will be enabled. See [enum Label3D.DrawFlags] for a list of flags. + </description> + </method> + <method name="set_opentype_feature"> + <return type="void" /> + <argument index="0" name="tag" type="String" /> + <argument index="1" name="value" type="int" /> + <description> + Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url]. + </description> + </method> + </methods> + <members> + <member name="alpha_cut" type="int" setter="set_alpha_cut_mode" getter="get_alpha_cut_mode" enum="Label3D.AlphaCutMode" default="0"> + The alpha cutting mode to use for the sprite. See [enum AlphaCutMode] for possible values. + </member> + <member name="alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold" default="0.5"> + Threshold at which the alpha scissor will discard values. + </member> + <member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="Label3D.AutowrapMode" default="0"> + If set to something other than [constant AUTOWRAP_OFF], the text gets wrapped inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. To see how each mode behaves, see [enum AutowrapMode]. + </member> + <member name="billboard" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="BaseMaterial3D.BillboardMode" default="0"> + The billboard mode to use for the label. See [enum BaseMaterial3D.BillboardMode] for possible values. + </member> + <member name="double_sided" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true"> + If [code]true[/code], text can be seen from the back as well, if [code]false[/code], it is invisible when looking at it from behind. + </member> + <member name="fixed_size" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false"> + If [code]true[/code], the label is rendered at the same size regardless of distance. + </member> + <member name="font" type="Font" setter="set_font" getter="get_font"> + [Font] used for the [Label3D]'s text. + </member> + <member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16"> + Font size of the [Label3D]'s text. + </member> + <member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="1"> + Controls the text's horizontal alignment. Supports left, center, right. Set it to one of the [enum HorizontalAlignment] constants. + </member> + <member name="language" type="String" setter="set_language" getter="get_language" default=""""> + Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. + </member> + <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0"> + Vertical space between lines in multiline [Label3D]. + </member> + <member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)"> + Text [Color] of the [Label3D]. + </member> + <member name="no_depth_test" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false"> + If [code]true[/code], depth testing is disabled and the object will be drawn in render order. + </member> + <member name="outline_modulate" type="Color" setter="set_outline_modulate" getter="get_outline_modulate" default="Color(0, 0, 0, 1)"> + The tint of [Font]'s outline. + </member> + <member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0"> + Text outline size. + </member> + <member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01"> + The size of one pixel's width on the label to scale it in 3D. + </member> + <member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false"> + If [code]true[/code], the [Light3D] in the [Environment] has effects on the label. + </member> + <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> + Set BiDi algorithm override for the structured text. + </member> + <member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]"> + Set additional options for BiDi override. + </member> + <member name="text" type="String" setter="set_text" getter="get_text" default=""""> + The text to display on screen. + </member> + <member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" enum="TextServer.Direction" default="0"> + Base text writing direction. + </member> + <member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="BaseMaterial3D.TextureFilter" default="3"> + Filter flags for the texture. See [enum BaseMaterial3D.TextureFilter] for options. + </member> + <member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase" default="false"> + If [code]true[/code], all the text displays as UPPERCASE. + </member> + <member name="vertical_alignment" type="int" setter="set_vertical_alignment" getter="get_vertical_alignment" enum="VerticalAlignment" default="1"> + Controls the text's vertical alignment. Supports top, center, bottom. Set it to one of the [enum VerticalAlignment] constants. + </member> + <member name="width" type="float" setter="set_width" getter="get_width" default="500.0"> + Text width (in pixels), used for autowrap and fill alignment. + </member> + </members> + <constants> + <constant name="AUTOWRAP_OFF" value="0" enum="AutowrapMode"> + Autowrap is disabled. + </constant> + <constant name="AUTOWRAP_ARBITRARY" value="1" enum="AutowrapMode"> + Wraps the text inside the node's bounding rectangle by allowing to break lines at arbitrary positions, which is useful when very limited space is available. + </constant> + <constant name="AUTOWRAP_WORD" value="2" enum="AutowrapMode"> + Wraps the text inside the node's bounding rectangle by soft-breaking between words. + </constant> + <constant name="AUTOWRAP_WORD_SMART" value="3" enum="AutowrapMode"> + Behaves similarly to [constant AUTOWRAP_WORD], but force-breaks a word if that single word does not fit in one line. + </constant> + <constant name="FLAG_SHADED" value="0" enum="DrawFlags"> + If set, lights in the environment affect the label. + </constant> + <constant name="FLAG_DOUBLE_SIDED" value="1" enum="DrawFlags"> + If set, text can be seen from the back as well. If not, the texture is invisible when looking at it from behind. + </constant> + <constant name="FLAG_DISABLE_DEPTH_TEST" value="2" enum="DrawFlags"> + Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it. + </constant> + <constant name="FLAG_FIXED_SIZE" value="3" enum="DrawFlags"> + Label is scaled by depth so that it always appears the same size on screen. + </constant> + <constant name="FLAG_MAX" value="4" enum="DrawFlags"> + Represents the size of the [enum DrawFlags] enum. + </constant> + <constant name="ALPHA_CUT_DISABLED" value="0" enum="AlphaCutMode"> + This mode performs standard alpha blending. It can display translucent areas, but transparency sorting issues may be visible when multiple transparent materials are overlapping. + </constant> + <constant name="ALPHA_CUT_DISCARD" value="1" enum="AlphaCutMode"> + This mode only allows fully transparent or fully opaque pixels. Harsh edges will be visible unless some form of screen-space antialiasing is enabled (see [member ProjectSettings.rendering/anti_aliasing/quality/screen_space_aa]). This mode is also known as [i]alpha testing[/i] or [i]1-bit transparency[/i]. + [b]Note:[/b] This mode might have issues with anti-aliased fonts and outlines, try adjusting [member alpha_scissor_threshold] or using MSDF font. + [b]Note:[/b] When using text with overlapping glyphs (e.g., cursive scripts), this mode might have transparency sorting issues between the main text and the outline. + </constant> + <constant name="ALPHA_CUT_OPAQUE_PREPASS" value="2" enum="AlphaCutMode"> + This mode draws fully opaque pixels in the depth prepass. This is slower than [constant ALPHA_CUT_DISABLED] or [constant ALPHA_CUT_DISCARD], but it allows displaying translucent areas and smooth edges while using proper sorting. + [b]Note:[/b] When using text with overlapping glyphs (e.g., cursive scripts), this mode might have transparency sorting issues between the main text and the outline. + </constant> + </constants> +</class> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 136147b4b0..55e012ee0c 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -251,7 +251,7 @@ <member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true"> If [code]false[/code], using shortcuts will be disabled. </member> - <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0"> + <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. </member> <member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]"> diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml index 3b03d86644..ba80504caf 100644 --- a/doc/classes/LinkButton.xml +++ b/doc/classes/LinkButton.xml @@ -36,7 +36,7 @@ <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. </member> - <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0"> + <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. </member> <member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]"> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 7079036879..3efa49b309 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -492,6 +492,12 @@ Returns [code]true[/code] if the node is processing unhandled key input (see [method set_process_unhandled_key_input]). </description> </method> + <method name="is_unique_name_in_owner" qualifiers="const"> + <return type="bool" /> + <description> + Returns whether the node is an unique name for all the other nodes owned by its [member owner]. + </description> + </method> <method name="move_child"> <return type="void" /> <argument index="0" name="child_node" type="Node" /> @@ -719,6 +725,13 @@ Sets whether this is an instance load placeholder. See [InstancePlaceholder]. </description> </method> + <method name="set_unique_name_in_owner"> + <return type="void" /> + <argument index="0" name="enable" type="bool" /> + <description> + Sets this node's name as the unique name in its [member owner]. This allows the node to be accessed as [code]%Name[/code] instead of the full path, from any node within that scene. + </description> + </method> <method name="update_configuration_warnings"> <return type="void" /> <description> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 02b67a4a5b..828117a847 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -342,7 +342,7 @@ <argument index="0" name="alignment" type="int" enum="HorizontalAlignment" /> <argument index="1" name="base_direction" type="int" enum="Control.TextDirection" default="0" /> <argument index="2" name="language" type="String" default="""" /> - <argument index="3" name="st_parser" type="int" enum="Control.StructuredTextParser" default="0" /> + <argument index="3" name="st_parser" type="int" enum="TextServer.StructuredTextParser" default="0" /> <description> Adds a [code][p][/code] tag to the tag stack. </description> @@ -488,7 +488,7 @@ <member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true"> If [code]true[/code], shortcut keys for context menu items are enabled, even if the context menu is disabled. </member> - <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0"> + <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. </member> <member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]"> diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml index 405fff0ce8..9733fa3a26 100644 --- a/doc/classes/SpriteBase3D.xml +++ b/doc/classes/SpriteBase3D.xml @@ -53,6 +53,9 @@ <member name="double_sided" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true"> If [code]true[/code], texture can be seen from the back as well, if [code]false[/code], it is invisible when looking at it from behind. </member> + <member name="fixed_size" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false"> + If [code]true[/code], the label is rendered at the same size regardless of distance. + </member> <member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h" default="false"> If [code]true[/code], texture is flipped horizontally. </member> @@ -63,6 +66,9 @@ A color value used to [i]multiply[/i] the texture's colors. Can be used for mood-coloring or to simulate the color of light. [b]Note:[/b] If a [member GeometryInstance3D.material_override] is defined on the [SpriteBase3D], the material override must be configured to take vertex colors into account for albedo. Otherwise, the color defined in [member modulate] will be ignored. For a [BaseMaterial3D], [member BaseMaterial3D.vertex_color_use_as_albedo] must be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function. </member> + <member name="no_depth_test" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false"> + If [code]true[/code], depth testing is disabled and the object will be drawn in render order. + </member> <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)"> The texture's drawing offset. </member> @@ -72,6 +78,9 @@ <member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false"> If [code]true[/code], the [Light3D] in the [Environment] has effects on the sprite. </member> + <member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="BaseMaterial3D.TextureFilter" default="3"> + Filter flags for the texture. See [enum BaseMaterial3D.TextureFilter] for options. + </member> <member name="transparent" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true"> If [code]true[/code], the texture's transparency and the opacity are used to make those parts of the sprite invisible. </member> @@ -86,7 +95,13 @@ <constant name="FLAG_DOUBLE_SIDED" value="2" enum="DrawFlags"> If set, texture can be seen from the back as well. If not, the texture is invisible when looking at it from behind. </constant> - <constant name="FLAG_MAX" value="3" enum="DrawFlags"> + <constant name="FLAG_DISABLE_DEPTH_TEST" value="3" enum="DrawFlags"> + Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it. + </constant> + <constant name="FLAG_FIXED_SIZE" value="4" enum="DrawFlags"> + Label is scaled by depth so that it always appears the same size on screen. + </constant> + <constant name="FLAG_MAX" value="5" enum="DrawFlags"> Represents the size of the [enum DrawFlags] enum. </constant> <constant name="ALPHA_CUT_DISABLED" value="0" enum="AlphaCutMode"> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index a4edaa79c7..58fdd2d058 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -1017,7 +1017,7 @@ <member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true"> If [code]true[/code], shortcut keys for context menu items are enabled, even if the context menu is disabled. </member> - <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0"> + <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. </member> <member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]"> diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 9ef800d7e1..dba4bd24a5 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -80,6 +80,7 @@ <description> Draws single glyph into a canvas item at the position, using [code]font_rid[/code] at the size [code]size[/code]. [b]Note:[/b] Glyph index is specific to the font, use glyphs indices returned by [method shaped_text_get_glyphs] or [method font_get_glyph_index]. + [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update. </description> </method> <method name="font_draw_glyph_outline" qualifiers="const"> @@ -94,6 +95,7 @@ <description> Draws single glyph outline of size [code]outline_size[/code] into a canvas item at the position, using [code]font_rid[/code] at the size [code]size[/code]. [b]Note:[/b] Glyph index is specific to the font, use glyphs indices returned by [method shaped_text_get_glyphs] or [method font_get_glyph_index]. + [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update. </description> </method> <method name="font_get_ascent" qualifiers="const"> @@ -126,6 +128,13 @@ Returns bitmap font fixed size. </description> </method> + <method name="font_get_generate_mipmaps" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns [code]true[/code] if font texture mipmap generation is enabled. + </description> + </method> <method name="font_get_global_oversampling" qualifiers="const"> <return type="float" /> <description> @@ -199,6 +208,26 @@ Returns index of the cache texture containing the glyph. </description> </method> + <method name="font_get_glyph_texture_rid" qualifiers="const"> + <return type="RID" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="size" type="Vector2i" /> + <argument index="2" name="glyph" type="int" /> + <description> + Returns resource id of the cache texture containing the glyph. + [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update. + </description> + </method> + <method name="font_get_glyph_texture_size" qualifiers="const"> + <return type="Vector2" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="size" type="Vector2i" /> + <argument index="2" name="glyph" type="int" /> + <description> + Returns size of the cache texture containing the glyph. + [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update. + </description> + </method> <method name="font_get_glyph_uv_rect" qualifiers="const"> <return type="Rect2" /> <argument index="0" name="font_rid" type="RID" /> @@ -580,6 +609,14 @@ If set to [code]true[/code] auto-hinting is preferred over font built-in hinting. </description> </method> + <method name="font_set_generate_mipmaps"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="generate_mipmaps" type="bool" /> + <description> + If set to [code]true[/code] font texture mipmap generation is enabled. + </description> + </method> <method name="font_set_global_oversampling"> <return type="void" /> <argument index="0" name="oversampling" type="float" /> @@ -927,6 +964,15 @@ Converts a number from the numeral systems used in [code]language[/code] to Western Arabic (0..9). </description> </method> + <method name="parse_structured_text" qualifiers="const"> + <return type="Array" /> + <argument index="0" name="parser_type" type="int" enum="TextServer.StructuredTextParser" /> + <argument index="1" name="args" type="Array" /> + <argument index="2" name="text" type="String" /> + <description> + Default implementation of the BiDi algorithm override function. See [enum StructuredTextParser] for more info. + </description> + </method> <method name="percent_sign" qualifiers="const"> <return type="String" /> <argument index="0" name="language" type="String" default="""" /> @@ -1630,5 +1676,27 @@ <constant name="FONT_FIXED_WIDTH" value="4" enum="FontStyle"> Font have fixed-width characters. </constant> + <constant name="STRUCTURED_TEXT_DEFAULT" value="0" enum="StructuredTextParser"> + Use default behavior. Same as [code]STRUCTURED_TEXT_NONE[/code] unless specified otherwise in the control description. + </constant> + <constant name="STRUCTURED_TEXT_URI" value="1" enum="StructuredTextParser"> + BiDi override for URI. + </constant> + <constant name="STRUCTURED_TEXT_FILE" value="2" enum="StructuredTextParser"> + BiDi override for file path. + </constant> + <constant name="STRUCTURED_TEXT_EMAIL" value="3" enum="StructuredTextParser"> + BiDi override for email. + </constant> + <constant name="STRUCTURED_TEXT_LIST" value="4" enum="StructuredTextParser"> + BiDi override for lists. + Structured text options: list separator [code]String[/code]. + </constant> + <constant name="STRUCTURED_TEXT_NONE" value="5" enum="StructuredTextParser"> + Use default Unicode BiDi algorithm. + </constant> + <constant name="STRUCTURED_TEXT_CUSTOM" value="6" enum="StructuredTextParser"> + User defined structured text BiDi override function. + </constant> </constants> </class> diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index e7c5edd266..ef522d08a7 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -121,6 +121,13 @@ Returns bitmap font fixed size. </description> </method> + <method name="font_get_generate_mipmaps" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="font_rid" type="RID" /> + <description> + Returns [code]true[/code] if font texture mipmap generation is enabled. + </description> + </method> <method name="font_get_global_oversampling" qualifiers="virtual const"> <return type="float" /> <description> @@ -193,6 +200,24 @@ Returns index of the cache texture containing the glyph. </description> </method> + <method name="font_get_glyph_texture_rid" qualifiers="virtual const"> + <return type="RID" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="size" type="Vector2i" /> + <argument index="2" name="glyph" type="int" /> + <description> + Returns resource id of the cache texture containing the glyph. + </description> + </method> + <method name="font_get_glyph_texture_size" qualifiers="virtual const"> + <return type="Vector2" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="size" type="Vector2i" /> + <argument index="2" name="glyph" type="int" /> + <description> + Returns size of the cache texture containing the glyph. + </description> + </method> <method name="font_get_glyph_uv_rect" qualifiers="virtual const"> <return type="Rect2" /> <argument index="0" name="font_rid" type="RID" /> @@ -581,6 +606,14 @@ If set to [code]true[/code] auto-hinting is preferred over font built-in hinting. </description> </method> + <method name="font_set_generate_mipmaps" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="font_rid" type="RID" /> + <argument index="1" name="generate_mipmaps" type="bool" /> + <description> + If set to [code]true[/code] font texture mipmap generation is enabled. + </description> + </method> <method name="font_set_global_oversampling" qualifiers="virtual"> <return type="void" /> <argument index="0" name="oversampling" type="float" /> @@ -927,6 +960,14 @@ Converts a number from the numeral systems used in [code]language[/code] to Western Arabic (0..9). </description> </method> + <method name="parse_structured_text" qualifiers="virtual const"> + <return type="Array" /> + <argument index="0" name="parser_type" type="int" enum="TextServer.StructuredTextParser" /> + <argument index="1" name="args" type="Array" /> + <argument index="2" name="text" type="String" /> + <description> + </description> + </method> <method name="percent_sign" qualifiers="virtual const"> <return type="String" /> <argument index="0" name="language" type="String" /> diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index 396be2d9f8..d2e29bf3b1 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -284,7 +284,7 @@ </description> </method> <method name="get_structured_text_bidi_override" qualifiers="const"> - <return type="int" enum="Control.StructuredTextParser" /> + <return type="int" enum="TextServer.StructuredTextParser" /> <argument index="0" name="column" type="int" /> <description> </description> @@ -620,7 +620,7 @@ <method name="set_structured_text_bidi_override"> <return type="void" /> <argument index="0" name="column" type="int" /> - <argument index="1" name="parser" type="int" enum="Control.StructuredTextParser" /> + <argument index="1" name="parser" type="int" enum="TextServer.StructuredTextParser" /> <description> </description> </method> diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 8812447f6e..f7db1d950c 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -478,10 +478,6 @@ float msdf_median(float r, float g, float b, float a) { return min(max(min(r, g), min(max(r, g), b)), a); } -vec2 msdf_map(vec2 value, vec2 in_min, vec2 in_max, vec2 out_min, vec2 out_max) { - return out_min + (out_max - out_min) * (value - in_min) / (in_max - in_min); -} - void main() { vec4 color = color_interp; vec2 uv = uv_interp; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index abfbde6e86..0a2922fbd6 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -105,7 +105,7 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind /* SHADER API */ -void MaterialStorage::_shader_make_dirty(Shader *p_shader) { +void MaterialStorage::_shader_make_dirty(GLES3::Shader *p_shader) { if (p_shader->dirty_list.in_list()) { return; } @@ -114,7 +114,7 @@ void MaterialStorage::_shader_make_dirty(Shader *p_shader) { } RID MaterialStorage::shader_allocate() { - Shader *shader = memnew(Shader); + GLES3::Shader *shader = memnew(GLES3::Shader); shader->mode = RS::SHADER_CANVAS_ITEM; //shader->shader = &scene->state.scene_shader; RID rid = shader_owner.make_rid(shader); @@ -129,7 +129,7 @@ void MaterialStorage::shader_initialize(RID p_rid) { } //RID MaterialStorage::shader_create() { -// Shader *shader = memnew(Shader); +// GLES3::Shader *shader = memnew(GLES3::Shader); // shader->mode = RS::SHADER_SPATIAL; // shader->shader = &scene->state.scene_shader; // RID rid = shader_owner.make_rid(shader); @@ -140,7 +140,7 @@ void MaterialStorage::shader_initialize(RID p_rid) { //} void MaterialStorage::shader_free(RID p_rid) { - Shader *shader = shader_owner.get_or_null(p_rid); + GLES3::Shader *shader = shader_owner.get_or_null(p_rid); if (shader->shader && shader->version.is_valid()) { shader->shader->version_free(shader->version); @@ -151,7 +151,7 @@ void MaterialStorage::shader_free(RID p_rid) { } while (shader->materials.first()) { - Material *m = shader->materials.first()->self(); + GLES3::Material *m = shader->materials.first()->self(); m->shader = nullptr; _material_make_dirty(m); @@ -164,7 +164,7 @@ void MaterialStorage::shader_free(RID p_rid) { } void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { - Shader *shader = shader_owner.get_or_null(p_shader); + GLES3::Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); shader->code = p_code; @@ -211,14 +211,14 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } String MaterialStorage::shader_get_code(RID p_shader) const { - const Shader *shader = shader_owner.get_or_null(p_shader); + const GLES3::Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, ""); return shader->code; } void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - Shader *shader = shader_owner.get_or_null(p_shader); + GLES3::Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); if (shader->dirty_list.in_list()) { @@ -359,7 +359,7 @@ void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_ } void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { - Shader *shader = shader_owner.get_or_null(p_shader); + GLES3::Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); ERR_FAIL_COND(p_texture.is_valid() && !TextureStorage::get_singleton()->owns_texture(p_texture)); @@ -382,7 +382,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin } RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { - const Shader *shader = shader_owner.get_or_null(p_shader); + const GLES3::Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, RID()); if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) { @@ -392,7 +392,7 @@ RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const String return RID(); } -void MaterialStorage::_update_shader(Shader *p_shader) const { +void MaterialStorage::_update_shader(GLES3::Shader *p_shader) const { _shader_dirty_list.remove(&p_shader->dirty_list); p_shader->valid = false; @@ -408,8 +408,8 @@ void MaterialStorage::_update_shader(Shader *p_shader) const { switch (p_shader->mode) { case RS::SHADER_CANVAS_ITEM: { - p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL; - p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX; + p_shader->canvas_item.light_mode = GLES3::Shader::CanvasItem::LIGHT_MODE_NORMAL; + p_shader->canvas_item.blend_mode = GLES3::Shader::CanvasItem::BLEND_MODE_MIX; p_shader->canvas_item.uses_screen_texture = false; p_shader->canvas_item.uses_screen_uv = false; @@ -423,14 +423,14 @@ void MaterialStorage::_update_shader(Shader *p_shader) const { p_shader->canvas_item.uses_projection_matrix = false; p_shader->canvas_item.uses_instance_custom = false; - shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD); - shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX); - shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB); - shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL); - shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA); + shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_ADD); + shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_MIX); + shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_SUB); + shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_MUL); + shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA); - shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED); - shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); + shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, GLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED); + shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, GLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv; shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv; @@ -453,9 +453,9 @@ void MaterialStorage::_update_shader(Shader *p_shader) const { case RS::SHADER_SPATIAL: { // TODO remove once 3D is added back return; - p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX; - p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE; - p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK; + p_shader->spatial.blend_mode = GLES3::Shader::Spatial::BLEND_MODE_MIX; + p_shader->spatial.depth_draw_mode = GLES3::Shader::Spatial::DEPTH_DRAW_OPAQUE; + p_shader->spatial.cull_mode = GLES3::Shader::Spatial::CULL_MODE_BACK; p_shader->spatial.uses_alpha = false; p_shader->spatial.uses_alpha_scissor = false; p_shader->spatial.uses_discard = false; @@ -472,19 +472,19 @@ void MaterialStorage::_update_shader(Shader *p_shader) const { p_shader->spatial.writes_modelview_or_projection = false; p_shader->spatial.uses_world_coordinates = false; - shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD); - shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX); - shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_SUB); - shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MUL); + shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, GLES3::Shader::Spatial::BLEND_MODE_ADD); + shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, GLES3::Shader::Spatial::BLEND_MODE_MIX); + shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, GLES3::Shader::Spatial::BLEND_MODE_SUB); + shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, GLES3::Shader::Spatial::BLEND_MODE_MUL); - shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_OPAQUE); - shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALWAYS); - shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_NEVER); - shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS); + shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, GLES3::Shader::Spatial::DEPTH_DRAW_OPAQUE); + shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, GLES3::Shader::Spatial::DEPTH_DRAW_ALWAYS); + shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, GLES3::Shader::Spatial::DEPTH_DRAW_NEVER); + shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, GLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS); - shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_FRONT); - shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_BACK); - shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_DISABLED); + shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, GLES3::Shader::Spatial::CULL_MODE_FRONT); + shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, GLES3::Shader::Spatial::CULL_MODE_BACK); + shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, GLES3::Shader::Spatial::CULL_MODE_DISABLED); shaders.actions_scene.render_mode_flags["unshaded"] = &p_shader->spatial.unshaded; shaders.actions_scene.render_mode_flags["depth_test_disable"] = &p_shader->spatial.no_depth_test; @@ -539,7 +539,7 @@ void MaterialStorage::_update_shader(Shader *p_shader) const { p_shader->uses_vertex_time = gen_code.uses_vertex_time; p_shader->uses_fragment_time = gen_code.uses_fragment_time; - for (SelfList<Material> *E = p_shader->materials.first(); E; E = E->next()) { + for (SelfList<GLES3::Material> *E = p_shader->materials.first(); E; E = E->next()) { _material_make_dirty(E->self()); } @@ -554,7 +554,7 @@ void MaterialStorage::update_dirty_shaders() { /* MATERIAL API */ -void MaterialStorage::_material_make_dirty(Material *p_material) const { +void MaterialStorage::_material_make_dirty(GLES3::Material *p_material) const { if (p_material->dirty_list.in_list()) { return; } @@ -562,7 +562,7 @@ void MaterialStorage::_material_make_dirty(Material *p_material) const { _material_dirty_list.add(&p_material->dirty_list); } -void MaterialStorage::_update_material(Material *p_material) { +void MaterialStorage::_update_material(GLES3::Material *p_material) { if (p_material->dirty_list.in_list()) { _material_dirty_list.remove(&p_material->dirty_list); } @@ -580,7 +580,8 @@ void MaterialStorage::_update_material(Material *p_material) { bool can_cast_shadow = false; bool is_animated = false; - if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX && + if (p_material->shader->spatial.blend_mode == GLES3::Shader::Spatial::BLEND_MODE_MIX && + (!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) { can_cast_shadow = true; } @@ -645,7 +646,7 @@ void MaterialStorage::_update_material(Material *p_material) { } RID MaterialStorage::material_allocate() { - Material *material = memnew(Material); + GLES3::Material *material = memnew(GLES3::Material); return material_owner.make_rid(material); } @@ -659,7 +660,7 @@ void MaterialStorage::material_initialize(RID p_rid) { //} void MaterialStorage::material_free(RID p_rid) { - Material *m = material_owner.get_or_null(p_rid); + GLES3::Material *m = material_owner.get_or_null(p_rid); if (m->shader) { m->shader->materials.remove(&m->list); @@ -691,10 +692,10 @@ void MaterialStorage::material_free(RID p_rid) { } void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); - Shader *shader = get_shader(p_shader); + GLES3::Shader *shader = get_shader(p_shader); if (material->shader) { // if a shader is present, remove the old shader @@ -711,7 +712,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { } void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); if (p_value.get_type() == Variant::NIL) { @@ -724,7 +725,7 @@ void MaterialStorage::material_set_param(RID p_material, const StringName &p_par } Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const { - const Material *material = material_owner.get_or_null(p_material); + const GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND_V(!material, RID()); if (material->params.has(p_param)) { @@ -735,7 +736,7 @@ Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_ } void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); material->next_pass = p_next_material; @@ -745,14 +746,14 @@ void MaterialStorage::material_set_render_priority(RID p_material, int priority) ERR_FAIL_COND(priority < RS::MATERIAL_RENDER_PRIORITY_MIN); ERR_FAIL_COND(priority > RS::MATERIAL_RENDER_PRIORITY_MAX); - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); material->render_priority = priority; } bool MaterialStorage::material_is_animated(RID p_material) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND_V(!material, false); if (material->dirty_list.in_list()) { _update_material(material); @@ -766,7 +767,7 @@ bool MaterialStorage::material_is_animated(RID p_material) { } bool MaterialStorage::material_casts_shadows(RID p_material) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND_V(!material, false); if (material->dirty_list.in_list()) { _update_material(material); @@ -782,7 +783,7 @@ bool MaterialStorage::material_casts_shadows(RID p_material) { } Variant MaterialStorage::material_get_param_default(RID p_material, const StringName &p_param) const { - const Material *material = material_owner.get_or_null(p_material); + const GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND_V(!material, Variant()); if (material->shader) { @@ -797,14 +798,14 @@ Variant MaterialStorage::material_get_param_default(RID p_material, const String void MaterialStorage::update_dirty_materials() { while (_material_dirty_list.first()) { - Material *material = _material_dirty_list.first()->self(); + GLES3::Material *material = _material_dirty_list.first()->self(); _update_material(material); } } /* are these still used? */ RID MaterialStorage::material_get_shader(RID p_material) const { - const Material *material = material_owner.get_or_null(p_material); + const GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND_V(!material, RID()); if (material->shader) { @@ -815,14 +816,14 @@ RID MaterialStorage::material_get_shader(RID p_material) const { } void MaterialStorage::material_set_line_width(RID p_material, float p_width) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); material->line_width = p_width; } bool MaterialStorage::material_uses_tangents(RID p_material) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND_V(!material, false); if (!material->shader) { @@ -837,7 +838,7 @@ bool MaterialStorage::material_uses_tangents(RID p_material) { } bool MaterialStorage::material_uses_ensure_correct_normals(RID p_material) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND_V(!material, false); if (!material->shader) { @@ -853,7 +854,7 @@ bool MaterialStorage::material_uses_ensure_correct_normals(RID p_material) { void MaterialStorage::material_add_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance) { /* - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance); @@ -867,7 +868,7 @@ void MaterialStorage::material_add_instance_owner(RID p_material, RendererStorag void MaterialStorage::material_remove_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance) { /* - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance); @@ -883,7 +884,7 @@ void MaterialStorage::material_remove_instance_owner(RID p_material, RendererSto /* void MaterialStorage::_material_add_geometry(RID p_material, Geometry *p_geometry) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry); @@ -896,7 +897,7 @@ void MaterialStorage::_material_add_geometry(RID p_material, Geometry *p_geometr } void MaterialStorage::_material_remove_geometry(RID p_material, Geometry *p_geometry) { - Material *material = material_owner.get_or_null(p_material); + GLES3::Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry); diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index dca69ffd5f..0ed0e9bcd7 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -1631,7 +1631,7 @@ EditorFileDialog::EditorFileDialog() { pathhb->add_child(drives_container); dir = memnew(LineEdit); - dir->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + dir->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); pathhb->add_child(dir); dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -1782,7 +1782,7 @@ EditorFileDialog::EditorFileDialog() { file_box->add_child(l); file = memnew(LineEdit); - file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + file->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); file->set_stretch_ratio(4); file->set_h_size_flags(Control::SIZE_EXPAND_FILL); file_box->add_child(file); @@ -1826,7 +1826,7 @@ EditorFileDialog::EditorFileDialog() { makedialog->add_child(makevb); makedirname = memnew(LineEdit); - makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + makedirname->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); makevb->add_margin_child(TTR("Name:"), makedirname); add_child(makedialog); makedialog->register_text_enter(makedirname); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index d2b8883b8a..4a3d195a69 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -485,7 +485,7 @@ EditorPropertyPath::EditorPropertyPath() { HBoxContainer *path_hb = memnew(HBoxContainer); add_child(path_hb); path = memnew(LineEdit); - path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); path_hb->add_child(path); path->connect("text_submitted", callable_mp(this, &EditorPropertyPath::_path_selected)); path->connect("focus_exited", callable_mp(this, &EditorPropertyPath::_path_focus_exited)); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index f4082746d8..17f9ed114d 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -489,6 +489,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("axis_x_color", "Editor", Color(0.96, 0.20, 0.32)); theme->set_color("axis_y_color", "Editor", Color(0.53, 0.84, 0.01)); theme->set_color("axis_z_color", "Editor", Color(0.16, 0.55, 0.96)); + theme->set_color("axis_w_color", "Editor", Color(0.55, 0.55, 0.55)); const float prop_color_saturation = accent_color.get_s() * 0.75; const float prop_color_value = accent_color.get_v(); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 778c5c33ff..33c6ce9622 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -73,7 +73,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory } subdirectory_item->set_text(0, dname); - subdirectory_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE); + subdirectory_item->set_structured_text_bidi_override(0, TextServer::STRUCTURED_TEXT_FILE); subdirectory_item->set_icon(0, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); subdirectory_item->set_icon_modulate(0, get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"))); subdirectory_item->set_selectable(0, true); @@ -143,7 +143,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory for (const FileInfo &fi : file_list) { TreeItem *file_item = tree->create_item(subdirectory_item); file_item->set_text(0, fi.name); - file_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE); + file_item->set_structured_text_bidi_override(0, TextServer::STRUCTURED_TEXT_FILE); file_item->set_icon(0, _get_tree_item_icon(!fi.import_broken, fi.type)); String file_metadata = lpath.plus_file(fi.name); file_item->set_metadata(0, file_metadata); @@ -3026,7 +3026,7 @@ FileSystemDock::FileSystemDock() { toolbar_hbc->add_child(button_hist_next); current_path = memnew(LineEdit); - current_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + current_path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); current_path->set_h_size_flags(SIZE_EXPAND_FILL); _set_current_path_text(path); toolbar_hbc->add_child(current_path); diff --git a/editor/icons/Label3D.svg b/editor/icons/Label3D.svg new file mode 100644 index 0000000000..76e1b7c276 --- /dev/null +++ b/editor/icons/Label3D.svg @@ -0,0 +1 @@ +<svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io"><path d="M6 3a1 1 0 0 0-.707.293l-4 4a1 1 0 0 0 0 1.414l4 4A1 1 0 0 0 6 13h8a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H6ZM5 7a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z" fill="#fc7f7f" fill-rule="evenodd" vectornator:layerName="Untitled"/></svg> diff --git a/editor/icons/SceneUniqueName.svg b/editor/icons/SceneUniqueName.svg new file mode 100644 index 0000000000..34279a14a6 --- /dev/null +++ b/editor/icons/SceneUniqueName.svg @@ -0,0 +1 @@ +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M4.378 2.224q1.235 0 2.084.866.865.85.865 2.083 0 1.17-.881 2.036-.866.85-2.068.85-1.218 0-2.083-.85-.866-.866-.866-2.068t.866-2.051q.865-.866 2.083-.866zm.962 1.988q-.4-.4-.962-.4-.56 0-.961.4-.401.384-.401.93 0 .56.4.961.401.385.962.385.561 0 .962-.385.4-.4.4-.946 0-.56-.4-.945zm5.45-2.116h1.218L5.677 13.78H4.442Zm1.17 5.722q1.234 0 2.083.866.866.849.866 2.1 0 1.17-.882 2.035-.865.85-2.068.85-1.218 0-2.083-.85-.866-.866-.866-2.084 0-1.202.866-2.051.865-.866 2.083-.866zm.961 1.987q-.4-.4-.962-.4-.56 0-.961.4-.4.385-.4.946 0 .561.4.962.4.384.961.384.561 0 .962-.384.4-.4.4-.946 0-.56-.4-.962z" aria-label="%" style="font-weight:600;font-size:16.0277px;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';letter-spacing:0;word-spacing:0;fill:#e0e0e0;fill-opacity:.996078;stroke-width:.400692"/></svg> diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 20349e8ccb..b72530f1e8 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -458,6 +458,10 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper if (font_preview->get_data_count() > 0) { font_preview->get_data(0)->set_antialiased(import_settings_data->get("antialiased")); } + } else if (p_edited_property == "generate_mipmaps") { + if (font_preview->get_data_count() > 0) { + font_preview->get_data(0)->set_generate_mipmaps(import_settings_data->get("generate_mipmaps")); + } } else if (p_edited_property == "multichannel_signed_distance_field") { if (font_preview->get_data_count() > 0) { font_preview->get_data(0)->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field")); @@ -926,6 +930,7 @@ void DynamicFontImportSettings::_re_import() { Map<StringName, Variant> main_settings; main_settings["antialiased"] = import_settings_data->get("antialiased"); + main_settings["generate_mipmaps"] = import_settings_data->get("generate_mipmaps"); main_settings["multichannel_signed_distance_field"] = import_settings_data->get("multichannel_signed_distance_field"); main_settings["msdf_pixel_range"] = import_settings_data->get("msdf_pixel_range"); main_settings["msdf_size"] = import_settings_data->get("msdf_size"); @@ -1340,6 +1345,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { singleton = this; options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); + options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_RANGE, "1,250,1"), 48)); diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index a7f6d09aed..2dc24c9d44 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -102,6 +102,7 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List< bool msdf = p_preset == PRESET_MSDF; r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), (msdf) ? true : false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_RANGE, "1,250,1"), 48)); @@ -179,6 +180,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str print_verbose("Importing dynamic font from: " + p_source_file); bool antialiased = p_options["antialiased"]; + bool generate_mipmaps = p_options["generate_mipmaps"]; bool msdf = p_options["multichannel_signed_distance_field"]; int px_range = p_options["msdf_pixel_range"]; int px_size = p_options["msdf_size"]; @@ -199,6 +201,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str font.instantiate(); font->set_data(data); font->set_antialiased(antialiased); + font->set_generate_mipmaps(generate_mipmaps); font->set_multichannel_signed_distance_field(msdf); font->set_msdf_pixel_range(px_range); font->set_msdf_size(px_size); diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index 1338cf03a8..2b67a171cc 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -96,6 +96,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin Ref<FontData> font; font.instantiate(); font->set_antialiased(false); + font->set_generate_mipmaps(false); font->set_multichannel_signed_distance_field(false); font->set_fixed_size(base_size); font->set_subpixel_positioning(TextServer::SUBPIXEL_POSITIONING_DISABLED); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 51e2f6ff00..179f78325c 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -47,6 +47,7 @@ #include "scene/3d/gpu_particles_3d.h" #include "scene/3d/gpu_particles_collision_3d.h" #include "scene/3d/joint_3d.h" +#include "scene/3d/label_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/lightmap_gi.h" #include "scene/3d/lightmap_probe.h" @@ -2170,6 +2171,38 @@ void Sprite3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { /// +Label3DGizmoPlugin::Label3DGizmoPlugin() { +} + +bool Label3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<Label3D>(p_spatial) != nullptr; +} + +String Label3DGizmoPlugin::get_gizmo_name() const { + return "Label3D"; +} + +int Label3DGizmoPlugin::get_priority() const { + return -1; +} + +bool Label3DGizmoPlugin::can_be_hidden() const { + return false; +} + +void Label3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + Label3D *label = Object::cast_to<Label3D>(p_gizmo->get_spatial_node()); + + p_gizmo->clear(); + + Ref<TriangleMesh> tm = label->generate_triangle_mesh(); + if (tm.is_valid()) { + p_gizmo->add_collision_triangles(tm); + } +} + +/// + Position3DGizmoPlugin::Position3DGizmoPlugin() { pos3d_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); cursor_points = Vector<Vector3>(); diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h index 3b67b898e3..8adb753a51 100644 --- a/editor/plugins/node_3d_editor_gizmos.h +++ b/editor/plugins/node_3d_editor_gizmos.h @@ -321,6 +321,19 @@ public: Sprite3DGizmoPlugin(); }; +class Label3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(Label3DGizmoPlugin, EditorNode3DGizmoPlugin); + +public: + bool has_gizmo(Node3D *p_spatial) override; + String get_gizmo_name() const override; + int get_priority() const override; + bool can_be_hidden() const override; + void redraw(EditorNode3DGizmo *p_gizmo) override; + + Label3DGizmoPlugin(); +}; + class Position3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(Position3DGizmoPlugin, EditorNode3DGizmoPlugin); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index f2ca1fcfeb..6eed85e370 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -7278,6 +7278,7 @@ void Node3DEditor::_register_all_gizmos() { add_gizmo_plugin(Ref<OccluderInstance3DGizmoPlugin>(memnew(OccluderInstance3DGizmoPlugin))); add_gizmo_plugin(Ref<SoftDynamicBody3DGizmoPlugin>(memnew(SoftDynamicBody3DGizmoPlugin))); add_gizmo_plugin(Ref<Sprite3DGizmoPlugin>(memnew(Sprite3DGizmoPlugin))); + add_gizmo_plugin(Ref<Label3DGizmoPlugin>(memnew(Label3DGizmoPlugin))); add_gizmo_plugin(Ref<Position3DGizmoPlugin>(memnew(Position3DGizmoPlugin))); add_gizmo_plugin(Ref<RayCast3DGizmoPlugin>(memnew(RayCast3DGizmoPlugin))); add_gizmo_plugin(Ref<SpringArm3DGizmoPlugin>(memnew(SpringArm3DGizmoPlugin))); diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp index 936eb747b0..ffa74173be 100644 --- a/editor/plugins/ot_features_plugin.cpp +++ b/editor/plugins/ot_features_plugin.cpp @@ -30,6 +30,8 @@ #include "ot_features_plugin.h" +#include "scene/3d/label_3d.h" + void OpenTypeFeaturesEditor::_value_changed(double val) { if (setting) { return; @@ -116,7 +118,25 @@ void OpenTypeFeaturesAdd::setup(Object *p_object) { bool have_ss = false; bool have_cv = false; bool have_cu = false; - Dictionary features = Object::cast_to<Control>(edited_object)->get_theme_font(SNAME("font"))->get_feature_list(); + + Ref<Font> font; + + Control *ctrl = Object::cast_to<Control>(edited_object); + if (ctrl != nullptr) { + font = ctrl->get_theme_font(SNAME("font")); + } else { + Label3D *l3d = Object::cast_to<Label3D>(edited_object); + if (l3d != nullptr) { + font = l3d->_get_font_or_default(); + } + } + + if (font.is_null()) { + return; + } + + Dictionary features = font->get_feature_list(); + for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) { String ftr_name = TS->tag_to_name(*ftr); if (ftr_name.begins_with("stylistic_set_")) { @@ -185,7 +205,7 @@ OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() { /*************************************************************************/ bool EditorInspectorPluginOpenTypeFeatures::can_handle(Object *p_object) { - return (Object::cast_to<Control>(p_object) != nullptr); + return (Object::cast_to<Control>(p_object) != nullptr) || (Object::cast_to<Label3D>(p_object) != nullptr); } bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index e6829660cb..c4a5ec7a87 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -923,6 +923,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { port_left = vsnode->get_input_port_type(i + 3); } node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]); + port_offset++; valid_left = (i + 4) < vsnode->get_input_port_count(); port_left = VisualShaderNode::PORT_TYPE_SCALAR; @@ -4027,7 +4028,10 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input, return; } - bool type_changed = p_input->get_input_type_by_name(p_name) != p_input->get_input_type_by_name(prev_name); + VisualShaderNode::PortType next_input_type = p_input->get_input_type_by_name(p_name); + VisualShaderNode::PortType prev_input_type = p_input->get_input_type_by_name(prev_name); + + bool type_changed = next_input_type != prev_input_type; UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); undo_redo->create_action(TTR("Visual Shader Input Type Changed")); @@ -4035,31 +4039,54 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input, undo_redo->add_do_method(p_input.ptr(), "set_input_name", p_name); undo_redo->add_undo_method(p_input.ptr(), "set_input_name", prev_name); - // update output port - for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) { - VisualShader::Type type = VisualShader::Type(type_id); - int id = visual_shader->find_node_id(type, p_input); - if (id != VisualShader::NODE_ID_INVALID) { - if (type_changed) { + if (type_changed) { + for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) { + VisualShader::Type type = VisualShader::Type(type_id); + + int id = visual_shader->find_node_id(type, p_input); + if (id != VisualShader::NODE_ID_INVALID) { + bool is_expanded = p_input->is_output_port_expandable(0) && p_input->_is_output_port_expanded(0); + + int type_size = 0; + if (is_expanded) { + switch (next_input_type) { + case VisualShaderNode::PORT_TYPE_VECTOR_2D: { + type_size = 2; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR_3D: { + type_size = 3; + } break; + case VisualShaderNode::PORT_TYPE_VECTOR_4D: { + type_size = 4; + } break; + default: + break; + } + } + List<VisualShader::Connection> conns; visual_shader->get_node_connections(type, &conns); for (const VisualShader::Connection &E : conns) { - if (E.from_node == id) { - if (visual_shader->is_port_types_compatible(p_input->get_input_type_by_name(p_name), visual_shader->get_node(type, E.to_node)->get_input_port_type(E.to_port))) { - undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); - undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); - continue; + int from_node = E.from_node; + int from_port = E.from_port; + int to_node = E.to_node; + int to_port = E.to_port; + + if (from_node == id) { + bool is_incompatible_types = !visual_shader->is_port_types_compatible(p_input->get_input_type_by_name(p_name), visual_shader->get_node(type, to_node)->get_input_port_type(to_port)); + + if (is_incompatible_types || from_port > type_size) { + undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port); } - undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); - undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); - undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); - undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port); } } + + undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, id); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id); } - undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, id); - undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id); - break; } } @@ -5068,8 +5095,7 @@ VisualShaderEditor::VisualShaderEditor() { // CANVASITEM-FOR-ALL - add_options.push_back(AddOption("Alpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha", "COLOR.a"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR.rgb"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("TexturePixelSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "texture_pixel_size", "TEXTURE_PIXEL_SIZE"), { "texture_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv", "UV"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_CANVAS_ITEM)); @@ -5077,11 +5103,9 @@ VisualShaderEditor::VisualShaderEditor() { // PARTICLES-FOR-ALL add_options.push_back(AddOption("Active", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active", "ACTIVE"), { "active" }, VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Alpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha", "COLOR.a"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("AttractorForce", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "attractor_force", "ATTRACTOR_FORCE"), { "attractor_force" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR.rgb"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Custom", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom", "CUSTOM.rgb"), { "custom" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("CustomAlpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha", "CUSTOM.a"), { "custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Custom", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom", "CUSTOM"), { "custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("Delta", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta", "DELTA"), { "delta" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("EmissionTransform", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform", "EMISSION_TRANSFORM"), { "emission_transform" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("Index", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index", "INDEX"), { "index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, -1, Shader::MODE_PARTICLES)); @@ -5111,12 +5135,10 @@ VisualShaderEditor::VisualShaderEditor() { // NODE3D INPUTS - add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha", "COLOR.a"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Binormal", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR.rgb"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("InstanceId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM.rgb"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("InstanceCustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom_alpha", "INSTANCE_CUSTOM.a"), { "instance_custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ModelViewMatrix", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "modelview_matrix", "MODELVIEW_MATRIX"), { "modelview_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size", "POINT_SIZE"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); @@ -5126,11 +5148,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha", "COLOR.a"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR.rgb"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("DepthTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "depth_texture", "DEPTH_TEXTURE"), { "depth_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD.xyz"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("FrontFacing", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing", "FRONT_FACING"), { "front_facing" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture", "SCREEN_TEXTURE"), { "screen_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); @@ -5146,7 +5167,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation", "ATTENUATION"), { "attenuation" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Backlight", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "backlight", "BACKLIGHT"), { "backlight" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Diffuse", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "diffuse", "DIFFUSE_LIGHT"), { "diffuse" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD.xyz"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Metallic", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "metallic", "METALLIC"), { "metallic" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); @@ -5158,8 +5179,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("AtLightPass", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass", "AT_LIGHT_PASS"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("CanvasMatrix", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "canvas_matrix", "CANVAS_MATRIX"), { "canvas_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM.rgb"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("InstanceCustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom_alpha", "INSTANCE_CUSTOM.a"), { "instance_custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("InstanceId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ModelMatrix", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "model_matrix", "MODEL_MATRIX"), { "model_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size", "POINT_SIZE"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); @@ -5168,32 +5188,27 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("VertexId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex_id", "VERTEX_ID"), { "vertex_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("AtLightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass", "AT_LIGHT_PASS"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD.xyz"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("NormalTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture", "NORMAL_TEXTURE"), { "normal_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size", "SCREEN_PIXEL_SIZE"), { "screen_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture", "SCREEN_TEXTURE"), { "screen_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("SpecularShininess", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS.rgb"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("SpecularShininessAlpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess_alpha", "SPECULAR_SHININESS.a"), { "specular_shininess_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("SpecularShininess", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("SpecularShininessTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE"), { "specular_shininess_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Texture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture", "TEXTURE"), { "texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD.xyz"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT.rgb"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_alpha", "LIGHT.a"), { "light_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR.rgb"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightColorAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color_alpha", "LIGHT_COLOR.a"), { "light_color_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("LightPosition", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_position", "LIGHT_POSITION"), { "light_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("LightVertex", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "light_vertex", "LIGHT_VERTEX"), { "light_vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Normal", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "normal", "NORMAL"), { "normal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Shadow", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow", "SHADOW_MODULATE.rgb"), { "shadow" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ShadowAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_alpha", "SHADOW_MODULATE.a"), { "shadow_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("SpecularShininess", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS.rgb"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("SpecularShininessAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess_alpha", "SPECULAR_SHININESS.a"), { "specular_shininess_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Shadow", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow", "SHADOW_MODULATE"), { "shadow" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("SpecularShininess", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Texture", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture", "TEXTURE"), { "texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); // SKY INPUTS @@ -5202,8 +5217,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("AtHalfResPass", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_half_res_pass", "AT_HALF_RES_PASS"), { "at_half_res_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("AtQuarterResPass", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_quarter_res_pass", "AT_QUARTER_RES_PASS"), { "at_quarter_res_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("EyeDir", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "eyedir", "EYEDIR"), { "eyedir" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); - add_options.push_back(AddOption("HalfResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "half_res_color", "HALF_RES_COLOR.rgb"), { "half_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); - add_options.push_back(AddOption("HalfResAlpha", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "half_res_alpha", "HALF_RES_COLOR.a"), { "half_res_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY)); + add_options.push_back(AddOption("HalfResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "half_res_color", "HALF_RES_COLOR"), { "half_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("Light0Color", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_color", "LIGHT0_COLOR"), { "light0_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("Light0Direction", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_direction", "LIGHT0_DIRECTION"), { "light0_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("Light0Enabled", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_enabled", "LIGHT0_ENABLED"), { "light0_enabled" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY)); @@ -5221,8 +5235,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Light3Enabled", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light3_enabled", "LIGHT3_ENABLED"), { "light3_enabled" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("Light3Energy", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light3_energy", "LIGHT3_ENERGY"), { "light3_energy" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("Position", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "position", "POSITION"), { "position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); - add_options.push_back(AddOption("QuarterResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_color", "QUARTER_RES_COLOR.rgb"), { "quarter_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); - add_options.push_back(AddOption("QuarterResAlpha", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_alpha", "QUARTER_RES_COLOR.a"), { "quarter_res_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY)); + add_options.push_back(AddOption("QuarterResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_color", "QUARTER_RES_COLOR"), { "quarter_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("Radiance", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "radiance", "RADIANCE"), { "radiance" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("ScreenUV", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); add_options.push_back(AddOption("SkyCoords", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "sky_coords", "SKY_COORDS"), { "sky_coords" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY)); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 4ca0f18f0e..81df7ee30a 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -802,7 +802,7 @@ public: project_path = memnew(LineEdit); project_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); - project_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + project_path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); pphb->add_child(project_path); install_path_container = memnew(VBoxContainer); @@ -817,7 +817,7 @@ public: install_path = memnew(LineEdit); install_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); - install_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + install_path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); iphb->add_child(install_path); // status icon @@ -1440,7 +1440,7 @@ void ProjectList::create_project_item_control(int p_index) { } Label *fpath = memnew(Label(item.path)); - fpath->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + fpath->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); path_hb->add_child(fpath); fpath->set_h_size_flags(Control::SIZE_EXPAND_FILL); fpath->set_modulate(Color(1, 1, 1, 0.5)); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 03f65cdf52..c63471720b 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1061,6 +1061,28 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } } } break; + case TOOL_TOGGLE_SCENE_UNIQUE_NAME: { + List<Node *> selection = editor_selection->get_selected_node_list(); + List<Node *>::Element *e = selection.front(); + if (e) { + UndoRedo *undo_redo = &editor_data->get_undo_redo(); + Node *node = e->get(); + bool enabled = node->is_unique_name_in_owner(); + if (!enabled && get_tree()->get_edited_scene_root()->get_node_or_null(UNIQUE_NODE_PREFIX + String(node->get_name())) != nullptr) { + accept->set_text(TTR("Another node already uses this unique name in the scene.")); + accept->popup_centered(); + return; + } + if (!enabled) { + undo_redo->create_action(TTR("Enable Scene Unique Name")); + } else { + undo_redo->create_action(TTR("Disable Scene Unique Name")); + } + undo_redo->add_do_method(node, "set_unique_name_in_owner", !enabled); + undo_redo->add_undo_method(node, "set_unique_name_in_owner", enabled); + undo_redo->commit_action(); + } + } break; case TOOL_CREATE_2D_SCENE: case TOOL_CREATE_3D_SCENE: case TOOL_CREATE_USER_INTERFACE: @@ -1309,8 +1331,17 @@ void SceneTreeDock::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root UndoRedo *undo_redo = &editor_data->get_undo_redo(); switch (p_mode) { case MODE_BIDI: { + bool is_unique = p_node->is_unique_name_in_owner() && p_base->get_node_or_null(UNIQUE_NODE_PREFIX + String(p_node->get_name())) != nullptr; + if (is_unique) { + // Will create a unique name conflict. Disable before setting owner. + undo_redo->add_do_method(p_node, "set_unique_name_in_owner", false); + } undo_redo->add_do_method(p_node, "set_owner", p_root); undo_redo->add_undo_method(p_node, "set_owner", p_base); + if (is_unique) { + // Will create a unique name conflict. Enable after setting owner. + undo_redo->add_undo_method(p_node, "set_unique_name_in_owner", true); + } } break; case MODE_DO: { @@ -2774,11 +2805,19 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->add_separator(); menu->add_icon_shortcut(get_theme_icon(SNAME("CreateNewSceneFrom"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM); } + if (full_selection.size() == 1) { menu->add_separator(); menu->add_icon_shortcut(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH); } + if (selection[0]->get_owner() == EditorNode::get_singleton()->get_edited_scene()) { + // Only for nodes owned by the edited scene root. + menu->add_separator(); + menu->add_icon_check_item(get_theme_icon(SNAME("SceneUniqueName"), SNAME("EditorIcons")), TTR("Access as Scene Unique Name"), TOOL_TOGGLE_SCENE_UNIQUE_NAME); + menu->set_item_checked(menu->get_item_index(TOOL_TOGGLE_SCENE_UNIQUE_NAME), selection[0]->is_unique_name_in_owner()); + } + bool is_external = (!selection[0]->get_scene_file_path().is_empty()); if (is_external) { bool is_inherited = selection[0]->get_scene_inherited_state() != nullptr; diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 599fb01203..842995dfe3 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -91,7 +91,7 @@ class SceneTreeDock : public VBoxContainer { TOOL_SCENE_CLEAR_INHERITANCE, TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM, TOOL_SCENE_OPEN_INHERITED, - + TOOL_TOGGLE_SCENE_UNIQUE_NAME, TOOL_CREATE_2D_SCENE, TOOL_CREATE_3D_SCENE, TOOL_CREATE_USER_INTERFACE, diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 44eb5c670d..aa48395152 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -148,6 +148,13 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i TabContainer *tab_container = Object::cast_to<TabContainer>(NodeDock::get_singleton()->get_parent()); NodeDock::get_singleton()->get_parent()->call("set_current_tab", tab_container->get_tab_idx_from_control(NodeDock::get_singleton())); NodeDock::get_singleton()->show_groups(); + } else if (p_id == BUTTON_UNIQUE) { + undo_redo->create_action(TTR("Disable Scene Unique Name")); + undo_redo->add_do_method(n, "set_unique_name_in_owner", false); + undo_redo->add_undo_method(n, "set_unique_name_in_owner", true); + undo_redo->add_do_method(this, "_update_tree"); + undo_redo->add_undo_method(this, "_update_tree"); + undo_redo->commit_action(); } } @@ -260,6 +267,10 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll item->add_button(0, get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning); } + if (p_node->is_unique_name_in_owner()) { + item->add_button(0, get_theme_icon(SNAME("SceneUniqueName"), SNAME("EditorIcons")), BUTTON_UNIQUE, false, vformat(TTR("This node can be accessed from within anywhere in the scene by preceding it with the '%s' prefix in a node path.\nClick to disable this."), UNIQUE_NODE_PREFIX)); + } + int num_connections = p_node->get_persistent_signal_connection_count(); int num_groups = p_node->get_persistent_group_count(); @@ -832,6 +843,13 @@ void SceneTreeEditor::_renamed() { // Trim leading/trailing whitespace to prevent node names from containing accidental whitespace, which would make it more difficult to get the node via `get_node()`. new_name = new_name.strip_edges(); + if (n->is_unique_name_in_owner() && get_tree()->get_edited_scene_root()->get_node_or_null("%" + new_name) != nullptr) { + error->set_text(TTR("Another node already uses this unique name in the scene.")); + error->popup_centered(); + which->set_text(0, n->get_name()); + return; + } + if (!undo_redo) { n->set_name(new_name); which->set_metadata(0, n->get_path()); diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index 547a5b57ca..3d88081ab1 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -53,6 +53,7 @@ class SceneTreeEditor : public Control { BUTTON_SIGNALS = 6, BUTTON_GROUPS = 7, BUTTON_PIN = 8, + BUTTON_UNIQUE = 9, }; Tree *tree = nullptr; diff --git a/misc/scripts/clang_format.sh b/misc/scripts/clang_format.sh index 5ab9c1bbb9..6d19044d96 100755 --- a/misc/scripts/clang_format.sh +++ b/misc/scripts/clang_format.sh @@ -17,8 +17,6 @@ while read -r f; do continue elif [[ "$f" == *"glsl" ]]; then continue - elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/input/InputManager"* ]]; then - continue elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView"* ]]; then continue elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/gl/EGLLogWrapper"* ]]; then diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 4cd5dada4d..0ae8219e23 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -994,8 +994,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( int w = (bounds.r - bounds.l); int h = (bounds.t - bounds.b); - int mw = w + p_rect_margin * 2; - int mh = h + p_rect_margin * 2; + int mw = w + p_rect_margin * 4; + int mh = h + p_rect_margin * 4; ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, FontGlyph()); @@ -1029,7 +1029,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { - int ofs = ((i + tex_pos.y + p_rect_margin) * tex.texture_w + j + tex_pos.x + p_rect_margin) * 4; + int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * 4; ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), FontGlyph()); wr[ofs + 0] = (uint8_t)(CLAMP(image(j, i)[0] * 256.f, 0.f, 255.f)); wr[ofs + 1] = (uint8_t)(CLAMP(image(j, i)[1] * 256.f, 0.f, 255.f)); @@ -1049,8 +1049,9 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( chr.texture_idx = tex_pos.index; - chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h); - chr.rect.position = Vector2(bounds.l, -bounds.t); + chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2); + chr.rect.position = Vector2(bounds.l - p_rect_margin, -bounds.t - p_rect_margin); + chr.rect.size = chr.uv_rect.size; } return chr; @@ -1062,8 +1063,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma int w = bitmap.width; int h = bitmap.rows; - int mw = w + p_rect_margin * 2; - int mh = h + p_rect_margin * 2; + int mw = w + p_rect_margin * 4; + int mh = h + p_rect_margin * 4; ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, FontGlyph()); @@ -1083,7 +1084,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { - int ofs = ((i + tex_pos.y + p_rect_margin) * tex.texture_w + j + tex_pos.x + p_rect_margin) * color_size; + int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * color_size; ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), FontGlyph()); switch (bitmap.pixel_mode) { case FT_PIXEL_MODE_MONO: { @@ -1124,8 +1125,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma chr.texture_idx = tex_pos.index; chr.found = true; - chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h); - chr.rect.position = Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling; + chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2); + chr.rect.position = Vector2(xofs - p_rect_margin, -yofs - p_rect_margin) * p_data->scale / p_data->oversampling; chr.rect.size = chr.uv_rect.size * p_data->scale / p_data->oversampling; return chr; } @@ -1796,6 +1797,29 @@ bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const { return fd->antialiased; } +void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + if (fd->mipmaps != p_generate_mipmaps) { + for (KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) { + for (int i = 0; i < E.value->textures.size(); i++) { + E.value->textures.write[i].dirty = true; + } + } + fd->mipmaps = p_generate_mipmaps; + } +} + +bool TextServerAdvanced::font_get_generate_mipmaps(const RID &p_font_rid) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, false); + + MutexLock lock(fd->mutex); + return fd->mipmaps; +} + void TextServerAdvanced::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) { FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); @@ -2276,6 +2300,9 @@ void TextServerAdvanced::font_set_texture_image(const RID &p_font_rid, const Vec Ref<Image> img; img.instantiate(); img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } tex.texture = Ref<ImageTexture>(); tex.texture.instantiate(); @@ -2559,6 +2586,86 @@ void TextServerAdvanced::font_set_glyph_texture_idx(const RID &p_font_rid, const gl[p_glyph].found = true; } +RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, RID()); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size_outline(fd, p_size); + + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID()); + if (!_ensure_glyph(fd, size, p_glyph)) { + return RID(); // Invalid or non graphicl glyph, do not display errors. + } + + const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; + ERR_FAIL_COND_V(gl[p_glyph].texture_idx < -1 || gl[p_glyph].texture_idx >= fd->cache[size]->textures.size(), RID()); + + if (RenderingServer::get_singleton() != nullptr) { + if (gl[p_glyph].texture_idx != -1) { + if (fd->cache[size]->textures[gl[p_glyph].texture_idx].dirty) { + FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph].texture_idx]; + Ref<Image> img; + img.instantiate(); + img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } + if (tex.texture.is_null()) { + tex.texture.instantiate(); + tex.texture->create_from_image(img); + } else { + tex.texture->update(img); + } + tex.dirty = false; + } + return fd->cache[size]->textures[gl[p_glyph].texture_idx].texture->get_rid(); + } + } + + return RID(); +} + +Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, Size2()); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size_outline(fd, p_size); + + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2()); + if (!_ensure_glyph(fd, size, p_glyph)) { + return Size2(); // Invalid or non graphicl glyph, do not display errors. + } + + const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; + ERR_FAIL_COND_V(gl[p_glyph].texture_idx < -1 || gl[p_glyph].texture_idx >= fd->cache[size]->textures.size(), Size2()); + + if (RenderingServer::get_singleton() != nullptr) { + if (gl[p_glyph].texture_idx != -1) { + if (fd->cache[size]->textures[gl[p_glyph].texture_idx].dirty) { + FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph].texture_idx]; + Ref<Image> img; + img.instantiate(); + img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } + if (tex.texture.is_null()) { + tex.texture.instantiate(); + tex.texture->create_from_image(img); + } else { + tex.texture->update(img); + } + tex.dirty = false; + } + return fd->cache[size]->textures[gl[p_glyph].texture_idx].texture->get_size(); + } + } + + return Size2(); +} + Dictionary TextServerAdvanced::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const { FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); @@ -2865,6 +2972,9 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can Ref<Image> img; img.instantiate(); img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } if (tex.texture.is_null()) { tex.texture.instantiate(); tex.texture->create_from_image(img); @@ -2941,6 +3051,9 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI Ref<Image> img; img.instantiate(); img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } if (tex.texture.is_null()) { tex.texture.instantiate(); tex.texture->create_from_image(img); @@ -3304,7 +3417,9 @@ void TextServerAdvanced::shaped_text_set_bidi_override(const RID &p_shaped, cons } sd->bidi_override.clear(); for (int i = 0; i < p_override.size(); i++) { - sd->bidi_override.push_back(p_override[i]); + if (p_override[i].get_type() == Variant::VECTOR2I) { + sd->bidi_override.push_back(p_override[i]); + } } invalidate(sd, false); } diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 8afba6adca..fa59566a94 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -216,6 +216,7 @@ class TextServerAdvanced : public TextServerExtension { Mutex mutex; bool antialiased = true; + bool mipmaps = false; bool msdf = false; int msdf_range = 14; int msdf_source_size = 48; @@ -483,6 +484,9 @@ public: virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; virtual bool font_is_antialiased(const RID &p_font_rid) const override; + virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; + virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; + virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override; virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override; @@ -567,6 +571,9 @@ public: virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) override; + virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override; virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const override; diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 47c6a73b24..1251aaf2b9 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -438,8 +438,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( int w = (bounds.r - bounds.l); int h = (bounds.t - bounds.b); - int mw = w + p_rect_margin * 2; - int mh = h + p_rect_margin * 2; + int mw = w + p_rect_margin * 4; + int mh = h + p_rect_margin * 4; ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, FontGlyph()); @@ -473,7 +473,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { - int ofs = ((i + tex_pos.y + p_rect_margin) * tex.texture_w + j + tex_pos.x + p_rect_margin) * 4; + int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * 4; ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), FontGlyph()); wr[ofs + 0] = (uint8_t)(CLAMP(image(j, i)[0] * 256.f, 0.f, 255.f)); wr[ofs + 1] = (uint8_t)(CLAMP(image(j, i)[1] * 256.f, 0.f, 255.f)); @@ -493,8 +493,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( chr.texture_idx = tex_pos.index; - chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h); - chr.rect.position = Vector2(bounds.l, -bounds.t); + chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2); + chr.rect.position = Vector2(bounds.l - p_rect_margin, -bounds.t - p_rect_margin); chr.rect.size = chr.uv_rect.size; } return chr; @@ -506,8 +506,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma int w = bitmap.width; int h = bitmap.rows; - int mw = w + p_rect_margin * 2; - int mh = h + p_rect_margin * 2; + int mw = w + p_rect_margin * 4; + int mh = h + p_rect_margin * 4; ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, FontGlyph()); @@ -527,7 +527,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { - int ofs = ((i + tex_pos.y + p_rect_margin) * tex.texture_w + j + tex_pos.x + p_rect_margin) * color_size; + int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * color_size; ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), FontGlyph()); switch (bitmap.pixel_mode) { case FT_PIXEL_MODE_MONO: { @@ -568,8 +568,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma chr.texture_idx = tex_pos.index; chr.found = true; - chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h); - chr.rect.position = Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling; + chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2); + chr.rect.position = Vector2(xofs - p_rect_margin, -yofs - p_rect_margin) * p_data->scale / p_data->oversampling; chr.rect.size = chr.uv_rect.size * p_data->scale / p_data->oversampling; return chr; } @@ -959,6 +959,29 @@ bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const { return fd->antialiased; } +void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND(!fd); + + MutexLock lock(fd->mutex); + if (fd->mipmaps != p_generate_mipmaps) { + for (KeyValue<Vector2i, FontDataForSizeFallback *> &E : fd->cache) { + for (int i = 0; i < E.value->textures.size(); i++) { + E.value->textures.write[i].dirty = true; + } + } + fd->mipmaps = p_generate_mipmaps; + } +} + +bool TextServerFallback::font_get_generate_mipmaps(const RID &p_font_rid) const { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, false); + + MutexLock lock(fd->mutex); + return fd->mipmaps; +} + void TextServerFallback::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) { FontDataFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); @@ -1439,6 +1462,9 @@ void TextServerFallback::font_set_texture_image(const RID &p_font_rid, const Vec Ref<Image> img; img.instantiate(); img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } tex.texture = Ref<ImageTexture>(); tex.texture.instantiate(); @@ -1708,6 +1734,86 @@ void TextServerFallback::font_set_glyph_texture_idx(const RID &p_font_rid, const gl[p_glyph].found = true; } +RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, RID()); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size_outline(fd, p_size); + + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID()); + if (!_ensure_glyph(fd, size, p_glyph)) { + return RID(); // Invalid or non graphicl glyph, do not display errors. + } + + const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; + ERR_FAIL_COND_V(gl[p_glyph].texture_idx < -1 || gl[p_glyph].texture_idx >= fd->cache[size]->textures.size(), RID()); + + if (RenderingServer::get_singleton() != nullptr) { + if (gl[p_glyph].texture_idx != -1) { + if (fd->cache[size]->textures[gl[p_glyph].texture_idx].dirty) { + FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph].texture_idx]; + Ref<Image> img; + img.instantiate(); + img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } + if (tex.texture.is_null()) { + tex.texture.instantiate(); + tex.texture->create_from_image(img); + } else { + tex.texture->update(img); + } + tex.dirty = false; + } + return fd->cache[size]->textures[gl[p_glyph].texture_idx].texture->get_rid(); + } + } + + return RID(); +} + +Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { + FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, Size2()); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size_outline(fd, p_size); + + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2()); + if (!_ensure_glyph(fd, size, p_glyph)) { + return Size2(); // Invalid or non graphicl glyph, do not display errors. + } + + const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; + ERR_FAIL_COND_V(gl[p_glyph].texture_idx < -1 || gl[p_glyph].texture_idx >= fd->cache[size]->textures.size(), Size2()); + + if (RenderingServer::get_singleton() != nullptr) { + if (gl[p_glyph].texture_idx != -1) { + if (fd->cache[size]->textures[gl[p_glyph].texture_idx].dirty) { + FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph].texture_idx]; + Ref<Image> img; + img.instantiate(); + img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } + if (tex.texture.is_null()) { + tex.texture.instantiate(); + tex.texture->create_from_image(img); + } else { + tex.texture->update(img); + } + tex.dirty = false; + } + return fd->cache[size]->textures[gl[p_glyph].texture_idx].texture->get_size(); + } + } + + return Size2(); +} + Dictionary TextServerFallback::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const { FontDataFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); @@ -1996,6 +2102,9 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can Ref<Image> img; img.instantiate(); img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } if (tex.texture.is_null()) { tex.texture.instantiate(); tex.texture->create_from_image(img); @@ -2072,6 +2181,9 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI Ref<Image> img; img.instantiate(); img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata); + if (fd->mipmaps) { + img->generate_mipmaps(); + } if (tex.texture.is_null()) { tex.texture.instantiate(); tex.texture->create_from_image(img); diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index ea77659b5d..d6f61e02f8 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -179,6 +179,7 @@ class TextServerFallback : public TextServerExtension { Mutex mutex; bool antialiased = true; + bool mipmaps = false; bool msdf = false; int msdf_range = 14; int msdf_source_size = 48; @@ -375,6 +376,9 @@ public: virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; virtual bool font_is_antialiased(const RID &p_font_rid) const override; + virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; + virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; + virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override; virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override; @@ -458,6 +462,8 @@ public: virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) override; + virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override; diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index 495303d6c4..06fa90eb29 100644 --- a/modules/visual_script/editor/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -3390,6 +3390,8 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_NODE_PATH); n->set_base_path(drop_path); } + } else { + n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_INSTANCE); } if (drop_node) { n->set_base_type(drop_node->get_class()); @@ -3702,8 +3704,13 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri Object::cast_to<VisualScriptTypeCast>(vnode.ptr())->set_base_type(base_type); Object::cast_to<VisualScriptTypeCast>(vnode.ptr())->set_base_script(base_script); } else if (Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())) { - Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_type(base_type); - Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_script(base_script); + if (base_type_map.has(base_type)) { + Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_basic_type(base_type_map[base_type]); + Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_call_mode(VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE); + } else { + Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_type(base_type); + Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_script(base_script); + } } else if (Object::cast_to<VisualScriptPropertySet>(vnode.ptr())) { Object::cast_to<VisualScriptPropertySet>(vnode.ptr())->set_base_type(base_type); Object::cast_to<VisualScriptPropertySet>(vnode.ptr())->set_base_script(base_script); @@ -4751,6 +4758,35 @@ VisualScriptEditor::VisualScriptEditor() { popup_menu->add_item(TTR("Duplicate"), EDIT_DUPLICATE_NODES); popup_menu->add_item(TTR("Clear Copy Buffer"), EDIT_CLEAR_COPY_BUFFER); popup_menu->connect("id_pressed", callable_mp(this, &VisualScriptEditor::_menu_option)); + + base_type_map.insert("String", Variant::STRING); + base_type_map.insert("Vector2", Variant::VECTOR2); + base_type_map.insert("Vector2i", Variant::VECTOR2I); + base_type_map.insert("Rect2", Variant::RECT2); + base_type_map.insert("Rect2i", Variant::RECT2I); + base_type_map.insert("Vector3", Variant::VECTOR3); + base_type_map.insert("Vector3i", Variant::VECTOR3I); + base_type_map.insert("Transform2D", Variant::TRANSFORM2D); + base_type_map.insert("Plane", Variant::PLANE); + base_type_map.insert("Quaternion", Variant::QUATERNION); + base_type_map.insert("AABB", Variant::AABB); + base_type_map.insert("Basis", Variant::BASIS); + base_type_map.insert("Transform3D", Variant::TRANSFORM3D); + base_type_map.insert("Color", Variant::COLOR); + base_type_map.insert("NodePath", Variant::NODE_PATH); + base_type_map.insert("RID", Variant::RID); + base_type_map.insert("Callable", Variant::CALLABLE); + base_type_map.insert("Dictionary", Variant::DICTIONARY); + base_type_map.insert("Array", Variant::ARRAY); + base_type_map.insert("PackedByteArray", Variant::PACKED_BYTE_ARRAY); + base_type_map.insert("PackedInt32Array", Variant::PACKED_INT32_ARRAY); + base_type_map.insert("PackedFloat32Array", Variant::PACKED_FLOAT32_ARRAY); + base_type_map.insert("PackedInt64Array", Variant::PACKED_INT64_ARRAY); + base_type_map.insert("PackedFloat64Array", Variant::PACKED_FLOAT64_ARRAY); + base_type_map.insert("PackedStringArray", Variant::PACKED_STRING_ARRAY); + base_type_map.insert("PackedVector2Array", Variant::PACKED_VECTOR2_ARRAY); + base_type_map.insert("PackedVector3Array", Variant::PACKED_VECTOR3_ARRAY); + base_type_map.insert("PackedColorArray", Variant::PACKED_COLOR_ARRAY); } VisualScriptEditor::~VisualScriptEditor() { diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index 5b355a71df..fcfd44cecd 100644 --- a/modules/visual_script/editor/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -144,6 +144,7 @@ class VisualScriptEditor : public ScriptEditorBase { Map<StringName, Color> node_colors; HashMap<StringName, Ref<StyleBox>> node_styles; + Map<StringName, Variant::Type> base_type_map; void _update_graph_connections(); void _update_graph(int p_only_id = -1); diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp index 31406a2a6f..07929e5c0e 100644 --- a/modules/visual_script/editor/visual_script_property_selector.cpp +++ b/modules/visual_script/editor/visual_script_property_selector.cpp @@ -86,6 +86,13 @@ void VisualScriptPropertySelector::_update_results_s(String p_string) { _update_results(); } +void VisualScriptPropertySelector::_update_results_search_all() { + if (search_classes->is_pressed()) { + scope_combo->select(COMBO_ALL); + } + _update_results(); +} + void VisualScriptPropertySelector::_update_results() { _update_icons(); search_runner = Ref<SearchRunner>(memnew(SearchRunner(this, results_tree))); @@ -167,7 +174,7 @@ void VisualScriptPropertySelector::select_method_from_base_type(const String &p_ search_properties->set_pressed(false); search_theme_items->set_pressed(false); - scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" + scope_combo->select(COMBO_BASE); results_tree->clear(); show_window(.5f); @@ -201,8 +208,7 @@ void VisualScriptPropertySelector::select_from_base_type(const String &p_base, c search_properties->set_pressed(true); search_theme_items->set_pressed(false); - // When class is Input only show inheritors - scope_combo->select(0); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" + scope_combo->select(COMBO_RELATED); results_tree->clear(); show_window(.5f); @@ -234,7 +240,7 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip search_properties->set_pressed(true); search_theme_items->set_pressed(false); - scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" + scope_combo->select(COMBO_BASE); results_tree->clear(); show_window(.5f); @@ -264,7 +270,7 @@ void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, search_properties->set_pressed(true); search_theme_items->set_pressed(false); - scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All" + scope_combo->select(COMBO_BASE); results_tree->clear(); show_window(.5f); @@ -294,7 +300,7 @@ void VisualScriptPropertySelector::select_from_action(const String &p_type, cons search_properties->set_pressed(false); search_theme_items->set_pressed(false); - scope_combo->select(0); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All" + scope_combo->select(COMBO_RELATED); results_tree->clear(); show_window(.5f); @@ -330,7 +336,7 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons search_properties->set_pressed(true); search_theme_items->set_pressed(false); - scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All" + scope_combo->select(COMBO_BASE); results_tree->clear(); show_window(.5f); @@ -363,7 +369,7 @@ void VisualScriptPropertySelector::select_from_visual_script(const Ref<Script> & search_properties->set_pressed(true); search_theme_items->set_pressed(false); - scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All" + scope_combo->select(COMBO_BASE); results_tree->clear(); show_window(.5f); @@ -418,7 +424,7 @@ VisualScriptPropertySelector::VisualScriptPropertySelector() { search_classes = memnew(Button); search_classes->set_flat(true); search_classes->set_tooltip(TTR("Search Classes")); - search_classes->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results)); + search_classes->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results_search_all)); search_classes->set_toggle_mode(true); search_classes->set_pressed(true); search_classes->set_focus_mode(Control::FOCUS_NONE); @@ -739,49 +745,46 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_node_classes_build() { if (vs_nodes.is_empty()) { return true; } - String registerd_node_name = vs_nodes[0]; + String registered_node_name = vs_nodes[0]; vs_nodes.pop_front(); - Vector<String> path = registerd_node_name.split("/"); + Vector<String> path = registered_node_name.split("/"); if (path[0] == "constants") { - _add_class_doc(registerd_node_name, "", "constants"); + _add_class_doc(registered_node_name, "", "constants"); } else if (path[0] == "custom") { - _add_class_doc(registerd_node_name, "", "custom"); + _add_class_doc(registered_node_name, "", "custom"); } else if (path[0] == "data") { - _add_class_doc(registerd_node_name, "", "data"); + _add_class_doc(registered_node_name, "", "data"); } else if (path[0] == "flow_control") { - _add_class_doc(registerd_node_name, "", "flow_control"); + _add_class_doc(registered_node_name, "", "flow_control"); } else if (path[0] == "functions") { if (path[1] == "built_in") { - _add_class_doc(registerd_node_name, "functions", "built_in"); + _add_class_doc(registered_node_name, "functions", "built_in"); } else if (path[1] == "by_type") { - if (search_flags & SEARCH_CLASSES) { - _add_class_doc(registerd_node_name, path[2], "by_type_class"); - } + // No action is required. + // Using function references from ClassDB to remove confusion for users. } else if (path[1] == "constructors") { - if (search_flags & SEARCH_CLASSES) { - _add_class_doc(registerd_node_name, path[2].substr(0, path[2].find_char('(')), "constructors_class"); - } + _add_class_doc(registered_node_name, "", "constructors"); } else if (path[1] == "deconstruct") { - _add_class_doc(registerd_node_name, "", "deconstruct"); + _add_class_doc(registered_node_name, "", "deconstruct"); } else if (path[1] == "wait") { - _add_class_doc(registerd_node_name, "functions", "yield"); + _add_class_doc(registered_node_name, "functions", "yield"); } else { - _add_class_doc(registerd_node_name, "functions", ""); + _add_class_doc(registered_node_name, "functions", ""); } } else if (path[0] == "index") { - _add_class_doc(registerd_node_name, "", "index"); + _add_class_doc(registered_node_name, "", "index"); } else if (path[0] == "operators") { if (path[1] == "bitwise") { - _add_class_doc(registerd_node_name, "operators", "bitwise"); + _add_class_doc(registered_node_name, "operators", "bitwise"); } else if (path[1] == "compare") { - _add_class_doc(registerd_node_name, "operators", "compare"); + _add_class_doc(registered_node_name, "operators", "compare"); } else if (path[1] == "logic") { - _add_class_doc(registerd_node_name, "operators", "logic"); + _add_class_doc(registered_node_name, "operators", "logic"); } else if (path[1] == "math") { - _add_class_doc(registerd_node_name, "operators", "math"); + _add_class_doc(registered_node_name, "operators", "math"); } else { - _add_class_doc(registerd_node_name, "operators", ""); + _add_class_doc(registered_node_name, "operators", ""); } } return false; diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h index faf39a14e4..1b32ee2967 100644 --- a/modules/visual_script/editor/visual_script_property_selector.h +++ b/modules/visual_script/editor/visual_script_property_selector.h @@ -62,6 +62,15 @@ class VisualScriptPropertySelector : public ConfirmationDialog { SCOPE_ALL = SCOPE_BASE | SCOPE_INHERITERS | SCOPE_UNRELATED }; + enum ScopeCombo { + COMBO_RELATED, + COMBO_SEPARATOR, + COMBO_BASE, + COMBO_INHERITERS, + COMBO_UNRELATED, + COMBO_ALL, + }; + LineEdit *search_box = nullptr; Button *case_sensitive_button = nullptr; @@ -88,6 +97,7 @@ class VisualScriptPropertySelector : public ConfirmationDialog { void _sbox_input(const Ref<InputEvent> &p_ie); void _update_results_i(int p_int); void _update_results_s(String p_string); + void _update_results_search_all(); void _update_results(); void _confirmed(); diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java index e8ffbb9481..fb1604f6af 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java +++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java @@ -65,10 +65,6 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God } else { Log.v(TAG, "Creating new Godot fragment instance."); godotFragment = initGodotInstance(); - if (godotFragment == null) { - throw new IllegalStateException("Godot instance must be non-null."); - } - getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss(); } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 8a86136daf..6e597163ab 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -509,17 +509,14 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC use_debug_opengl = true; } else if (command_line[i].equals("--use_immersive")) { use_immersive = true; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+ - window.getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar - View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - - UiChangeListener(); - } + window.getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar + View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + UiChangeListener(); } else if (command_line[i].equals("--use_apk_expansion")) { use_apk_expansion = true; } else if (has_extra && command_line[i].equals("--apk_expansion_md5")) { @@ -699,7 +696,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); - if (use_immersive && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+ + if (use_immersive) { Window window = getActivity().getWindow(); window.getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | @@ -719,15 +716,13 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC final View decorView = getActivity().getWindow().getDecorView(); decorView.setOnSystemUiVisibilityChangeListener(visibility -> { if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - decorView.setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_FULLSCREEN | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - } + decorView.setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } }); } @@ -888,9 +883,8 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC // Create Hex String StringBuilder hexString = new StringBuilder(); - for (int i = 0; i < messageDigest.length; i++) { - String s = Integer.toHexString(0xFF & messageDigest[i]); - + for (byte b : messageDigest) { + String s = Integer.toHexString(0xFF & b); if (s.length() == 1) { s = "0" + s; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java index c06d89b843..8694bb91e1 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java @@ -34,8 +34,9 @@ import static org.godotengine.godot.utils.GLUtils.DEBUG; import org.godotengine.godot.GodotLib; import org.godotengine.godot.GodotRenderView; -import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener; +import android.content.Context; +import android.hardware.input.InputManager; import android.os.Build; import android.util.Log; import android.util.SparseArray; @@ -53,9 +54,9 @@ import java.util.Set; /** * Handles input related events for the {@link GodotRenderView} view. */ -public class GodotInputHandler implements InputDeviceListener { +public class GodotInputHandler implements InputManager.InputDeviceListener { private final GodotRenderView mRenderView; - private final InputManagerCompat mInputManager; + private final InputManager mInputManager; private final String tag = this.getClass().getSimpleName(); @@ -64,7 +65,7 @@ public class GodotInputHandler implements InputDeviceListener { public GodotInputHandler(GodotRenderView godotView) { mRenderView = godotView; - mInputManager = InputManagerCompat.Factory.getInputManager(mRenderView.getView().getContext()); + mInputManager = (InputManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_SERVICE); mInputManager.registerInputDeviceListener(this, null); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java deleted file mode 100644 index 21fdc658bb..0000000000 --- a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.godotengine.godot.input; - -import android.content.Context; -import android.os.Handler; -import android.view.InputDevice; -import android.view.MotionEvent; - -public interface InputManagerCompat { - /** - * Gets information about the input device with the specified id. - * - * @param id The device id - * @return The input device or null if not found - */ - InputDevice getInputDevice(int id); - - /** - * Gets the ids of all input devices in the system. - * - * @return The input device ids. - */ - int[] getInputDeviceIds(); - - /** - * Registers an input device listener to receive notifications about when - * input devices are added, removed or changed. - * - * @param listener The listener to register. - * @param handler The handler on which the listener should be invoked, or - * null if the listener should be invoked on the calling thread's - * looper. - */ - void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener, - Handler handler); - - /** - * Unregisters an input device listener. - * - * @param listener The listener to unregister. - */ - void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener); - - /* - * The following three calls are to simulate V16 behavior on pre-Jellybean - * devices. If you don't call them, your callback will never be called - * pre-API 16. - */ - - /** - * Pass the motion events to the InputManagerCompat. This is used to - * optimize for polling for controllers. If you do not pass these events in, - * polling will cause regular object creation. - * - * @param event the motion event from the app - */ - void onGenericMotionEvent(MotionEvent event); - - /** - * Tell the V9 input manager that it should stop polling for disconnected - * devices. You can call this during onPause in your activity, although you - * might want to call it whenever your game is not active (or whenever you - * don't care about being notified of new input devices) - */ - void onPause(); - - /** - * Tell the V9 input manager that it should start polling for disconnected - * devices. You can call this during onResume in your activity, although you - * might want to call it less often (only when the gameplay is actually - * active) - */ - void onResume(); - - interface InputDeviceListener { - /** - * Called whenever the input manager detects that a device has been - * added. This will only be called in the V9 version when a motion event - * is detected. - * - * @param deviceId The id of the input device that was added. - */ - void onInputDeviceAdded(int deviceId); - - /** - * Called whenever the properties of an input device have changed since - * they were last queried. This will not be called for the V9 version of - * the API. - * - * @param deviceId The id of the input device that changed. - */ - void onInputDeviceChanged(int deviceId); - - /** - * Called whenever the input manager detects that a device has been - * removed. For the V9 version, this can take some time depending on the - * poll rate. - * - * @param deviceId The id of the input device that was removed. - */ - void onInputDeviceRemoved(int deviceId); - } - - /** - * Use this to construct a compatible InputManager. - */ - class Factory { - /** - * Constructs and returns a compatible InputManger - * - * @param context the Context that will be used to get the system - * service from - * @return a compatible implementation of InputManager - */ - public static InputManagerCompat getInputManager(Context context) { - return new InputManagerV16(context); - } - } -} diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java deleted file mode 100644 index 0dbc13c77b..0000000000 --- a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.godotengine.godot.input; - -import android.annotation.TargetApi; -import android.content.Context; -import android.hardware.input.InputManager; -import android.os.Build; -import android.os.Handler; -import android.view.InputDevice; -import android.view.MotionEvent; - -import java.util.HashMap; -import java.util.Map; - -@TargetApi(Build.VERSION_CODES.JELLY_BEAN) -public class InputManagerV16 implements InputManagerCompat { - private final InputManager mInputManager; - private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners; - - public InputManagerV16(Context context) { - mInputManager = (InputManager)context.getSystemService(Context.INPUT_SERVICE); - mListeners = new HashMap<>(); - } - - @Override - public InputDevice getInputDevice(int id) { - return mInputManager.getInputDevice(id); - } - - @Override - public int[] getInputDeviceIds() { - return mInputManager.getInputDeviceIds(); - } - - static class V16InputDeviceListener implements InputManager.InputDeviceListener { - final InputManagerCompat.InputDeviceListener mIDL; - - public V16InputDeviceListener(InputDeviceListener idl) { - mIDL = idl; - } - - @Override - public void onInputDeviceAdded(int deviceId) { - mIDL.onInputDeviceAdded(deviceId); - } - - @Override - public void onInputDeviceChanged(int deviceId) { - mIDL.onInputDeviceChanged(deviceId); - } - - @Override - public void onInputDeviceRemoved(int deviceId) { - mIDL.onInputDeviceRemoved(deviceId); - } - } - - @Override - public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) { - V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener); - mInputManager.registerInputDeviceListener(v16Listener, handler); - mListeners.put(listener, v16Listener); - } - - @Override - public void unregisterInputDeviceListener(InputDeviceListener listener) { - V16InputDeviceListener curListener = mListeners.remove(listener); - if (null != curListener) { - mInputManager.unregisterInputDeviceListener(curListener); - } - } - - @Override - public void onGenericMotionEvent(MotionEvent event) { - // unused in V16 - } - - @Override - public void onPause() { - // unused in V16 - } - - @Override - public void onResume() { - // unused in V16 - } -} diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java b/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java index 39a57f587a..47df23fe1a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java @@ -43,8 +43,8 @@ public class Crypt { // Create Hex String StringBuilder hexString = new StringBuilder(); - for (int i = 0; i < messageDigest.length; i++) - hexString.append(Integer.toHexString(0xFF & messageDigest[i])); + for (byte b : messageDigest) + hexString.append(Integer.toHexString(0xFF & b)); return hexString.toString(); } catch (Exception e) { diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index ea72bc0e15..5e0a9d967b 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -503,6 +503,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNI return; } + // We force redraw to ensure we render at least once when resuming the app. + Main::force_redraw(); if (os_android->get_main_loop()) { os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED); } diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index ef53415f16..54124c22d0 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -187,10 +187,11 @@ bool OS_Android::main_loop_iterate(bool *r_should_swap_buffers) { return false; } DisplayServerAndroid::get_singleton()->process_events(); + uint64_t current_frames_drawn = Engine::get_singleton()->get_frames_drawn(); bool exit = Main::iteration(); if (r_should_swap_buffers) { - *r_should_swap_buffers = !is_in_low_processor_usage_mode() || RenderingServer::get_singleton()->has_changed(); + *r_should_swap_buffers = !is_in_low_processor_usage_mode() || RenderingServer::get_singleton()->has_changed() || current_frames_drawn != Engine::get_singleton()->get_frames_drawn(); } return exit; diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp new file mode 100644 index 0000000000..7dc90da4be --- /dev/null +++ b/scene/3d/label_3d.cpp @@ -0,0 +1,962 @@ +/*************************************************************************/ +/* label_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "label_3d.h" + +#include "core/core_string_names.h" +#include "scene/resources/theme.h" +#include "scene/scene_string_names.h" + +void Label3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &Label3D::set_horizontal_alignment); + ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &Label3D::get_horizontal_alignment); + + ClassDB::bind_method(D_METHOD("set_vertical_alignment", "alignment"), &Label3D::set_vertical_alignment); + ClassDB::bind_method(D_METHOD("get_vertical_alignment"), &Label3D::get_vertical_alignment); + + ClassDB::bind_method(D_METHOD("set_modulate", "modulate"), &Label3D::set_modulate); + ClassDB::bind_method(D_METHOD("get_modulate"), &Label3D::get_modulate); + + ClassDB::bind_method(D_METHOD("set_outline_modulate", "modulate"), &Label3D::set_outline_modulate); + ClassDB::bind_method(D_METHOD("get_outline_modulate"), &Label3D::get_outline_modulate); + + ClassDB::bind_method(D_METHOD("set_text", "text"), &Label3D::set_text); + ClassDB::bind_method(D_METHOD("get_text"), &Label3D::get_text); + + ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Label3D::set_text_direction); + ClassDB::bind_method(D_METHOD("get_text_direction"), &Label3D::get_text_direction); + + ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Label3D::set_opentype_feature); + ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Label3D::get_opentype_feature); + ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Label3D::clear_opentype_features); + + ClassDB::bind_method(D_METHOD("set_language", "language"), &Label3D::set_language); + ClassDB::bind_method(D_METHOD("get_language"), &Label3D::get_language); + + ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &Label3D::set_structured_text_bidi_override); + ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override"), &Label3D::get_structured_text_bidi_override); + + ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override_options", "args"), &Label3D::set_structured_text_bidi_override_options); + ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &Label3D::get_structured_text_bidi_override_options); + + ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &Label3D::set_uppercase); + ClassDB::bind_method(D_METHOD("is_uppercase"), &Label3D::is_uppercase); + + ClassDB::bind_method(D_METHOD("set_font", "font"), &Label3D::set_font); + ClassDB::bind_method(D_METHOD("get_font"), &Label3D::get_font); + + ClassDB::bind_method(D_METHOD("set_font_size", "size"), &Label3D::set_font_size); + ClassDB::bind_method(D_METHOD("get_font_size"), &Label3D::get_font_size); + + ClassDB::bind_method(D_METHOD("set_outline_size", "outline_size"), &Label3D::set_outline_size); + ClassDB::bind_method(D_METHOD("get_outline_size"), &Label3D::get_outline_size); + + ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &Label3D::set_line_spacing); + ClassDB::bind_method(D_METHOD("get_line_spacing"), &Label3D::get_line_spacing); + + ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Label3D::set_autowrap_mode); + ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &Label3D::get_autowrap_mode); + + ClassDB::bind_method(D_METHOD("set_width", "width"), &Label3D::set_width); + ClassDB::bind_method(D_METHOD("get_width"), &Label3D::get_width); + + ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &Label3D::set_pixel_size); + ClassDB::bind_method(D_METHOD("get_pixel_size"), &Label3D::get_pixel_size); + + ClassDB::bind_method(D_METHOD("set_draw_flag", "flag", "enabled"), &Label3D::set_draw_flag); + ClassDB::bind_method(D_METHOD("get_draw_flag", "flag"), &Label3D::get_draw_flag); + + ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &Label3D::set_billboard_mode); + ClassDB::bind_method(D_METHOD("get_billboard_mode"), &Label3D::get_billboard_mode); + + ClassDB::bind_method(D_METHOD("set_alpha_cut_mode", "mode"), &Label3D::set_alpha_cut_mode); + ClassDB::bind_method(D_METHOD("get_alpha_cut_mode"), &Label3D::get_alpha_cut_mode); + + ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &Label3D::set_alpha_scissor_threshold); + ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &Label3D::get_alpha_scissor_threshold); + + ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &Label3D::set_texture_filter); + ClassDB::bind_method(D_METHOD("get_texture_filter"), &Label3D::get_texture_filter); + + ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &Label3D::generate_triangle_mesh); + + ClassDB::bind_method(D_METHOD("_queue_update"), &Label3D::_queue_update); + ClassDB::bind_method(D_METHOD("_font_changed"), &Label3D::_font_changed); + ClassDB::bind_method(D_METHOD("_im_update"), &Label3D::_im_update); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size"); + + ADD_GROUP("Flags", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard"), "set_billboard_mode", "get_billboard_mode"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shaded"), "set_draw_flag", "get_draw_flag", FLAG_SHADED); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "double_sided"), "set_draw_flag", "get_draw_flag", FLAG_DOUBLE_SIDED); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_draw_flag", "get_draw_flag", FLAG_DISABLE_DEPTH_TEST); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_draw_flag", "get_draw_flag", FLAG_FIXED_SIZE); + ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); + + ADD_GROUP("Text", ""); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_modulate"), "set_outline_modulate", "get_outline_modulate"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1"), "set_font_size", "get_font_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1"), "set_outline_size", "get_outline_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing"), "set_line_spacing", "get_line_spacing"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width"), "set_width", "get_width"); + 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("Locale", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); + + BIND_ENUM_CONSTANT(AUTOWRAP_OFF); + BIND_ENUM_CONSTANT(AUTOWRAP_ARBITRARY); + BIND_ENUM_CONSTANT(AUTOWRAP_WORD); + BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART); + + BIND_ENUM_CONSTANT(FLAG_SHADED); + BIND_ENUM_CONSTANT(FLAG_DOUBLE_SIDED); + BIND_ENUM_CONSTANT(FLAG_DISABLE_DEPTH_TEST); + BIND_ENUM_CONSTANT(FLAG_FIXED_SIZE); + BIND_ENUM_CONSTANT(FLAG_MAX); + + BIND_ENUM_CONSTANT(ALPHA_CUT_DISABLED); + BIND_ENUM_CONSTANT(ALPHA_CUT_DISCARD); + BIND_ENUM_CONSTANT(ALPHA_CUT_OPAQUE_PREPASS); +} + +bool Label3D::_set(const StringName &p_name, const Variant &p_value) { + String str = p_name; + if (str.begins_with("opentype_features/")) { + String name = str.get_slicec('/', 1); + int32_t tag = TS->name_to_tag(name); + int value = p_value; + if (value == -1) { + if (opentype_features.has(tag)) { + opentype_features.erase(tag); + dirty_font = true; + _queue_update(); + } + } else { + if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) { + opentype_features[tag] = value; + dirty_font = true; + _queue_update(); + } + } + notify_property_list_changed(); + return true; + } + + return false; +} + +bool Label3D::_get(const StringName &p_name, Variant &r_ret) const { + String str = p_name; + if (str.begins_with("opentype_features/")) { + String name = str.get_slicec('/', 1); + int32_t tag = TS->name_to_tag(name); + if (opentype_features.has(tag)) { + r_ret = opentype_features[tag]; + return true; + } else { + r_ret = -1; + return true; + } + } + return false; +} + +void Label3D::_get_property_list(List<PropertyInfo> *p_list) const { + for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) { + String name = TS->tag_to_name(*ftr); + p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name)); + } + p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); +} + +void Label3D::_validate_property(PropertyInfo &property) const { + if (property.name == "material_override" || property.name == "material_overlay") { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } +} + +void Label3D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + if (!pending_update) { + _im_update(); + } + } break; + case NOTIFICATION_TRANSLATION_CHANGED: { + String new_text = tr(text); + if (new_text == xl_text) { + return; // Nothing new. + } + xl_text = new_text; + dirty_text = true; + _queue_update(); + } break; + } +} + +void Label3D::_im_update() { + _shape(); + + triangle_mesh.unref(); + update_gizmos(); + + pending_update = false; +} + +void Label3D::_queue_update() { + if (pending_update) { + return; + } + + pending_update = true; + call_deferred(SceneStringNames::get_singleton()->_im_update); +} + +AABB Label3D::get_aabb() const { + return aabb; +} + +Ref<TriangleMesh> Label3D::generate_triangle_mesh() const { + if (triangle_mesh.is_valid()) { + return triangle_mesh; + } + + Ref<Font> font = _get_font_or_default(); + if (font.is_null()) { + return Ref<TriangleMesh>(); + } + + Vector<Vector3> faces; + faces.resize(6); + Vector3 *facesw = faces.ptrw(); + + float total_h = 0.0; + float max_line_w = 0.0; + for (int i = 0; i < lines_rid.size(); i++) { + total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing; + max_line_w = MAX(max_line_w, TS->shaped_text_get_width(lines_rid[i])); + } + + float vbegin = 0; + switch (vertical_alignment) { + case VERTICAL_ALIGNMENT_FILL: + case VERTICAL_ALIGNMENT_TOP: { + // Nothing. + } break; + case VERTICAL_ALIGNMENT_CENTER: { + vbegin = (total_h - line_spacing) / 2.0; + } break; + case VERTICAL_ALIGNMENT_BOTTOM: { + vbegin = (total_h - line_spacing); + } break; + } + + Vector2 offset = Vector2(0, vbegin); + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_LEFT: + break; + case HORIZONTAL_ALIGNMENT_FILL: + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = -max_line_w / 2.0; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + offset.x = -max_line_w; + } break; + } + + Rect2 final_rect = Rect2(offset, Size2(max_line_w, total_h)); + + if (final_rect.size.x == 0 || final_rect.size.y == 0) { + return Ref<TriangleMesh>(); + } + + real_t pixel_size = get_pixel_size(); + + Vector2 vertices[4] = { + + (final_rect.position + Vector2(0, -final_rect.size.y)) * pixel_size, + (final_rect.position + Vector2(final_rect.size.x, -final_rect.size.y)) * pixel_size, + (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, + final_rect.position * pixel_size, + + }; + + static const int indices[6] = { + 0, 1, 2, + 0, 2, 3 + }; + + for (int j = 0; j < 6; j++) { + int i = indices[j]; + Vector3 vtx; + vtx[0] = vertices[i][0]; + vtx[1] = vertices[i][1]; + facesw[j] = vtx; + } + + triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); + triangle_mesh->create(faces); + + return triangle_mesh; +} + +void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, const Color &p_modulate, int p_priority, int p_outline_size) { + for (int j = 0; j < p_glyph.repeat; j++) { + Vector2 gl_of; + Vector2 gl_sz; + Rect2 gl_uv; + Size2 texs; + RID tex; + + if (p_glyph.font_rid != RID()) { + tex = TS->font_get_glyph_texture_rid(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index); + if (tex != RID()) { + gl_of = (TS->font_get_glyph_offset(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index) + Vector2(p_glyph.x_off, p_glyph.y_off)) * pixel_size; + gl_sz = TS->font_get_glyph_size(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index) * pixel_size; + gl_uv = TS->font_get_glyph_uv_rect(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index); + texs = TS->font_get_glyph_texture_size(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index); + } + } else { + gl_sz = TS->get_hex_code_box_size(p_glyph.font_size, p_glyph.index) * pixel_size; + gl_of = Vector2(0, -gl_sz.y); + } + + bool msdf = TS->font_is_multichannel_signed_distance_field(p_glyph.font_rid); + + uint64_t mat_hash; + if (tex != RID()) { + mat_hash = hash_one_uint64(tex.get_id()); + } else { + mat_hash = hash_one_uint64(0); + } + mat_hash = hash_djb2_one_64(p_priority | (p_outline_size << 31), mat_hash); + + if (!surfaces.has(mat_hash)) { + SurfaceData surf; + surf.material = RenderingServer::get_singleton()->material_create(); + // Set defaults for material, names need to match up those in StandardMaterial3D + RS::get_singleton()->material_set_param(surf.material, "albedo", Color(1, 1, 1, 1)); + RS::get_singleton()->material_set_param(surf.material, "specular", 0.5); + RS::get_singleton()->material_set_param(surf.material, "metallic", 0.0); + RS::get_singleton()->material_set_param(surf.material, "roughness", 1.0); + RS::get_singleton()->material_set_param(surf.material, "uv1_offset", Vector3(0, 0, 0)); + RS::get_singleton()->material_set_param(surf.material, "uv1_scale", Vector3(1, 1, 1)); + RS::get_singleton()->material_set_param(surf.material, "uv2_offset", Vector3(0, 0, 0)); + RS::get_singleton()->material_set_param(surf.material, "uv2_scale", Vector3(1, 1, 1)); + RS::get_singleton()->material_set_param(surf.material, "alpha_scissor_threshold", alpha_scissor_threshold); + if (msdf) { + RS::get_singleton()->material_set_param(surf.material, "msdf_pixel_range", TS->font_get_msdf_pixel_range(p_glyph.font_rid)); + RS::get_singleton()->material_set_param(surf.material, "msdf_outline_size", p_outline_size); + } + + RID shader_rid; + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), true, get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, msdf, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), texture_filter, &shader_rid); + + RS::get_singleton()->material_set_shader(surf.material, shader_rid); + RS::get_singleton()->material_set_param(surf.material, "texture_albedo", tex); + if (get_alpha_cut_mode() == ALPHA_CUT_DISABLED) { + RS::get_singleton()->material_set_render_priority(surf.material, p_priority); + } else { + surf.z_shift = p_priority * pixel_size; + } + + surfaces[mat_hash] = surf; + } + SurfaceData &s = surfaces[mat_hash]; + + s.mesh_vertices.resize((s.offset + 1) * 4); + s.mesh_normals.resize((s.offset + 1) * 4); + s.mesh_tangents.resize((s.offset + 1) * 16); + s.mesh_colors.resize((s.offset + 1) * 4); + s.mesh_uvs.resize((s.offset + 1) * 4); + + s.mesh_vertices.write[(s.offset * 4) + 3] = Vector3(r_offset.x + gl_of.x, r_offset.y - gl_of.y - gl_sz.y, s.z_shift); + s.mesh_vertices.write[(s.offset * 4) + 2] = Vector3(r_offset.x + gl_of.x + gl_sz.x, r_offset.y - gl_of.y - gl_sz.y, s.z_shift); + s.mesh_vertices.write[(s.offset * 4) + 1] = Vector3(r_offset.x + gl_of.x + gl_sz.x, r_offset.y - gl_of.y, s.z_shift); + s.mesh_vertices.write[(s.offset * 4) + 0] = Vector3(r_offset.x + gl_of.x, r_offset.y - gl_of.y, s.z_shift); + + for (int i = 0; i < 4; i++) { + s.mesh_normals.write[(s.offset * 4) + i] = Vector3(0.0, 0.0, 1.0); + s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 0] = 1.0; + s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 1] = 0.0; + s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 2] = 0.0; + s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 3] = 1.0; + s.mesh_colors.write[(s.offset * 4) + i] = p_modulate; + s.mesh_uvs.write[(s.offset * 4) + i] = Vector2(); + + if (aabb == AABB()) { + aabb.position = s.mesh_vertices[(s.offset * 4) + i]; + } else { + aabb.expand_to(s.mesh_vertices[(s.offset * 4) + i]); + } + } + + if (tex != RID()) { + s.mesh_uvs.write[(s.offset * 4) + 3] = Vector2(gl_uv.position.x / texs.x, (gl_uv.position.y + gl_uv.size.y) / texs.y); + s.mesh_uvs.write[(s.offset * 4) + 2] = Vector2((gl_uv.position.x + gl_uv.size.x) / texs.x, (gl_uv.position.y + gl_uv.size.y) / texs.y); + s.mesh_uvs.write[(s.offset * 4) + 1] = Vector2((gl_uv.position.x + gl_uv.size.x) / texs.x, gl_uv.position.y / texs.y); + s.mesh_uvs.write[(s.offset * 4) + 0] = Vector2(gl_uv.position.x / texs.x, gl_uv.position.y / texs.y); + } + + s.indices.resize((s.offset + 1) * 6); + s.indices.write[(s.offset * 6) + 0] = (s.offset * 4) + 0; + s.indices.write[(s.offset * 6) + 1] = (s.offset * 4) + 1; + s.indices.write[(s.offset * 6) + 2] = (s.offset * 4) + 2; + s.indices.write[(s.offset * 6) + 3] = (s.offset * 4) + 0; + s.indices.write[(s.offset * 6) + 4] = (s.offset * 4) + 2; + s.indices.write[(s.offset * 6) + 5] = (s.offset * 4) + 3; + + s.offset++; + r_offset.x += p_glyph.advance * pixel_size; + } +} + +void Label3D::_shape() { + // Clear mesh. + RS::get_singleton()->mesh_clear(mesh); + aabb = AABB(); + + // Clear materials. + for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) { + RenderingServer::get_singleton()->free(E->get().material); + } + surfaces.clear(); + + Ref<Font> font = _get_font_or_default(); + ERR_FAIL_COND(font.is_null()); + + // Update text buffer. + if (dirty_text) { + TS->shaped_text_clear(text_rid); + TS->shaped_text_set_direction(text_rid, text_direction); + + String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text; + TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, language); + + Array stt; + if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) { + GDVIRTUAL_CALL(_structured_text_parser, st_args, text, stt); + } else { + stt = TS->parse_structured_text(st_parser, st_args, text); + } + TS->shaped_text_set_bidi_override(text_rid, stt); + + dirty_text = false; + dirty_font = false; + dirty_lines = true; + } else if (dirty_font) { + 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); + } + + dirty_font = false; + dirty_lines = true; + } + + if (dirty_lines) { + for (int i = 0; i < lines_rid.size(); i++) { + TS->free_rid(lines_rid[i]); + } + lines_rid.clear(); + + uint16_t autowrap_flags = TextServer::BREAK_MANDATORY; + switch (autowrap_mode) { + case AUTOWRAP_WORD_SMART: + autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_WORD: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_ARBITRARY: + autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_OFF: + break; + } + PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); + + float max_line_w = 0.0; + for (int i = 0; i < line_breaks.size(); i = i + 2) { + RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); + max_line_w = MAX(max_line_w, TS->shaped_text_get_width(line)); + lines_rid.push_back(line); + } + + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { + for (int i = 0; i < lines_rid.size() - 1; i++) { + TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); + } + } + dirty_lines = false; + } + + // Generate surfaces and materials. + float total_h = 0.0; + for (int i = 0; i < lines_rid.size(); i++) { + total_h += (TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing) * pixel_size; + } + + float vbegin = 0.0; + switch (vertical_alignment) { + case VERTICAL_ALIGNMENT_FILL: + case VERTICAL_ALIGNMENT_TOP: { + // Nothing. + } break; + case VERTICAL_ALIGNMENT_CENTER: { + vbegin = (total_h - line_spacing * pixel_size) / 2.0; + } break; + case VERTICAL_ALIGNMENT_BOTTOM: { + vbegin = (total_h - line_spacing * pixel_size); + } break; + } + + Vector2 offset = Vector2(0, vbegin); + for (int i = 0; i < lines_rid.size(); i++) { + const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); + int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]); + float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size; + + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_LEFT: + offset.x = 0.0; + break; + case HORIZONTAL_ALIGNMENT_FILL: + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = -line_width / 2.0; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + offset.x = -line_width; + } break; + } + offset.y -= (TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(TextServer::SPACING_TOP)) * pixel_size; + + if (outline_modulate.a != 0.0 && outline_size > 0) { + // Outline surfaces. + Vector2 ol_offset = offset; + for (int j = 0; j < gl_size; j++) { + _generate_glyph_surfaces(glyphs[j], ol_offset, outline_modulate, -1, outline_size); + } + } + + // Main text surfaces. + for (int j = 0; j < gl_size; j++) { + _generate_glyph_surfaces(glyphs[j], offset, modulate, 0); + } + offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM)) * pixel_size; + } + + for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) { + Array mesh_array; + mesh_array.resize(RS::ARRAY_MAX); + mesh_array[RS::ARRAY_VERTEX] = E->get().mesh_vertices; + mesh_array[RS::ARRAY_NORMAL] = E->get().mesh_normals; + mesh_array[RS::ARRAY_TANGENT] = E->get().mesh_tangents; + mesh_array[RS::ARRAY_COLOR] = E->get().mesh_colors; + mesh_array[RS::ARRAY_TEX_UV] = E->get().mesh_uvs; + mesh_array[RS::ARRAY_INDEX] = E->get().indices; + + RS::SurfaceData sd; + RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, mesh_array); + + sd.material = E->get().material; + + RS::get_singleton()->mesh_add_surface(mesh, sd); + } +} + +void Label3D::set_text(const String &p_string) { + text = p_string; + xl_text = tr(p_string); + dirty_text = true; + _queue_update(); +} + +String Label3D::get_text() const { + return text; +} + +void Label3D::set_horizontal_alignment(HorizontalAlignment p_alignment) { + ERR_FAIL_INDEX((int)p_alignment, 4); + if (horizontal_alignment != p_alignment) { + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL || p_alignment == HORIZONTAL_ALIGNMENT_FILL) { + dirty_lines = true; // Reshape lines. + } + horizontal_alignment = p_alignment; + _queue_update(); + } +} + +HorizontalAlignment Label3D::get_horizontal_alignment() const { + return horizontal_alignment; +} + +void Label3D::set_vertical_alignment(VerticalAlignment p_alignment) { + ERR_FAIL_INDEX((int)p_alignment, 4); + if (vertical_alignment != p_alignment) { + vertical_alignment = p_alignment; + _queue_update(); + } +} + +VerticalAlignment Label3D::get_vertical_alignment() const { + return vertical_alignment; +} + +void Label3D::set_text_direction(TextServer::Direction 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_text = true; + _queue_update(); + } +} + +TextServer::Direction Label3D::get_text_direction() const { + return text_direction; +} + +void Label3D::clear_opentype_features() { + opentype_features.clear(); + dirty_font = true; + _queue_update(); +} + +void Label3D::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_font = true; + _queue_update(); + } +} + +int Label3D::get_opentype_feature(const String &p_name) const { + int32_t tag = TS->name_to_tag(p_name); + if (!opentype_features.has(tag)) { + return -1; + } + return opentype_features[tag]; +} + +void Label3D::set_language(const String &p_language) { + if (language != p_language) { + language = p_language; + dirty_text = true; + _queue_update(); + } +} + +String Label3D::get_language() const { + return language; +} + +void Label3D::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) { + if (st_parser != p_parser) { + st_parser = p_parser; + dirty_text = true; + _queue_update(); + } +} + +TextServer::StructuredTextParser Label3D::get_structured_text_bidi_override() const { + return st_parser; +} + +void Label3D::set_structured_text_bidi_override_options(Array p_args) { + if (st_args != p_args) { + st_args = p_args; + dirty_text = true; + _queue_update(); + } +} + +Array Label3D::get_structured_text_bidi_override_options() const { + return st_args; +} + +void Label3D::set_uppercase(bool p_uppercase) { + if (uppercase != p_uppercase) { + uppercase = p_uppercase; + dirty_text = true; + _queue_update(); + } +} + +bool Label3D::is_uppercase() const { + return uppercase; +} + +void Label3D::_font_changed() { + dirty_font = true; + _queue_update(); +} + +void Label3D::set_font(const Ref<Font> &p_font) { + if (font_override != p_font) { + if (font_override.is_valid()) { + font_override->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed")); + } + font_override = p_font; + dirty_font = true; + if (font_override.is_valid()) { + font_override->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed")); + } + _queue_update(); + } +} + +Ref<Font> Label3D::get_font() const { + return font_override; +} + +Ref<Font> Label3D::_get_font_or_default() const { + if (font_override.is_valid() && font_override->get_data_count() > 0) { + return font_override; + } + + // Check the project-defined Theme resource. + if (Theme::get_project_default().is_valid()) { + List<StringName> theme_types; + Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); + + for (const StringName &E : theme_types) { + if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { + return Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); + } + } + } + + // Lastly, fall back on the items defined in the default Theme, if they exist. + { + List<StringName> theme_types; + Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); + + for (const StringName &E : theme_types) { + if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { + return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); + } + } + } + + // If they don't exist, use any type to return the default/empty value. + return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); +} + +void Label3D::set_font_size(int p_size) { + if (font_size != p_size) { + font_size = p_size; + dirty_font = true; + _queue_update(); + } +} + +int Label3D::get_font_size() const { + return font_size; +} + +void Label3D::set_outline_size(int p_size) { + if (outline_size != p_size) { + outline_size = p_size; + _queue_update(); + } +} + +int Label3D::get_outline_size() const { + return outline_size; +} + +void Label3D::set_modulate(const Color &p_color) { + if (modulate != p_color) { + modulate = p_color; + _queue_update(); + } +} + +Color Label3D::get_modulate() const { + return modulate; +} + +void Label3D::set_outline_modulate(const Color &p_color) { + if (outline_modulate != p_color) { + outline_modulate = p_color; + _queue_update(); + } +} + +Color Label3D::get_outline_modulate() const { + return outline_modulate; +} + +void Label3D::set_autowrap_mode(Label3D::AutowrapMode p_mode) { + if (autowrap_mode != p_mode) { + autowrap_mode = p_mode; + dirty_lines = true; + _queue_update(); + } +} + +Label3D::AutowrapMode Label3D::get_autowrap_mode() const { + return autowrap_mode; +} + +void Label3D::set_width(float p_width) { + if (width != p_width) { + width = p_width; + dirty_lines = true; + _queue_update(); + } +} + +float Label3D::get_width() const { + return width; +} + +void Label3D::set_pixel_size(real_t p_amount) { + if (pixel_size != p_amount) { + pixel_size = p_amount; + _queue_update(); + } +} + +real_t Label3D::get_pixel_size() const { + return pixel_size; +} + +void Label3D::set_line_spacing(float p_line_spacing) { + if (line_spacing != p_line_spacing) { + line_spacing = p_line_spacing; + _queue_update(); + } +} + +float Label3D::get_line_spacing() const { + return line_spacing; +} + +void Label3D::set_draw_flag(DrawFlags p_flag, bool p_enable) { + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + if (flags[p_flag] != p_enable) { + flags[p_flag] = p_enable; + _queue_update(); + } +} + +bool Label3D::get_draw_flag(DrawFlags p_flag) const { + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags[p_flag]; +} + +void Label3D::set_billboard_mode(StandardMaterial3D::BillboardMode p_mode) { + ERR_FAIL_INDEX(p_mode, 3); + if (billboard_mode != p_mode) { + billboard_mode = p_mode; + _queue_update(); + } +} + +StandardMaterial3D::BillboardMode Label3D::get_billboard_mode() const { + return billboard_mode; +} + +void Label3D::set_alpha_cut_mode(AlphaCutMode p_mode) { + ERR_FAIL_INDEX(p_mode, 3); + if (alpha_cut != p_mode) { + alpha_cut = p_mode; + _queue_update(); + } +} + +void Label3D::set_texture_filter(StandardMaterial3D::TextureFilter p_filter) { + if (texture_filter != p_filter) { + texture_filter = p_filter; + _queue_update(); + } +} + +StandardMaterial3D::TextureFilter Label3D::get_texture_filter() const { + return texture_filter; +} + +Label3D::AlphaCutMode Label3D::get_alpha_cut_mode() const { + return alpha_cut; +} + +void Label3D::set_alpha_scissor_threshold(float p_threshold) { + if (alpha_scissor_threshold != p_threshold) { + alpha_scissor_threshold = p_threshold; + _queue_update(); + } +} + +float Label3D::get_alpha_scissor_threshold() const { + return alpha_scissor_threshold; +} + +Label3D::Label3D() { + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = (i == FLAG_DOUBLE_SIDED); + } + + text_rid = TS->create_shaped_text(); + + mesh = RenderingServer::get_singleton()->mesh_create(); + + set_cast_shadows_setting(SHADOW_CASTING_SETTING_OFF); + set_base(mesh); +} + +Label3D::~Label3D() { + for (int i = 0; i < lines_rid.size(); i++) { + TS->free_rid(lines_rid[i]); + } + lines_rid.clear(); + + TS->free_rid(text_rid); + + RenderingServer::get_singleton()->free(mesh); + for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) { + RenderingServer::get_singleton()->free(E->get().material); + } + surfaces.clear(); +} diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h new file mode 100644 index 0000000000..cbc5c3c649 --- /dev/null +++ b/scene/3d/label_3d.h @@ -0,0 +1,228 @@ +/*************************************************************************/ +/* label_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LABEL_3D_H +#define LABEL_3D_H + +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/font.h" + +#include "servers/text_server.h" + +class Label3D : public GeometryInstance3D { + GDCLASS(Label3D, GeometryInstance3D); + +public: + enum DrawFlags { + FLAG_SHADED, + FLAG_DOUBLE_SIDED, + FLAG_DISABLE_DEPTH_TEST, + FLAG_FIXED_SIZE, + FLAG_MAX + }; + + enum AlphaCutMode { + ALPHA_CUT_DISABLED, + ALPHA_CUT_DISCARD, + ALPHA_CUT_OPAQUE_PREPASS + }; + + enum AutowrapMode { + AUTOWRAP_OFF, + AUTOWRAP_ARBITRARY, + AUTOWRAP_WORD, + AUTOWRAP_WORD_SMART + }; + +private: + real_t pixel_size = 0.01; + bool flags[FLAG_MAX] = {}; + AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED; + float alpha_scissor_threshold = 0.5; + + AABB aabb; + + mutable Ref<TriangleMesh> triangle_mesh; + RID mesh; + struct SurfaceData { + PackedVector3Array mesh_vertices; + PackedVector3Array mesh_normals; + PackedFloat32Array mesh_tangents; + PackedColorArray mesh_colors; + PackedVector2Array mesh_uvs; + PackedInt32Array indices; + int offset = 0; + float z_shift = 0.0; + RID material; + }; + + Map<uint64_t, SurfaceData> surfaces; + + HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER; + VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER; + String text; + String xl_text; + bool uppercase = false; + + AutowrapMode autowrap_mode = AUTOWRAP_OFF; + float width = 500.0; + + int font_size = 16; + Ref<Font> font_override; + Color modulate = Color(1, 1, 1, 1); + + int outline_size = 0; + Color outline_modulate = Color(0, 0, 0, 1); + + float line_spacing = 0.f; + + Dictionary opentype_features; + String language; + TextServer::Direction text_direction = TextServer::DIRECTION_AUTO; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; + Array st_args; + + RID text_rid; + Vector<RID> lines_rid; + + RID base_material; + StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED; + StandardMaterial3D::TextureFilter texture_filter = StandardMaterial3D::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS; + + bool pending_update = false; + + bool dirty_lines = true; + bool dirty_font = true; + bool dirty_text = true; + + void _generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, const Color &p_modulate, int p_priority = 0, int p_outline_size = 0); + +protected: + GDVIRTUAL2RC(Array, _structured_text_parser, Array, String) + + void _notification(int p_what); + + static void _bind_methods(); + + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + void _validate_property(PropertyInfo &property) const override; + + void _im_update(); + void _font_changed(); + void _queue_update(); + + void _shape(); + +public: + void set_horizontal_alignment(HorizontalAlignment p_alignment); + HorizontalAlignment get_horizontal_alignment() const; + + void set_vertical_alignment(VerticalAlignment p_alignment); + VerticalAlignment get_vertical_alignment() const; + + void set_text(const String &p_string); + String get_text() const; + + void set_text_direction(TextServer::Direction p_text_direction); + TextServer::Direction get_text_direction() const; + + void set_opentype_feature(const String &p_name, int p_value); + int get_opentype_feature(const String &p_name) const; + void clear_opentype_features(); + + void set_language(const String &p_language); + String get_language() const; + + void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); + TextServer::StructuredTextParser get_structured_text_bidi_override() const; + + void set_structured_text_bidi_override_options(Array p_args); + Array get_structured_text_bidi_override_options() const; + + void set_uppercase(bool p_uppercase); + bool is_uppercase() const; + + void set_font(const Ref<Font> &p_font); + Ref<Font> get_font() const; + Ref<Font> _get_font_or_default() const; + + void set_font_size(int p_size); + int get_font_size() const; + + void set_outline_size(int p_size); + int get_outline_size() const; + + void set_line_spacing(float p_size); + float get_line_spacing() const; + + void set_modulate(const Color &p_color); + Color get_modulate() const; + + void set_outline_modulate(const Color &p_color); + Color get_outline_modulate() const; + + void set_autowrap_mode(AutowrapMode p_mode); + AutowrapMode get_autowrap_mode() const; + + void set_width(float p_width); + float get_width() const; + + void set_pixel_size(real_t p_amount); + real_t get_pixel_size() const; + + void set_draw_flag(DrawFlags p_flag, bool p_enable); + bool get_draw_flag(DrawFlags p_flag) const; + + void set_alpha_cut_mode(AlphaCutMode p_mode); + AlphaCutMode get_alpha_cut_mode() const; + + void set_alpha_scissor_threshold(float p_threshold); + float get_alpha_scissor_threshold() const; + + void set_billboard_mode(StandardMaterial3D::BillboardMode p_mode); + StandardMaterial3D::BillboardMode get_billboard_mode() const; + + void set_texture_filter(StandardMaterial3D::TextureFilter p_filter); + StandardMaterial3D::TextureFilter get_texture_filter() const; + + virtual AABB get_aabb() const override; + Ref<TriangleMesh> generate_triangle_mesh() const; + + Label3D(); + ~Label3D(); +}; + +VARIANT_ENUM_CAST(Label3D::AutowrapMode); +VARIANT_ENUM_CAST(Label3D::DrawFlags); +VARIANT_ENUM_CAST(Label3D::AlphaCutMode); + +#endif // LABEL_3D_H diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 8d813e8b2b..d541dd5f37 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -268,6 +268,17 @@ StandardMaterial3D::BillboardMode SpriteBase3D::get_billboard_mode() const { return billboard_mode; } +void SpriteBase3D::set_texture_filter(StandardMaterial3D::TextureFilter p_filter) { + if (texture_filter != p_filter) { + texture_filter = p_filter; + _queue_update(); + } +} + +StandardMaterial3D::TextureFilter SpriteBase3D::get_texture_filter() const { + return texture_filter; +} + void SpriteBase3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_centered", "centered"), &SpriteBase3D::set_centered); ClassDB::bind_method(D_METHOD("is_centered"), &SpriteBase3D::is_centered); @@ -299,6 +310,9 @@ void SpriteBase3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpriteBase3D::set_billboard_mode); ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpriteBase3D::get_billboard_mode); + ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &SpriteBase3D::set_texture_filter); + ClassDB::bind_method(D_METHOD("get_texture_filter"), &SpriteBase3D::get_texture_filter); + ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect); ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh); @@ -317,11 +331,16 @@ void SpriteBase3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_draw_flag", "get_draw_flag", FLAG_TRANSPARENT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shaded"), "set_draw_flag", "get_draw_flag", FLAG_SHADED); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "double_sided"), "set_draw_flag", "get_draw_flag", FLAG_DOUBLE_SIDED); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_draw_flag", "get_draw_flag", FLAG_DISABLE_DEPTH_TEST); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_draw_flag", "get_draw_flag", FLAG_FIXED_SIZE); ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); BIND_ENUM_CONSTANT(FLAG_TRANSPARENT); BIND_ENUM_CONSTANT(FLAG_SHADED); BIND_ENUM_CONSTANT(FLAG_DOUBLE_SIDED); + BIND_ENUM_CONSTANT(FLAG_DISABLE_DEPTH_TEST); + BIND_ENUM_CONSTANT(FLAG_FIXED_SIZE); BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(ALPHA_CUT_DISABLED); @@ -586,7 +605,7 @@ void Sprite3D::_draw() { set_aabb(aabb); RID shader_rid; - StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid); + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, false, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), get_texture_filter(), &shader_rid); if (last_shader != shader_rid) { RS::get_singleton()->material_set_shader(get_material(), shader_rid); last_shader = shader_rid; @@ -948,7 +967,7 @@ void AnimatedSprite3D::_draw() { set_aabb(aabb); RID shader_rid; - StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid); + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, false, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), get_texture_filter(), &shader_rid); if (last_shader != shader_rid) { RS::get_singleton()->material_set_shader(get_material(), shader_rid); last_shader = shader_rid; diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 92dbef0855..047ed5a40d 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -44,6 +44,8 @@ public: FLAG_TRANSPARENT, FLAG_SHADED, FLAG_DOUBLE_SIDED, + FLAG_DISABLE_DEPTH_TEST, + FLAG_FIXED_SIZE, FLAG_MAX }; @@ -80,6 +82,7 @@ private: bool flags[FLAG_MAX] = {}; AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED; StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED; + StandardMaterial3D::TextureFilter texture_filter = StandardMaterial3D::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS; bool pending_update = false; void _im_update(); @@ -131,9 +134,13 @@ public: void set_alpha_cut_mode(AlphaCutMode p_mode); AlphaCutMode get_alpha_cut_mode() const; + void set_billboard_mode(StandardMaterial3D::BillboardMode p_mode); StandardMaterial3D::BillboardMode get_billboard_mode() const; + void set_texture_filter(StandardMaterial3D::TextureFilter p_filter); + StandardMaterial3D::TextureFilter get_texture_filter() const; + virtual Rect2 get_item_rect() const = 0; virtual AABB get_aabb() const override; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 96d2b29fc1..35d1cf1f3e 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2946,90 +2946,17 @@ bool Control::is_text_field() const { return false; } -Array Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String &p_text) const { - Array ret; - switch (p_theme_type) { - case STRUCTURED_TEXT_URI: { - int prev = 0; - for (int i = 0; i < p_text.length(); i++) { - if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) { - if (prev != i) { - ret.push_back(Vector2i(prev, i)); - } - ret.push_back(Vector2i(i, i + 1)); - prev = i + 1; - } - } - if (prev != p_text.length()) { - ret.push_back(Vector2i(prev, p_text.length())); - } - } break; - case STRUCTURED_TEXT_FILE: { - int prev = 0; - for (int i = 0; i < p_text.length(); i++) { - if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) { - if (prev != i) { - ret.push_back(Vector2i(prev, i)); - } - ret.push_back(Vector2i(i, i + 1)); - prev = i + 1; - } - } - if (prev != p_text.length()) { - ret.push_back(Vector2i(prev, p_text.length())); - } - } break; - case STRUCTURED_TEXT_EMAIL: { - bool local = true; - int prev = 0; - for (int i = 0; i < p_text.length(); i++) { - if ((p_text[i] == '@') && local) { // Add full "local" as single context. - local = false; - ret.push_back(Vector2i(prev, i)); - ret.push_back(Vector2i(i, i + 1)); - prev = i + 1; - } else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context. - if (prev != i) { - ret.push_back(Vector2i(prev, i)); - } - ret.push_back(Vector2i(i, i + 1)); - prev = i + 1; - } - } - if (prev != p_text.length()) { - ret.push_back(Vector2i(prev, p_text.length())); - } - } break; - case STRUCTURED_TEXT_LIST: { - if (p_args.size() == 1 && p_args[0].get_type() == Variant::STRING) { - Vector<String> tags = p_text.split(String(p_args[0])); - int prev = 0; - for (int i = 0; i < tags.size(); i++) { - if (prev != i) { - ret.push_back(Vector2i(prev, prev + tags[i].length())); - } - ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1)); - prev = prev + tags[i].length() + 1; - } - } - } break; - case STRUCTURED_TEXT_CUSTOM: { - Array r; - if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, r)) { - for (int i = 0; i < r.size(); i++) { - if (r[i].get_type() == Variant::VECTOR2I) { - ret.push_back(Vector2i(r[i])); - } - } - } - } break; - case STRUCTURED_TEXT_NONE: - case STRUCTURED_TEXT_DEFAULT: - default: { - ret.push_back(Vector2i(0, p_text.length())); +Array Control::structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { + if (p_parser_type == TextServer::STRUCTURED_TEXT_CUSTOM) { + Array ret; + if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, ret)) { + return ret; + } else { + return Array(); } + } else { + return TS->parse_structured_text(p_parser_type, p_args, p_text); } - return ret; } void Control::set_rotation(real_t p_radians) { @@ -3491,14 +3418,6 @@ void Control::_bind_methods() { BIND_ENUM_CONSTANT(TEXT_DIRECTION_LTR); BIND_ENUM_CONSTANT(TEXT_DIRECTION_RTL); - BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT); - BIND_ENUM_CONSTANT(STRUCTURED_TEXT_URI); - BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE); - BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL); - BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST); - BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE); - BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM); - ADD_SIGNAL(MethodInfo("resized")); ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("mouse_entered")); diff --git a/scene/gui/control.h b/scene/gui/control.h index 4240d52b65..65b71d74f8 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -147,16 +147,6 @@ public: TEXT_DIRECTION_INHERITED, }; - enum StructuredTextParser { - STRUCTURED_TEXT_DEFAULT, - STRUCTURED_TEXT_URI, - STRUCTURED_TEXT_FILE, - STRUCTURED_TEXT_EMAIL, - STRUCTURED_TEXT_LIST, - STRUCTURED_TEXT_NONE, - STRUCTURED_TEXT_CUSTOM - }; - private: struct CComparator { bool operator()(const Control *p_a, const Control *p_b) const { @@ -290,7 +280,7 @@ protected: //virtual void _window_gui_input(InputEvent p_event); - virtual Array structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String &p_text) const; + virtual Array structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; @@ -579,6 +569,5 @@ VARIANT_ENUM_CAST(Control::Anchor); VARIANT_ENUM_CAST(Control::LayoutMode); VARIANT_ENUM_CAST(Control::LayoutDirection); VARIANT_ENUM_CAST(Control::TextDirection); -VARIANT_ENUM_CAST(Control::StructuredTextParser); #endif diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index c953dbf4c3..6da5340ca4 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -988,7 +988,7 @@ FileDialog::FileDialog() { hbc->add_child(drives); dir = memnew(LineEdit); - dir->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + dir->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); hbc->add_child(dir); dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -1029,7 +1029,7 @@ FileDialog::FileDialog() { file_box = memnew(HBoxContainer); file_box->add_child(memnew(Label(TTRC("File:")))); file = memnew(LineEdit); - file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + file->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); file->set_stretch_ratio(4); file->set_h_size_flags(Control::SIZE_EXPAND_FILL); file_box->add_child(file); @@ -1063,7 +1063,7 @@ FileDialog::FileDialog() { makedialog->add_child(makevb); makedirname = memnew(LineEdit); - makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); + makedirname->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); makevb->add_margin_child(TTRC("Name:"), makedirname); add_child(makedialog, false, INTERNAL_MODE_FRONT); makedialog->register_text_enter(makedirname); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index cd6fc168c2..eda3d40f63 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -648,21 +648,21 @@ void Label::set_text_direction(Control::TextDirection p_text_direction) { } } -void Label::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) { +void Label::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) { if (st_parser != p_parser) { st_parser = p_parser; - font_dirty = true; + dirty = true; update(); } } -Control::StructuredTextParser Label::get_structured_text_bidi_override() const { +TextServer::StructuredTextParser Label::get_structured_text_bidi_override() const { return st_parser; } void Label::set_structured_text_bidi_override_options(Array p_args) { st_args = p_args; - font_dirty = true; + dirty = true; update(); } diff --git a/scene/gui/label.h b/scene/gui/label.h index 0b931b3084..f7b725928f 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -80,7 +80,7 @@ private: Dictionary opentype_features; String language; TextDirection text_direction = TEXT_DIRECTION_AUTO; - Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; Array st_args; float percent_visible = 1.0; @@ -124,8 +124,8 @@ public: void set_language(const String &p_language); String get_language() const; - void set_structured_text_bidi_override(Control::StructuredTextParser p_parser); - Control::StructuredTextParser get_structured_text_bidi_override() const; + void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); + TextServer::StructuredTextParser get_structured_text_bidi_override() const; void set_structured_text_bidi_override_options(Array p_args); Array get_structured_text_bidi_override_options() const; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index b3f051bb75..e5b58a7cc8 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -1452,7 +1452,7 @@ bool LineEdit::get_draw_control_chars() const { return draw_control_chars; } -void LineEdit::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) { +void LineEdit::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) { if (st_parser != p_parser) { st_parser = p_parser; _shape(); @@ -1460,7 +1460,7 @@ void LineEdit::set_structured_text_bidi_override(Control::StructuredTextParser p } } -Control::StructuredTextParser LineEdit::get_structured_text_bidi_override() const { +TextServer::StructuredTextParser LineEdit::get_structured_text_bidi_override() const { return st_parser; } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index b86ccd6421..50aa2f4460 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -106,7 +106,7 @@ private: String language; TextDirection text_direction = TEXT_DIRECTION_AUTO; TextDirection input_direction = TEXT_DIRECTION_LTR; - Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; Array st_args; bool draw_control_chars = false; @@ -253,8 +253,8 @@ public: void set_draw_control_chars(bool p_draw_control_chars); bool get_draw_control_chars() const; - void set_structured_text_bidi_override(Control::StructuredTextParser p_parser); - Control::StructuredTextParser get_structured_text_bidi_override() const; + void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); + TextServer::StructuredTextParser get_structured_text_bidi_override() const; void set_structured_text_bidi_override_options(Array p_args); Array get_structured_text_bidi_override_options() const; diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index dc4f09d22d..dca6437519 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -61,7 +61,7 @@ String LinkButton::get_text() const { return text; } -void LinkButton::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) { +void LinkButton::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) { if (st_parser != p_parser) { st_parser = p_parser; _shape(); @@ -69,7 +69,7 @@ void LinkButton::set_structured_text_bidi_override(Control::StructuredTextParser } } -Control::StructuredTextParser LinkButton::get_structured_text_bidi_override() const { +TextServer::StructuredTextParser LinkButton::get_structured_text_bidi_override() const { return st_parser; } diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h index f996558f32..6d2dcbde84 100644 --- a/scene/gui/link_button.h +++ b/scene/gui/link_button.h @@ -53,7 +53,7 @@ private: Dictionary opentype_features; String language; TextDirection text_direction = TEXT_DIRECTION_AUTO; - Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; Array st_args; void _shape(); @@ -71,8 +71,8 @@ public: void set_text(const String &p_text); String get_text() const; - void set_structured_text_bidi_override(Control::StructuredTextParser p_parser); - Control::StructuredTextParser get_structured_text_bidi_override() const; + void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); + TextServer::StructuredTextParser get_structured_text_bidi_override() const; void set_structured_text_bidi_override_options(Array p_args); Array get_structured_text_bidi_override_options() const; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index ec13399f82..77055d250b 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2248,7 +2248,7 @@ TextServer::Direction RichTextLabel::_find_direction(Item *p_item) { } } -Control::StructuredTextParser RichTextLabel::_find_stt(Item *p_item) { +TextServer::StructuredTextParser RichTextLabel::_find_stt(Item *p_item) { Item *item = p_item; while (item) { @@ -2838,7 +2838,7 @@ void RichTextLabel::push_strikethrough() { _add_item(item, true); } -void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction, const String &p_language, Control::StructuredTextParser p_st_parser) { +void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction, const String &p_language, TextServer::StructuredTextParser p_st_parser) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemParagraph *item = memnew(ItemParagraph); @@ -3463,7 +3463,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT; Control::TextDirection dir = Control::TEXT_DIRECTION_INHERITED; String lang; - Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; for (int i = 0; i < subtag.size(); i++) { Vector<String> subtag_a = subtag[i].split("="); if (subtag_a.size() == 2) { @@ -3489,19 +3489,19 @@ void RichTextLabel::append_text(const String &p_bbcode) { lang = subtag_a[1]; } else if (subtag_a[0] == "st" || subtag_a[0] == "bidi_override") { if (subtag_a[1] == "d" || subtag_a[1] == "default") { - st_parser = STRUCTURED_TEXT_DEFAULT; + st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; } else if (subtag_a[1] == "u" || subtag_a[1] == "uri") { - st_parser = STRUCTURED_TEXT_URI; + st_parser = TextServer::STRUCTURED_TEXT_URI; } else if (subtag_a[1] == "f" || subtag_a[1] == "file") { - st_parser = STRUCTURED_TEXT_FILE; + st_parser = TextServer::STRUCTURED_TEXT_FILE; } else if (subtag_a[1] == "e" || subtag_a[1] == "email") { - st_parser = STRUCTURED_TEXT_EMAIL; + st_parser = TextServer::STRUCTURED_TEXT_EMAIL; } else if (subtag_a[1] == "l" || subtag_a[1] == "list") { - st_parser = STRUCTURED_TEXT_LIST; + st_parser = TextServer::STRUCTURED_TEXT_LIST; } else if (subtag_a[1] == "n" || subtag_a[1] == "none") { - st_parser = STRUCTURED_TEXT_NONE; + st_parser = TextServer::STRUCTURED_TEXT_NONE; } else if (subtag_a[1] == "c" || subtag_a[1] == "custom") { - st_parser = STRUCTURED_TEXT_CUSTOM; + st_parser = TextServer::STRUCTURED_TEXT_CUSTOM; } } } @@ -4376,7 +4376,7 @@ void RichTextLabel::set_text_direction(Control::TextDirection p_text_direction) } } -void RichTextLabel::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) { +void RichTextLabel::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) { if (st_parser != p_parser) { st_parser = p_parser; main->first_invalid_line = 0; //invalidate ALL @@ -4385,7 +4385,7 @@ void RichTextLabel::set_structured_text_bidi_override(Control::StructuredTextPar } } -Control::StructuredTextParser RichTextLabel::get_structured_text_bidi_override() const { +TextServer::StructuredTextParser RichTextLabel::get_structured_text_bidi_override() const { return st_parser; } @@ -4520,7 +4520,7 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("push_color", "color"), &RichTextLabel::push_color); ClassDB::bind_method(D_METHOD("push_outline_size", "outline_size"), &RichTextLabel::push_outline_size); ClassDB::bind_method(D_METHOD("push_outline_color", "color"), &RichTextLabel::push_outline_color); - ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(STRUCTURED_TEXT_DEFAULT)); + ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(TextServer::STRUCTURED_TEXT_DEFAULT)); ClassDB::bind_method(D_METHOD("push_indent", "level"), &RichTextLabel::push_indent); ClassDB::bind_method(D_METHOD("push_list", "level", "type", "capitalize"), &RichTextLabel::push_list); ClassDB::bind_method(D_METHOD("push_meta", "data"), &RichTextLabel::push_meta); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 856dd52b6e..c6d0d0875d 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -234,7 +234,7 @@ private: HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT; String language; Control::TextDirection direction = Control::TEXT_DIRECTION_AUTO; - Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; ItemParagraph() { type = ITEM_PARAGRAPH; } }; @@ -399,7 +399,7 @@ private: String language; TextDirection text_direction = TEXT_DIRECTION_AUTO; - Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; Array st_args; struct Selection { @@ -467,7 +467,7 @@ private: int _find_margin(Item *p_item, const Ref<Font> &p_base_font, int p_base_font_size); HorizontalAlignment _find_alignment(Item *p_item); TextServer::Direction _find_direction(Item *p_item); - Control::StructuredTextParser _find_stt(Item *p_item); + TextServer::StructuredTextParser _find_stt(Item *p_item); String _find_language(Item *p_item); Color _find_color(Item *p_item, const Color &p_default_color); Color _find_outline_color(Item *p_item, const Color &p_default_color); @@ -525,7 +525,7 @@ public: void push_outline_color(const Color &p_color); void push_underline(); void push_strikethrough(); - void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", Control::StructuredTextParser p_st_parser = STRUCTURED_TEXT_DEFAULT); + void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", TextServer::StructuredTextParser p_st_parser = TextServer::STRUCTURED_TEXT_DEFAULT); void push_indent(int p_level); void push_list(int p_level, ListType p_list, bool p_capitalize); void push_meta(const Variant &p_meta); @@ -633,8 +633,8 @@ public: void set_autowrap_mode(AutowrapMode p_mode); AutowrapMode get_autowrap_mode() const; - void set_structured_text_bidi_override(Control::StructuredTextParser p_parser); - Control::StructuredTextParser get_structured_text_bidi_override() const; + void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); + TextServer::StructuredTextParser get_structured_text_bidi_override() const; void set_structured_text_bidi_override_options(Array p_args); Array get_structured_text_bidi_override_options() const; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index ff23e44cb7..1eacb1d1b7 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2859,7 +2859,7 @@ String TextEdit::get_language() const { return language; } -void TextEdit::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) { +void TextEdit::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) { if (st_parser != p_parser) { st_parser = p_parser; for (int i = 0; i < text.size(); i++) { @@ -2869,7 +2869,7 @@ void TextEdit::set_structured_text_bidi_override(Control::StructuredTextParser p } } -Control::StructuredTextParser TextEdit::get_structured_text_bidi_override() const { +TextServer::StructuredTextParser TextEdit::get_structured_text_bidi_override() const { return st_parser; } diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index b365e9c61c..a0ae9631f9 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -271,7 +271,7 @@ private: Dictionary opentype_features; String language = ""; - Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; Array st_args; void _clear(); @@ -651,8 +651,8 @@ public: void set_language(const String &p_language); String get_language() const; - void set_structured_text_bidi_override(Control::StructuredTextParser p_parser); - Control::StructuredTextParser get_structured_text_bidi_override() const; + void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); + TextServer::StructuredTextParser get_structured_text_bidi_override() const; void set_structured_text_bidi_override_options(Array p_args); Array get_structured_text_bidi_override_options() const; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 3c8ea4d6df..934992c68e 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -334,7 +334,7 @@ int TreeItem::get_opentype_feature(int p_column, const String &p_name) const { return cells[p_column].opentype_features[tag]; } -void TreeItem::set_structured_text_bidi_override(int p_column, Control::StructuredTextParser p_parser) { +void TreeItem::set_structured_text_bidi_override(int p_column, TextServer::StructuredTextParser p_parser) { ERR_FAIL_INDEX(p_column, cells.size()); if (cells[p_column].st_parser != p_parser) { @@ -346,8 +346,8 @@ void TreeItem::set_structured_text_bidi_override(int p_column, Control::Structur } } -Control::StructuredTextParser TreeItem::get_structured_text_bidi_override(int p_column) const { - ERR_FAIL_INDEX_V(p_column, cells.size(), Control::STRUCTURED_TEXT_NONE); +TextServer::StructuredTextParser TreeItem::get_structured_text_bidi_override(int p_column) const { + ERR_FAIL_INDEX_V(p_column, cells.size(), TextServer::STRUCTURED_TEXT_NONE); return cells[p_column].st_parser; } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index b704495444..8ee2a3c382 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -65,7 +65,7 @@ private: Ref<TextLine> text_buf; Dictionary opentype_features; String language; - Control::StructuredTextParser st_parser = Control::STRUCTURED_TEXT_DEFAULT; + TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; Array st_args; Control::TextDirection text_direction = Control::TEXT_DIRECTION_INHERITED; bool dirty = true; @@ -220,8 +220,8 @@ public: int get_opentype_feature(int p_column, const String &p_name) const; void clear_opentype_features(int p_column); - void set_structured_text_bidi_override(int p_column, Control::StructuredTextParser p_parser); - Control::StructuredTextParser get_structured_text_bidi_override(int p_column) const; + void set_structured_text_bidi_override(int p_column, TextServer::StructuredTextParser p_parser); + TextServer::StructuredTextParser get_structured_text_bidi_override(int p_column) const; void set_structured_text_bidi_override_options(int p_column, Array p_args); Array get_structured_text_bidi_override_options(int p_column) const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 34bb1cde05..1cfe54155a 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -257,6 +257,9 @@ void Node::_propagate_after_exit_tree() { } if (!found) { + if (data.unique_name_in_owner) { + _release_unique_name_in_owner(); + } data.owner->data.owned.erase(data.OW); data.owner = nullptr; } @@ -917,12 +920,20 @@ void Node::set_name(const String &p_name) { String name = p_name.validate_node_name(); ERR_FAIL_COND(name.is_empty()); + + if (data.unique_name_in_owner && data.owner) { + _release_unique_name_in_owner(); + } data.name = name; if (data.parent) { data.parent->_validate_child_name(this, true); } + if (data.unique_name_in_owner && data.owner) { + _acquire_unique_name_in_owner(); + } + propagate_notification(NOTIFICATION_PATH_RENAMED); if (is_inside_tree()) { @@ -1303,6 +1314,24 @@ Node *Node::get_node_or_null(const NodePath &p_path) const { next = root; } + } else if (name.is_node_unique_name()) { + if (current->data.owned_unique_nodes.size()) { + // Has unique nodes in ownership + Node **unique = current->data.owned_unique_nodes.getptr(name); + if (!unique) { + return nullptr; + } + next = *unique; + } else if (current->data.owner) { + Node **unique = current->data.owner->data.owned_unique_nodes.getptr(name); + if (!unique) { + return nullptr; + } + next = *unique; + } else { + return nullptr; + } + } else { next = nullptr; @@ -1498,8 +1527,54 @@ void Node::_set_owner_nocheck(Node *p_owner) { data.OW = data.owner->data.owned.back(); } +void Node::_release_unique_name_in_owner() { + ERR_FAIL_NULL(data.owner); // Sanity check. + StringName key = StringName(UNIQUE_NODE_PREFIX + data.name.operator String()); + Node **which = data.owner->data.owned_unique_nodes.getptr(key); + if (which == nullptr || *which != this) { + return; // Ignore. + } + data.owner->data.owned_unique_nodes.erase(key); +} + +void Node::_acquire_unique_name_in_owner() { + ERR_FAIL_NULL(data.owner); // Sanity check. + StringName key = StringName(UNIQUE_NODE_PREFIX + data.name.operator String()); + Node **which = data.owner->data.owned_unique_nodes.getptr(key); + if (which != nullptr && *which != this) { + WARN_PRINT(vformat(RTR("Setting node name '%s' to be unique within scene for '%s', but it's already claimed by '%s'. This node is no longer set unique."), get_name(), is_inside_tree() ? get_path() : data.owner->get_path_to(this), is_inside_tree() ? (*which)->get_path() : data.owner->get_path_to(*which))); + data.unique_name_in_owner = false; + return; + } + data.owner->data.owned_unique_nodes[key] = this; +} + +void Node::set_unique_name_in_owner(bool p_enabled) { + if (data.unique_name_in_owner == p_enabled) { + return; + } + + if (data.unique_name_in_owner && data.owner != nullptr) { + _release_unique_name_in_owner(); + } + data.unique_name_in_owner = p_enabled; + + if (data.unique_name_in_owner && data.owner != nullptr) { + _acquire_unique_name_in_owner(); + } + + update_configuration_warnings(); +} + +bool Node::is_unique_name_in_owner() const { + return data.unique_name_in_owner; +} + void Node::set_owner(Node *p_owner) { if (data.owner) { + if (data.unique_name_in_owner) { + _release_unique_name_in_owner(); + } data.owner->data.owned.erase(data.OW); data.OW = nullptr; data.owner = nullptr; @@ -1526,6 +1601,10 @@ void Node::set_owner(Node *p_owner) { ERR_FAIL_COND(!owner_valid); _set_owner_nocheck(p_owner); + + if (data.unique_name_in_owner) { + _acquire_unique_name_in_owner(); + } } Node *Node::get_owner() const { @@ -2585,16 +2664,16 @@ void Node::clear_internal_tree_resource_paths() { } TypedArray<String> Node::get_configuration_warnings() const { + TypedArray<String> ret; + Vector<String> warnings; if (GDVIRTUAL_CALL(_get_configuration_warnings, warnings)) { - TypedArray<String> ret; - ret.resize(warnings.size()); for (int i = 0; i < warnings.size(); i++) { - ret[i] = warnings[i]; + ret.push_back(warnings[i]); } - return ret; } - return Array(); + + return ret; } String Node::get_configuration_warnings_as_string() const { @@ -2790,6 +2869,11 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path); ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path); + ClassDB::bind_method(D_METHOD("set_unique_name_in_owner", "enable"), &Node::set_unique_name_in_owner); + ClassDB::bind_method(D_METHOD("is_unique_name_in_owner"), &Node::is_unique_name_in_owner); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "unique_name_in_owner", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_unique_name_in_owner", "is_unique_name_in_owner"); + #ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_set_property_pinned", "property", "pinned"), &Node::set_property_pinned); #endif diff --git a/scene/main/node.h b/scene/main/node.h index 57b150e29a..0973baf793 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -99,6 +99,9 @@ private: Node *parent = nullptr; Node *owner = nullptr; Vector<Node *> children; + HashMap<StringName, Node *> owned_unique_nodes; + bool unique_name_in_owner = false; + int internal_children_front = 0; int internal_children_back = 0; int pos = -1; @@ -193,6 +196,9 @@ private: _FORCE_INLINE_ bool _can_process(bool p_paused) const; _FORCE_INLINE_ bool _is_enabled() const; + void _release_unique_name_in_owner(); + void _acquire_unique_name_in_owner(); + protected: void _block() { data.blocked++; } void _unblock() { data.blocked--; } @@ -345,6 +351,9 @@ public: Node *get_owner() const; void get_owned_by(Node *p_by, List<Node *> *p_owned); + void set_unique_name_in_owner(bool p_enabled); + bool is_unique_name_in_owner() const; + void remove_and_skip(); int get_index(bool p_include_internal = true) const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index a2ab9c1f67..e421cdc1f8 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -226,6 +226,7 @@ #include "scene/3d/gpu_particles_collision_3d.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/3d/joint_3d.h" +#include "scene/3d/label_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/lightmap_gi.h" #include "scene/3d/lightmap_probe.h" @@ -480,6 +481,7 @@ void register_scene_types() { GDREGISTER_ABSTRACT_CLASS(SpriteBase3D); GDREGISTER_CLASS(Sprite3D); GDREGISTER_CLASS(AnimatedSprite3D); + GDREGISTER_CLASS(Label3D); GDREGISTER_ABSTRACT_CLASS(Light3D); GDREGISTER_CLASS(DirectionalLight3D); GDREGISTER_CLASS(OmniLight3D); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index efbe9c93f7..d6b2572628 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -54,6 +54,7 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const { cache.write[p_cache_index] = TS->create_font(); TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size); TS->font_set_antialiased(cache[p_cache_index], antialiased); + TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps); TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf); TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range); TS->font_set_msdf_size(cache[p_cache_index], msdf_size); @@ -77,6 +78,9 @@ void FontData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontData::set_antialiased); ClassDB::bind_method(D_METHOD("is_antialiased"), &FontData::is_antialiased); + ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontData::set_generate_mipmaps); + ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontData::get_generate_mipmaps); + ClassDB::bind_method(D_METHOD("set_font_name", "name"), &FontData::set_font_name); ClassDB::bind_method(D_METHOD("get_font_name"), &FontData::get_font_name); @@ -212,6 +216,7 @@ void FontData::_bind_methods() { ClassDB::bind_method(D_METHOD("get_supported_variation_list"), &FontData::get_supported_variation_list); ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name"); @@ -442,6 +447,7 @@ void FontData::reset_state() { cache.clear(); antialiased = true; + mipmaps = false; msdf = false; force_autohinter = false; hinting = TextServer::HINTING_LIGHT; @@ -735,6 +741,7 @@ Error FontData::load_bitmap_font(const String &p_path) { reset_state(); antialiased = false; + mipmaps = false; msdf = false; force_autohinter = false; hinting = TextServer::HINTING_NONE; @@ -1290,6 +1297,21 @@ bool FontData::is_antialiased() const { return antialiased; } +void FontData::set_generate_mipmaps(bool p_generate_mipmaps) { + if (mipmaps != p_generate_mipmaps) { + mipmaps = p_generate_mipmaps; + for (int i = 0; i < cache.size(); i++) { + _ensure_rid(i); + TS->font_set_generate_mipmaps(cache[i], mipmaps); + } + emit_changed(); + } +} + +bool FontData::get_generate_mipmaps() const { + return mipmaps; +} + void FontData::set_multichannel_signed_distance_field(bool p_msdf) { if (msdf != p_msdf) { msdf = p_msdf; diff --git a/scene/resources/font.h b/scene/resources/font.h index 2aa12dd2de..9a90032605 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -49,6 +49,7 @@ class FontData : public Resource { PackedByteArray data; bool antialiased = true; + bool mipmaps = false; bool msdf = false; int msdf_pixel_range = 16; int msdf_size = 48; @@ -103,6 +104,9 @@ public: virtual void set_antialiased(bool p_antialiased); virtual bool is_antialiased() const; + virtual void set_generate_mipmaps(bool p_generate_mipmaps); + virtual bool get_generate_mipmaps() const; + virtual void set_multichannel_signed_distance_field(bool p_msdf); virtual bool is_multichannel_signed_distance_field() const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 430626b008..8e17ff35a9 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -395,6 +395,9 @@ void BaseMaterial3D::init_shaders() { shader_names->distance_fade_min = "distance_fade_min"; shader_names->distance_fade_max = "distance_fade_max"; + shader_names->msdf_pixel_range = "msdf_pixel_range"; + shader_names->msdf_outline_size = "msdf_outline_size"; + shader_names->metallic_texture_channel = "metallic_texture_channel"; shader_names->ao_texture_channel = "ao_texture_channel"; shader_names->clearcoat_texture_channel = "clearcoat_texture_channel"; @@ -432,12 +435,10 @@ void BaseMaterial3D::init_shaders() { shader_names->albedo_texture_size = "albedo_texture_size"; } -Ref<StandardMaterial3D> BaseMaterial3D::materials_for_2d[BaseMaterial3D::MAX_MATERIALS_FOR_2D]; +HashMap<uint64_t, Ref<StandardMaterial3D>> BaseMaterial3D::materials_for_2d; void BaseMaterial3D::finish_shaders() { - for (int i = 0; i < MAX_MATERIALS_FOR_2D; i++) { - materials_for_2d[i].unref(); - } + materials_for_2d.clear(); memdelete(dirty_materials); dirty_materials = nullptr; @@ -644,6 +645,11 @@ void BaseMaterial3D::_update_shader() { code += "uniform float distance_fade_max;\n"; } + if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) { + code += "uniform float msdf_pixel_range;\n"; + code += "uniform float msdf_outline_size;\n"; + } + // alpha scissor is only valid if there is not antialiasing edge // alpha hash is valid whenever, but not with alpha scissor if (transparency == TRANSPARENCY_ALPHA_SCISSOR) { @@ -911,6 +917,12 @@ void BaseMaterial3D::_update_shader() { code += "}\n"; code += "\n\n"; + if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) { + code += "float msdf_median(float r, float g, float b, float a) {\n"; + code += " return min(max(min(r, g), min(max(r, g), b)), a);\n"; + code += "}\n"; + } + code += "\n\n"; if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) { code += "vec4 triplanar_texture(sampler2D p_sampler,vec3 p_weights,vec3 p_triplanar_pos) {\n"; code += " vec4 samp=vec4(0.0);\n"; @@ -1010,7 +1022,30 @@ void BaseMaterial3D::_update_shader() { } } - if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) { + if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) { + code += " {\n"; + code += " albedo_tex.rgb = mix(vec3(1.0 + 0.055) * pow(albedo_tex.rgb, vec3(1.0 / 2.4)) - vec3(0.055), vec3(12.92) * albedo_tex.rgb.rgb, lessThan(albedo_tex.rgb, vec3(0.0031308)));\n"; + code += " vec2 msdf_size = vec2(msdf_pixel_range) / vec2(textureSize(texture_albedo, 0));\n"; + if (flags[FLAG_USE_POINT_SIZE]) { + code += " vec2 dest_size = vec2(1.0) / fwidth(POINT_COORD);\n"; + } else { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += " vec2 dest_size = vec2(1.0) / fwidth(uv1_triplanar_pos);\n"; + } else { + code += " vec2 dest_size = vec2(1.0) / fwidth(base_uv);\n"; + } + } + code += " float px_size = max(0.5 * dot(msdf_size, dest_size), 1.0);\n"; + code += " float d = msdf_median(albedo_tex.r, albedo_tex.g, albedo_tex.b, albedo_tex.a) - 0.5;\n"; + code += " if (msdf_outline_size > 0.0) {\n"; + code += " float cr = clamp(msdf_outline_size, 0.0, msdf_pixel_range / 2.0) / msdf_pixel_range;\n"; + code += " albedo_tex.a = clamp((d + cr) * px_size, 0.0, 1.0);\n"; + code += " } else {\n"; + code += " albedo_tex.a = clamp(d * px_size + 0.5, 0.0, 1.0);\n"; + code += " }\n"; + code += " albedo_tex.rgb = vec3(1.0);\n"; + code += " }\n"; + } else if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) { code += " albedo_tex.rgb = mix(pow((albedo_tex.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)),vec3(2.4)),albedo_tex.rgb.rgb * (1.0 / 12.92),lessThan(albedo_tex.rgb,vec3(0.04045)));\n"; } @@ -1777,6 +1812,14 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { property.usage = PROPERTY_USAGE_NO_EDITOR; } + if (property.name == "msdf_pixel_range" && !flags[FLAG_ALBEDO_TEXTURE_MSDF]) { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } + + if (property.name == "msdf_outline_size" && !flags[FLAG_ALBEDO_TEXTURE_MSDF]) { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } + if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) { property.usage = PROPERTY_USAGE_NO_EDITOR; } @@ -2125,35 +2168,45 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel() return refraction_texture_channel; } -Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, RID *r_shader_rid) { - int version = 0; +Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, bool p_msdf, bool p_no_depth, bool p_fixed_size, TextureFilter p_filter, RID *r_shader_rid) { + int64_t hash = 0; if (p_shaded) { - version = 1; + hash |= 1 << 0; } if (p_transparent) { - version |= 2; + hash |= 1 << 1; } if (p_cut_alpha) { - version |= 4; + hash |= 1 << 2; } if (p_opaque_prepass) { - version |= 8; + hash |= 1 << 3; } if (p_double_sided) { - version |= 16; + hash |= 1 << 4; } if (p_billboard) { - version |= 32; + hash |= 1 << 5; } if (p_billboard_y) { - version |= 64; + hash |= 1 << 6; + } + if (p_msdf) { + hash |= 1 << 7; } + if (p_no_depth) { + hash |= 1 << 8; + } + if (p_fixed_size) { + hash |= 1 << 9; + } + hash = hash_djb2_one_64(p_filter, hash); - if (materials_for_2d[version].is_valid()) { + if (materials_for_2d.has(hash)) { if (r_shader_rid) { - *r_shader_rid = materials_for_2d[version]->get_shader_rid(); + *r_shader_rid = materials_for_2d[hash]->get_shader_rid(); } - return materials_for_2d[version]; + return materials_for_2d[hash]; } Ref<StandardMaterial3D> material; @@ -2164,18 +2217,22 @@ Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, bool p_transpar material->set_cull_mode(p_double_sided ? CULL_DISABLED : CULL_BACK); material->set_flag(FLAG_SRGB_VERTEX_COLOR, true); material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + material->set_flag(FLAG_ALBEDO_TEXTURE_MSDF, p_msdf); + material->set_flag(FLAG_DISABLE_DEPTH_TEST, p_no_depth); + material->set_flag(FLAG_FIXED_SIZE, p_fixed_size); + material->set_texture_filter(p_filter); if (p_billboard || p_billboard_y) { material->set_flag(FLAG_BILLBOARD_KEEP_SCALE, true); material->set_billboard_mode(p_billboard_y ? BILLBOARD_FIXED_Y : BILLBOARD_ENABLED); } - materials_for_2d[version] = material; + materials_for_2d[hash] = material; if (r_shader_rid) { - *r_shader_rid = materials_for_2d[version]->get_shader_rid(); + *r_shader_rid = materials_for_2d[hash]->get_shader_rid(); } - return materials_for_2d[version]; + return materials_for_2d[hash]; } void BaseMaterial3D::set_on_top_of_alpha() { @@ -2203,6 +2260,24 @@ float BaseMaterial3D::get_proximity_fade_distance() const { return proximity_fade_distance; } +void BaseMaterial3D::set_msdf_pixel_range(float p_range) { + msdf_pixel_range = p_range; + RS::get_singleton()->material_set_param(_get_material(), shader_names->msdf_pixel_range, p_range); +} + +float BaseMaterial3D::get_msdf_pixel_range() const { + return msdf_pixel_range; +} + +void BaseMaterial3D::set_msdf_outline_size(float p_size) { + msdf_outline_size = p_size; + RS::get_singleton()->material_set_param(_get_material(), shader_names->msdf_outline_size, p_size); +} + +float BaseMaterial3D::get_msdf_outline_size() const { + return msdf_outline_size; +} + void BaseMaterial3D::set_distance_fade(DistanceFadeMode p_mode) { distance_fade = p_mode; _queue_shader_change(); @@ -2445,6 +2520,12 @@ void BaseMaterial3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_proximity_fade_distance", "distance"), &BaseMaterial3D::set_proximity_fade_distance); ClassDB::bind_method(D_METHOD("get_proximity_fade_distance"), &BaseMaterial3D::get_proximity_fade_distance); + ClassDB::bind_method(D_METHOD("set_msdf_pixel_range", "range"), &BaseMaterial3D::set_msdf_pixel_range); + ClassDB::bind_method(D_METHOD("get_msdf_pixel_range"), &BaseMaterial3D::get_msdf_pixel_range); + + ClassDB::bind_method(D_METHOD("set_msdf_outline_size", "size"), &BaseMaterial3D::set_msdf_outline_size); + ClassDB::bind_method(D_METHOD("get_msdf_outline_size"), &BaseMaterial3D::get_msdf_outline_size); + ClassDB::bind_method(D_METHOD("set_distance_fade", "mode"), &BaseMaterial3D::set_distance_fade); ClassDB::bind_method(D_METHOD("get_distance_fade"), &BaseMaterial3D::get_distance_fade); @@ -2479,6 +2560,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ALBEDO); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "albedo_tex_force_srgb"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_FORCE_SRGB); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "albedo_tex_msdf"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_MSDF); ADD_GROUP("ORM", "orm_"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orm_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ORM); @@ -2616,6 +2698,9 @@ void BaseMaterial3D::_bind_methods() { ADD_GROUP("Proximity Fade", "proximity_fade_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "proximity_fade_enable"), "set_proximity_fade", "is_proximity_fade_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_proximity_fade_distance", "get_proximity_fade_distance"); + ADD_GROUP("MSDF", "msdf_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), "set_msdf_pixel_range", "get_msdf_pixel_range"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "msdf_outline_size", PROPERTY_HINT_RANGE, "1,250,1"), "set_msdf_outline_size", "get_msdf_outline_size"); ADD_GROUP("Distance Fade", "distance_fade_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "distance_fade_mode", PROPERTY_HINT_ENUM, "Disabled,PixelAlpha,PixelDither,ObjectDither"), "set_distance_fade", "get_distance_fade"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_min_distance", "get_distance_fade_min_distance"); @@ -2715,6 +2800,7 @@ void BaseMaterial3D::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_INVERT_HEIGHTMAP); BIND_ENUM_CONSTANT(FLAG_SUBSURFACE_MODE_SKIN); BIND_ENUM_CONSTANT(FLAG_PARTICLE_TRAILS_MODE); + BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_MSDF); BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(DIFFUSE_BURLEY); @@ -2804,6 +2890,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) : set_heightmap_deep_parallax_max_layers(32); set_heightmap_deep_parallax_flip_tangent(false); //also sets binormal + flags[FLAG_ALBEDO_TEXTURE_MSDF] = false; flags[FLAG_USE_TEXTURE_REPEAT] = true; is_initialized = true; diff --git a/scene/resources/material.h b/scene/resources/material.h index 07227c037c..99e125f5b0 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -242,6 +242,7 @@ public: FLAG_INVERT_HEIGHTMAP, FLAG_SUBSURFACE_MODE_SKIN, FLAG_PARTICLE_TRAILS_MODE, + FLAG_ALBEDO_TEXTURE_MSDF, FLAG_MAX }; @@ -412,6 +413,8 @@ private: StringName uv2_blend_sharpness; StringName grow; StringName proximity_fade_distance; + StringName msdf_pixel_range; + StringName msdf_outline_size; StringName distance_fade_min; StringName distance_fade_max; StringName ao_light_affect; @@ -500,6 +503,9 @@ private: bool proximity_fade_enabled = false; float proximity_fade_distance; + float msdf_pixel_range = 4.f; + float msdf_outline_size = 0.f; + DistanceFadeMode distance_fade = DISTANCE_FADE_DISABLED; float distance_fade_max_distance; float distance_fade_min_distance; @@ -527,9 +533,7 @@ private: _FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const; - static const int MAX_MATERIALS_FOR_2D = 128; - - static Ref<StandardMaterial3D> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff + static HashMap<uint64_t, Ref<StandardMaterial3D>> materials_for_2d; //used by Sprite3D, Label3D and other stuff void _validate_high_end(const String &text, PropertyInfo &property) const; @@ -714,6 +718,12 @@ public: void set_proximity_fade_distance(float p_distance); float get_proximity_fade_distance() const; + void set_msdf_pixel_range(float p_range); + float get_msdf_pixel_range() const; + + void set_msdf_outline_size(float p_size); + float get_msdf_outline_size() const; + void set_distance_fade(DistanceFadeMode p_mode); DistanceFadeMode get_distance_fade() const; @@ -739,7 +749,7 @@ public: static void finish_shaders(); static void flush_changes(); - static Ref<Material> get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, RID *r_shader_rid = nullptr); + static Ref<Material> get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, bool p_msdf = false, bool p_no_depth = false, bool p_fixed_size = false, TextureFilter p_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RID *r_shader_rid = nullptr); virtual RID get_shader_rid() const override; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index b1c2702a1e..b991cb1abe 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -310,6 +310,9 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { NODE_FROM_ID(owner, n.owner); if (owner) { node->_set_owner_nocheck(owner); + if (node->data.unique_name_in_owner) { + node->_acquire_unique_name_in_owner(); + } } } diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 01a0411545..597d070285 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -233,48 +233,48 @@ void ParticlesMaterial::_update_shader() { code += "uniform vec3 gravity;\n"; if (color_ramp.is_valid()) { - code += "uniform sampler2D color_ramp;\n"; + code += "uniform sampler2D color_ramp : repeat_disable;\n"; } if (color_initial_ramp.is_valid()) { - code += "uniform sampler2D color_initial_ramp;\n"; + code += "uniform sampler2D color_initial_ramp : repeat_disable;\n"; } if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - code += "uniform sampler2D linear_velocity_texture;\n"; + code += "uniform sampler2D linear_velocity_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) { - code += "uniform sampler2D orbit_velocity_texture;\n"; + code += "uniform sampler2D orbit_velocity_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) { - code += "uniform sampler2D angular_velocity_texture;\n"; + code += "uniform sampler2D angular_velocity_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) { - code += "uniform sampler2D linear_accel_texture;\n"; + code += "uniform sampler2D linear_accel_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) { - code += "uniform sampler2D radial_accel_texture;\n"; + code += "uniform sampler2D radial_accel_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) { - code += "uniform sampler2D tangent_accel_texture;\n"; + code += "uniform sampler2D tangent_accel_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_DAMPING].is_valid()) { - code += "uniform sampler2D damping_texture;\n"; + code += "uniform sampler2D damping_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_ANGLE].is_valid()) { - code += "uniform sampler2D angle_texture;\n"; + code += "uniform sampler2D angle_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_SCALE].is_valid()) { - code += "uniform sampler2D scale_texture;\n"; + code += "uniform sampler2D scale_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) { - code += "uniform sampler2D hue_variation_texture;\n"; + code += "uniform sampler2D hue_variation_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) { - code += "uniform sampler2D anim_speed_texture;\n"; + code += "uniform sampler2D anim_speed_texture : repeat_disable;\n"; } if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) { - code += "uniform sampler2D anim_offset_texture;\n"; + code += "uniform sampler2D anim_offset_texture : repeat_disable;\n"; } if (collision_enabled) { diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 8a7020add5..755962b96c 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -812,7 +812,6 @@ void VisualShader::add_node(Type p_type, const Ref<VisualShaderNode> &p_node, co if (input.is_valid()) { input->shader_mode = shader_mode; input->shader_type = p_type; - input->connect("input_type_changed", callable_mp(this, &VisualShader::_input_type_changed), varray(p_type, p_id)); } n.node->connect("changed", callable_mp(this, &VisualShader::_queue_update)); @@ -882,11 +881,6 @@ void VisualShader::remove_node(Type p_type, int p_id) { Graph *g = &graph[p_type]; ERR_FAIL_COND(!g->nodes.has(p_id)); - Ref<VisualShaderNodeInput> input = g->nodes[p_id].node; - if (input.is_valid()) { - input->disconnect("input_type_changed", callable_mp(this, &VisualShader::_input_type_changed)); - } - g->nodes[p_id].node->disconnect("changed", callable_mp(this, &VisualShader::_queue_update)); g->nodes.erase(p_id); @@ -2033,29 +2027,19 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui if (!node_code.is_empty()) { code += node_name; code += node_code; - code += "\n"; } for (int i = 0; i < output_count; i++) { - bool new_line_inserted = false; if (expanded_output_ports[i]) { 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; } 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; @@ -2065,30 +2049,18 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui } break; case VisualShaderNode::PORT_TYPE_VECTOR_3D: { 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; } 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; } 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; @@ -2098,43 +2070,27 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui } break; case VisualShaderNode::PORT_TYPE_VECTOR_4D: { 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; } 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; } 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; } if (vsnode->is_output_port_connected(i + 4) || (for_preview && vsnode->get_output_port_for_preview() == (i + 4))) { // alpha-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) + ".a;\n"; - outputs[i + 4] = b; + String a = "n_out" + itos(node) + "p" + itos(i + 4); + code += " float " + a + " = n_out" + itos(node) + "p" + itos(i) + ".a;\n"; + outputs[i + 4] = a; } i += 4; @@ -2145,6 +2101,10 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui } } + if (!node_code.is_empty()) { + code += "\n"; + } + code += "\n"; // processed.insert(node); @@ -2597,21 +2557,6 @@ void VisualShader::_queue_update() { call_deferred(SNAME("_update_shader")); } -void VisualShader::_input_type_changed(Type p_type, int p_id) { - ERR_FAIL_INDEX(p_type, TYPE_MAX); - //erase connections using this input, as type changed - Graph *g = &graph[p_type]; - - for (List<Connection>::Element *E = g->connections.front(); E;) { - List<Connection>::Element *N = E->next(); - if (E->get().from_node == p_id) { - g->connections.erase(E); - g->nodes[E->get().to_node].prev_connected_nodes.erase(p_id); - } - E = N; - } -} - void VisualShader::rebuild() { dirty.set(); _update_shader(); @@ -2720,12 +2665,10 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" }, { 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_3D, "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_VECTOR_4D, "color", "COLOR" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "instance_custom", "INSTANCE_CUSTOM.rgb" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "instance_custom_alpha", "INSTANCE_CUSTOM.a" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "instance_custom", "INSTANCE_CUSTOM" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "modelview_matrix", "MODELVIEW_MATRIX" }, @@ -2741,7 +2684,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, // Node3D, Fragment - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "TANGENT" }, @@ -2749,8 +2692,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "view", "VIEW" }, { 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_3D, "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_4D, "color", "COLOR" }, { 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, "model_matrix", "MODEL_MATRIX" }, @@ -2770,7 +2712,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, // Node3D, Light - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, { 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" }, @@ -2798,8 +2740,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { // Canvas Item, Vertex { 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_3D, "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_VECTOR_4D, "color", "COLOR" }, { 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_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" }, @@ -2807,16 +2748,14 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "screen_matrix", "SCREEN_MATRIX" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "instance_custom", "INSTANCE_CUSTOM.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "instance_custom_alpha", "INSTANCE_CUSTOM.a" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "instance_custom", "INSTANCE_CUSTOM" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" }, // Canvas Item, Fragment - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { 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_3D, "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_4D, "color", "COLOR" }, { 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" }, @@ -2826,42 +2765,34 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_texture", "NORMAL_TEXTURE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "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_VECTOR_4D, "specular_shininess", "SPECULAR_SHININESS" }, { 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_2D, "vertex", "VERTEX" }, // Canvas Item, Light - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { 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_3D, "normal", "NORMAL" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light", "LIGHT.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_color", "LIGHT_COLOR.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_color_alpha", "LIGHT_COLOR.a" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light", "LIGHT" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light_color", "LIGHT_COLOR" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_position", "LIGHT_POSITION" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_vertex", "LIGHT_VERTEX" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "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_4D, "shadow", "SHADOW_MODULATE" }, { 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_3D, "specular_shininess", "SPECULAR_SHININESS.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "specular_shininess_alpha", "SPECULAR_SHININESS.a" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "specular_shininess", "SPECULAR_SHININESS" }, // Particles, Start { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, @@ -2871,13 +2802,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { // Particles, Start (Custom) { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, @@ -2887,13 +2816,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { // Particles, Process { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, @@ -2903,13 +2830,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { // Particles, Process (Custom) { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, @@ -2921,13 +2846,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "collision_depth", "COLLISION_DEPTH" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "collision_normal", "COLLISION_NORMAL" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, @@ -2940,8 +2863,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_half_res_pass", "AT_HALF_RES_PASS" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_quarter_res_pass", "AT_QUARTER_RES_PASS" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "eyedir", "EYEDIR" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "half_res_color", "HALF_RES_COLOR.rgb" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "half_res_alpha", "HALF_RES_COLOR.a" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "half_res_color", "HALF_RES_COLOR" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light0_color", "LIGHT0_COLOR" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light0_direction", "LIGHT0_DIRECTION" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "light0_enabled", "LIGHT0_ENABLED" }, @@ -2959,8 +2881,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "light3_enabled", "LIGHT3_ENABLED" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "light3_energy", "LIGHT3_ENERGY" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "position", "POSITION" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "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_VECTOR_4D, "quarter_res_color", "QUARTER_RES_COLOR" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SAMPLER, "radiance", "RADIANCE" }, { 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" }, @@ -2986,20 +2907,20 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "vec3(1.0, 0.0, 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_3D, "color", "vec3(1.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(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_2D, "viewport_size", "vec2(1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Spatial, Fragment - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.rgb" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "vec3(0.0, 1.0, 0.0)" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "vec3(1.0, 0.0, 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_3D, "color", "vec3(1.0)" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(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_2D, "screen_uv", "SCREEN_UV" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" }, @@ -3007,7 +2928,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { // Spatial, Light - { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.rgb" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.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" }, @@ -3018,25 +2939,25 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { { 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_3D, "color", "vec3(1.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(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" }, // Canvas Item, Fragment - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.rgb" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { 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_3D, "color", "vec3(1.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "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_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_3D, "fragcoord", "FRAGCOORD.rgb" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { 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_3D, "normal", "vec3(0.0, 0.0, 1.0)" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "vec3(1.0)" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(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_2D, "screen_uv", "SCREEN_UV" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, @@ -3078,7 +2999,7 @@ int VisualShaderNodeInput::get_output_port_count() const { } VisualShaderNodeInput::PortType VisualShaderNodeInput::get_output_port_type(int p_port) const { - return get_input_type_by_name(input_name); + return p_port == 0 ? get_input_type_by_name(input_name) : PORT_TYPE_SCALAR; } String VisualShaderNodeInput::get_output_port_name(int p_port) const { @@ -3089,6 +3010,22 @@ String VisualShaderNodeInput::get_caption() const { return "Input"; } +bool VisualShaderNodeInput::is_output_port_expandable(int p_port) const { + if (p_port == 0) { + switch (get_input_type_by_name(input_name)) { + case PORT_TYPE_VECTOR_2D: + return true; + case PORT_TYPE_VECTOR_3D: + return true; + case PORT_TYPE_VECTOR_4D: + return true; + default: + return false; + } + } + return false; +} + String VisualShaderNodeInput::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 { if (get_output_port_type(0) == PORT_TYPE_SAMPLER) { return ""; @@ -3548,8 +3485,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" }, { 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_3D, "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_VECTOR_4D, "color", "COLOR" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_view_matrix", "MODELVIEW_MATRIX" }, @@ -3597,14 +3533,12 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { //////////////////////////////////////////////////////////////////////// { 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_3D, "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_VECTOR_4D, "color", "COLOR" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" }, //////////////////////////////////////////////////////////////////////// // Canvas Item, Fragment. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "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_4D, "color", "COLOR" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal_map", "NORMAL_MAP" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "normal_map_depth", "NORMAL_MAP_DEPTH" }, @@ -3613,16 +3547,14 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { //////////////////////////////////////////////////////////////////////// // Canvas Item, Light. //////////////////////////////////////////////////////////////////////// - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light", "LIGHT.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light", "LIGHT" }, //////////////////////////////////////////////////////////////////////// // Sky, Sky. //////////////////////////////////////////////////////////////////////// { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR" }, { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fog", "FOG.rgb" }, - { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "fog_alpha", "FOG.a" }, + { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fog", "FOG" }, //////////////////////////////////////////////////////////////////////// // Fog, Fog. diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 56371c9bba..aaf570d98c 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -448,6 +448,7 @@ public: 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 bool is_output_port_expandable(int p_port) const override; virtual String get_caption() const override; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index c302ea8afd..1368bf0382 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -296,7 +296,7 @@ int VisualShaderNodeColorConstant::get_input_port_count() const { } VisualShaderNodeColorConstant::PortType VisualShaderNodeColorConstant::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR_3D; + return PORT_TYPE_VECTOR_4D; } String VisualShaderNodeColorConstant::get_input_port_name(int p_port) const { @@ -304,15 +304,15 @@ String VisualShaderNodeColorConstant::get_input_port_name(int p_port) const { } int VisualShaderNodeColorConstant::get_output_port_count() const { - return 2; + return 1; } VisualShaderNodeColorConstant::PortType VisualShaderNodeColorConstant::get_output_port_type(int p_port) const { - return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR; + return p_port == 0 ? PORT_TYPE_VECTOR_4D : PORT_TYPE_SCALAR; } String VisualShaderNodeColorConstant::get_output_port_name(int p_port) const { - return p_port == 0 ? "" : "alpha"; //no output port means the editor will be used as port + return ""; } bool VisualShaderNodeColorConstant::is_output_port_expandable(int p_port) const { @@ -323,11 +323,7 @@ bool VisualShaderNodeColorConstant::is_output_port_expandable(int p_port) const } String VisualShaderNodeColorConstant::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] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n"; - code += " " + p_output_vars[1] + " = " + vformat("%.6f", constant.a) + ";\n"; - - return code; + return " " + p_output_vars[0] + " = " + vformat("vec4(%.6f, %.6f, %.6f, %.6f)", constant.r, constant.g, constant.b, constant.a) + ";\n"; } void VisualShaderNodeColorConstant::set_constant(const Color &p_constant) { @@ -651,21 +647,25 @@ String VisualShaderNodeTexture::get_input_port_name(int p_port) const { } int VisualShaderNodeTexture::get_output_port_count() const { - return 2; + return 1; } VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_output_port_type(int p_port) const { - if (p_port == 0 && source == SOURCE_DEPTH) { - return PORT_TYPE_SCALAR; + switch (p_port) { + case 0: + return PORT_TYPE_VECTOR_4D; + default: + return PORT_TYPE_SCALAR; } - return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR; } String VisualShaderNodeTexture::get_output_port_name(int p_port) const { - if (p_port == 0 && source == SOURCE_DEPTH) { - return "depth"; + switch (p_port) { + case 0: + return "color"; + default: + return ""; } - return p_port == 0 ? "rgb" : "alpha"; } bool VisualShaderNodeTexture::is_output_port_expandable(int p_port) const { @@ -722,170 +722,116 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: default_uv = "vec2(0.0)"; } + String code; if (source == SOURCE_TEXTURE) { String id = make_unique_id(p_type, p_id, "tex"); - String code; if (p_input_vars[0].is_empty()) { // Use UV by default. - if (p_input_vars[1].is_empty()) { - code += " vec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n"; + code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n"; } else { - code += " vec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; } - } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; + code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - - code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n"; - code += " " + p_output_vars[1] + " = " + id + "_read.a;\n"; return code; } if (source == SOURCE_PORT) { String id = p_input_vars[2]; - - String code; - code += " {\n"; if (id.is_empty()) { - code += " vec4 " + id + "_tex_read = vec4(0.0);\n"; + code += " " + p_output_vars[0] + " = vec4(0.0);\n"; } else { if (p_input_vars[0].is_empty()) { // Use UV by default. - if (p_input_vars[1].is_empty()) { - code += " vec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n"; + code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n"; } else { - code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; } - } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; + code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - - code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; - code += " " + p_output_vars[1] + " = " + id + "_tex_read.a;\n"; } - code += " }\n"; return code; } if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) { - String code = " {\n"; if (p_input_vars[0].is_empty() || p_for_preview) { // Use UV by default. - if (p_input_vars[1].is_empty()) { - code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0 );\n"; + code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0);\n"; } else { - code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; } - } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", 0.0);\n"; + code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", 0.0);\n"; } else { - code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - - code += " " + p_output_vars[0] + " = _tex_read.rgb;\n"; - code += " " + p_output_vars[1] + " = _tex_read.a;\n"; - code += " }\n"; return code; } if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) { - String code = " {\n"; if (p_input_vars[0].is_empty()) { // Use UV by default. - if (p_input_vars[1].is_empty()) { - code += " vec4 _tex_read = texture(TEXTURE, " + default_uv + ");\n"; + code += " " + p_output_vars[0] + " = texture(TEXTURE, " + default_uv + ");\n"; } else { - code += " vec4 _tex_read = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; } - } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ");\n"; + code += " " + p_output_vars[0] + " = texture(TEXTURE, " + p_input_vars[0] + ");\n"; } else { - code += " vec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - - code += " " + p_output_vars[0] + " = _tex_read.rgb;\n"; - code += " " + p_output_vars[1] + " = _tex_read.a;\n"; - code += " }\n"; return code; } if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) { - String code = " {\n"; if (p_input_vars[0].is_empty()) { // Use UV by default. - if (p_input_vars[1].is_empty()) { - code += " vec4 _tex_read = texture(NORMAL_TEXTURE, " + default_uv + ");\n"; + code += " " + p_output_vars[0] + " = texture(NORMAL_TEXTURE, " + default_uv + ");\n"; } else { - code += " vec4 _tex_read = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; } - } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 _tex_read = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n"; + code += " " + p_output_vars[0] + " = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n"; } else { - code += " vec4 _tex_read = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } - - code += " " + p_output_vars[0] + " = _tex_read.rgb;\n"; - code += " " + p_output_vars[1] + " = _tex_read.a;\n"; - code += " }\n"; return code; } - if (p_for_preview) // DEPTH_TEXTURE is not supported in preview(canvas_item) shader - { - if (source == SOURCE_DEPTH) { - String code; - code += " " + p_output_vars[0] + " = 0.0;\n"; - code += " " + p_output_vars[1] + " = 1.0;\n"; - return code; - } - } - - if (source == SOURCE_DEPTH && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { - String code = " {\n"; - if (p_input_vars[0].is_empty()) { // Use UV by default. - - if (p_input_vars[1].is_empty()) { - code += " float _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n"; + if (source == SOURCE_DEPTH) { + if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { + code += " {\n"; + if (p_input_vars[0].is_empty()) { // Use UV by default. + if (p_input_vars[1].is_empty()) { + code += " float _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n"; + } else { + code += " float _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n"; + } + } else if (p_input_vars[1].is_empty()) { + //no lod + code += " float _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n"; } else { - code += " float _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n"; + code += " float _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n"; } - } else if (p_input_vars[1].is_empty()) { - //no lod - code += " float _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n"; - } else { - code += " float _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n"; + code += " " + p_output_vars[0] + " = vec4(_depth, _depth, _depth, 1.0);\n"; + code += " }\n"; + return code; } - - code += " " + p_output_vars[0] + " = _depth;\n"; - code += " " + p_output_vars[1] + " = 1.0;\n"; - code += " }\n"; - return code; - } else if (source == SOURCE_DEPTH) { - String code; - code += " " + p_output_vars[0] + " = 0.0;\n"; - code += " " + p_output_vars[1] + " = 1.0;\n"; - return code; } - //none - String code; - code += " " + p_output_vars[0] + " = vec3(0.0);\n"; - code += " " + p_output_vars[1] + " = 1.0;\n"; + code += " " + p_output_vars[0] + " = vec4(0.0);\n"; return code; } @@ -1224,15 +1170,15 @@ String VisualShaderNodeSample3D::get_input_port_name(int p_port) const { } int VisualShaderNodeSample3D::get_output_port_count() const { - return 2; + return 1; } VisualShaderNodeSample3D::PortType VisualShaderNodeSample3D::get_output_port_type(int p_port) const { - return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR; + return p_port == 0 ? PORT_TYPE_VECTOR_4D : PORT_TYPE_SCALAR; } String VisualShaderNodeSample3D::get_output_port_name(int p_port) const { - return p_port == 0 ? "rgb" : "alpha"; + return "color"; } bool VisualShaderNodeSample3D::is_output_port_expandable(int p_port) const { @@ -1262,7 +1208,6 @@ String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader String code; if (source == SOURCE_TEXTURE || source == SOURCE_PORT) { String id; - code += " {\n"; if (source == SOURCE_TEXTURE) { id = make_unique_id(p_type, p_id, "tex3d"); } else { @@ -1271,27 +1216,22 @@ String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader if (!id.is_empty()) { if (p_input_vars[0].is_empty()) { // Use UV by default. if (p_input_vars[1].is_empty()) { - code += " vec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n"; + code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n"; } else { - code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; + code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } } else { - code += " vec4 " + id + "_tex_read = vec4(0.0);\n"; + code += " " + p_output_vars[0] + " = vec4(0.0);\n"; } - - code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; - code += " " + p_output_vars[1] + " = " + id + "_tex_read.a;\n"; - code += " }\n"; return code; } - code += " " + p_output_vars[0] + " = vec3(0.0);\n"; - code += " " + p_output_vars[1] + " = 1.0;\n"; + code += " " + p_output_vars[0] + " = vec4(0.0);\n"; return code; } @@ -1489,15 +1429,15 @@ String VisualShaderNodeCubemap::get_input_port_name(int p_port) const { } int VisualShaderNodeCubemap::get_output_port_count() const { - return 2; + return 1; } VisualShaderNodeCubemap::PortType VisualShaderNodeCubemap::get_output_port_type(int p_port) const { - return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR; + return PORT_TYPE_VECTOR_4D; } String VisualShaderNodeCubemap::get_output_port_name(int p_port) const { - return p_port == 0 ? "rgb" : "alpha"; + return "color"; } bool VisualShaderNodeCubemap::is_output_port_expandable(int p_port) const { @@ -1551,37 +1491,28 @@ String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader: } else if (source == SOURCE_PORT) { id = p_input_vars[2]; } else { - return String(); + return code; } - code += " {\n"; - if (id.is_empty()) { - code += " vec4 " + id + "_read = vec4(0.0);\n"; - code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n"; - code += " " + p_output_vars[1] + " = " + id + "_read.a;\n"; - code += " }\n"; + code += " " + p_output_vars[0] + " = vec4(0.0);\n"; return code; } if (p_input_vars[0].is_empty()) { // Use UV by default. if (p_input_vars[1].is_empty()) { - code += " vec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n"; + code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n"; } else { - code += " vec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + " );\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1].is_empty()) { //no lod - code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; + code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n"; - code += " " + p_output_vars[1] + " = " + id + "_read.a;\n"; - code += " }\n"; - return code; } @@ -5680,28 +5611,24 @@ String VisualShaderNodeTextureUniform::get_caption() const { } int VisualShaderNodeTextureUniform::get_input_port_count() const { - return 2; + return 0; } VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_input_port_type(int p_port) const { - return p_port == 0 ? PORT_TYPE_VECTOR_2D : PORT_TYPE_SCALAR; + return PORT_TYPE_SCALAR; } String VisualShaderNodeTextureUniform::get_input_port_name(int p_port) const { - return p_port == 0 ? "uv" : "lod"; + return ""; } int VisualShaderNodeTextureUniform::get_output_port_count() const { - return 3; + return 1; } VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_output_port_type(int p_port) const { switch (p_port) { case 0: - return PORT_TYPE_VECTOR_3D; - case 1: - return PORT_TYPE_SCALAR; - case 2: return PORT_TYPE_SAMPLER; default: return PORT_TYPE_SCALAR; @@ -5711,10 +5638,6 @@ VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_out String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const { switch (p_port) { case 0: - return "rgb"; - case 1: - return "alpha"; - case 2: return "sampler2D"; default: return ""; @@ -5825,37 +5748,8 @@ String VisualShaderNodeTextureUniform::generate_global(Shader::Mode p_mode, Visu return code; } -bool VisualShaderNodeTextureUniform::is_code_generated() const { - return is_output_port_connected(0) || is_output_port_connected(1); // rgb or alpha -} - 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"; - } else { - default_uv = "vec2(0.0)"; - } - - String id = get_uniform_name(); - String code = " {\n"; - if (p_input_vars[0].is_empty()) { // Use UV by default. - if (p_input_vars[1].is_empty()) { - code += " vec4 n_tex_read = texture(" + id + ", " + default_uv + ");\n"; - } else { - code += " vec4 n_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; - } - } else if (p_input_vars[1].is_empty()) { - //no lod - code += " vec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; - } else { - 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"; - code += " " + p_output_vars[1] + " = n_tex_read.a;\n"; - code += " }\n"; - return code; + return ""; } void VisualShaderNodeTextureUniform::set_texture_type(TextureType p_texture_type) { @@ -5977,15 +5871,6 @@ void VisualShaderNodeTextureUniform::_bind_methods() { BIND_ENUM_CONSTANT(REPEAT_MAX); } -bool VisualShaderNodeTextureUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { - if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { - if (p_port == 0) { - return true; - } - } - return false; -} - bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) const { switch (p_qual) { case Qualifier::QUAL_NONE: @@ -6005,7 +5890,6 @@ bool VisualShaderNodeTextureUniform::is_convertible_to_constant() const { } VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() { - simple_decl = false; } ////////////// Texture Uniform (Triplanar) @@ -6018,7 +5902,7 @@ int VisualShaderNodeTextureUniformTriplanar::get_input_port_count() const { return 2; } -VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniformTriplanar::get_input_port_type(int p_port) const { +VisualShaderNodeTextureUniformTriplanar::PortType VisualShaderNodeTextureUniformTriplanar::get_input_port_type(int p_port) const { if (p_port == 0 || p_port == 1) { return PORT_TYPE_VECTOR_3D; } @@ -6034,6 +5918,32 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_name(int p_port) return ""; } +int VisualShaderNodeTextureUniformTriplanar::get_output_port_count() const { + return 2; +} + +VisualShaderNodeTextureUniformTriplanar::PortType VisualShaderNodeTextureUniformTriplanar::get_output_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_VECTOR_4D; + case 1: + return PORT_TYPE_SAMPLER; + default: + return PORT_TYPE_SCALAR; + } +} + +String VisualShaderNodeTextureUniformTriplanar::get_output_port_name(int p_port) const { + switch (p_port) { + case 0: + return "color"; + case 1: + return "sampler2D"; + default: + return ""; + } +} + String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader::Mode p_mode, int p_id) const { String code; @@ -6074,22 +5984,18 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader: 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 = " {\n"; + String code; if (p_input_vars[0].is_empty() && p_input_vars[1].is_empty()) { - code += " vec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n"; + code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n"; } else if (!p_input_vars[0].is_empty() && p_input_vars[1].is_empty()) { - code += " vec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n"; + code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n"; } else if (p_input_vars[0].is_empty() && !p_input_vars[1].is_empty()) { - code += " vec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n"; } else { - code += " vec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - code += " " + p_output_vars[0] + " = n_tex_read.rgb;\n"; - code += " " + p_output_vars[1] + " = n_tex_read.a;\n"; - code += " }\n"; - return code; } @@ -6111,34 +6017,10 @@ String VisualShaderNodeTexture2DArrayUniform::get_caption() const { return "Texture2DArrayUniform"; } -int VisualShaderNodeTexture2DArrayUniform::get_output_port_count() const { - return 1; -} - -VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_output_port_type(int p_port) const { - return PORT_TYPE_SAMPLER; -} - String VisualShaderNodeTexture2DArrayUniform::get_output_port_name(int p_port) const { return "sampler2DArray"; } -int VisualShaderNodeTexture2DArrayUniform::get_input_port_count() const { - return 0; -} - -VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_input_port_type(int p_port) const { - return PORT_TYPE_SCALAR; -} - -String VisualShaderNodeTexture2DArrayUniform::get_input_port_name(int p_port) const { - return ""; -} - -bool VisualShaderNodeTexture2DArrayUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { - return false; -} - String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = _get_qual_str() + "uniform sampler2DArray " + get_uniform_name(); @@ -6184,34 +6066,10 @@ String VisualShaderNodeTexture3DUniform::get_caption() const { return "Texture3DUniform"; } -int VisualShaderNodeTexture3DUniform::get_output_port_count() const { - return 1; -} - -VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_output_port_type(int p_port) const { - return PORT_TYPE_SAMPLER; -} - String VisualShaderNodeTexture3DUniform::get_output_port_name(int p_port) const { return "sampler3D"; } -int VisualShaderNodeTexture3DUniform::get_input_port_count() const { - return 0; -} - -VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_input_port_type(int p_port) const { - return PORT_TYPE_SCALAR; -} - -String VisualShaderNodeTexture3DUniform::get_input_port_name(int p_port) const { - return ""; -} - -bool VisualShaderNodeTexture3DUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { - return false; -} - String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = _get_qual_str() + "uniform sampler3D " + get_uniform_name(); @@ -6257,34 +6115,10 @@ String VisualShaderNodeCubemapUniform::get_caption() const { return "CubemapUniform"; } -int VisualShaderNodeCubemapUniform::get_output_port_count() const { - return 1; -} - -VisualShaderNodeCubemapUniform::PortType VisualShaderNodeCubemapUniform::get_output_port_type(int p_port) const { - return PORT_TYPE_SAMPLER; -} - String VisualShaderNodeCubemapUniform::get_output_port_name(int p_port) const { return "samplerCube"; } -int VisualShaderNodeCubemapUniform::get_input_port_count() const { - return 0; -} - -VisualShaderNodeCubemapUniform::PortType VisualShaderNodeCubemapUniform::get_input_port_type(int p_port) const { - return PORT_TYPE_SCALAR; -} - -String VisualShaderNodeCubemapUniform::get_input_port_name(int p_port) const { - return ""; -} - -bool VisualShaderNodeCubemapUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { - return false; -} - String VisualShaderNodeCubemapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = _get_qual_str() + "uniform samplerCube " + get_uniform_name(); diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index da638c2d10..26c98bd2ea 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -2166,7 +2166,6 @@ public: 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 bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -2177,7 +2176,6 @@ public: virtual Map<StringName, String> get_editable_properties_names() const override; virtual bool is_show_prop_names() const override; - virtual bool is_code_generated() const override; Vector<StringName> get_editable_properties() const override; @@ -2216,6 +2214,10 @@ public: 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 bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override; @@ -2232,16 +2234,8 @@ class VisualShaderNodeTexture2DArrayUniform : public VisualShaderNodeTextureUnif 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 bool is_input_port_default(int p_port, Shader::Mode p_mode) 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; @@ -2255,16 +2249,8 @@ class VisualShaderNodeTexture3DUniform : public VisualShaderNodeTextureUniform { 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 bool is_input_port_default(int p_port, Shader::Mode p_mode) 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; @@ -2278,16 +2264,8 @@ class VisualShaderNodeCubemapUniform : public VisualShaderNodeTextureUniform { 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 bool is_input_port_default(int p_port, Shader::Mode p_mode) 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; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 2dfc4f426e..3c115c942b 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -555,10 +555,21 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin } valid_color_pass_pipelines.insert(0); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP); + + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); + valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); - valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW); material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index fbc641ee9e..f8e9020f9f 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -461,10 +461,6 @@ float msdf_median(float r, float g, float b, float a) { return min(max(min(r, g), min(max(r, g), b)), a); } -vec2 msdf_map(vec2 value, vec2 in_min, vec2 in_max, vec2 out_min, vec2 out_max) { - return out_min + (out_max - out_min) * (value - in_min) / (in_max - in_min); -} - void main() { vec4 color = color_interp; vec2 uv = uv_interp; diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index c8efacc9c5..001706bb6f 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -67,6 +67,9 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased"); GDVIRTUAL_BIND(font_is_antialiased, "font_rid"); + GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps"); + GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid"); + GDVIRTUAL_BIND(font_set_multichannel_signed_distance_field, "font_rid", "msdf"); GDVIRTUAL_BIND(font_is_multichannel_signed_distance_field, "font_rid"); @@ -151,6 +154,9 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(font_get_glyph_texture_idx, "font_rid", "size", "glyph"); GDVIRTUAL_BIND(font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx"); + GDVIRTUAL_BIND(font_get_glyph_texture_rid, "font_rid", "size", "glyph"); + GDVIRTUAL_BIND(font_get_glyph_texture_size, "font_rid", "size", "glyph"); + GDVIRTUAL_BIND(font_get_glyph_contours, "font_rid", "size", "index"); GDVIRTUAL_BIND(font_get_kerning_list, "font_rid", "size"); @@ -289,6 +295,8 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(string_to_upper, "string", "language"); GDVIRTUAL_BIND(string_to_lower, "string", "language"); + + GDVIRTUAL_BIND(parse_structured_text, "parser_type", "args", "text"); } bool TextServerExtension::has_feature(Feature p_feature) const { @@ -451,6 +459,18 @@ bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const { return false; } +void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { + GDVIRTUAL_CALL(font_set_generate_mipmaps, p_font_rid, p_generate_mipmaps); +} + +bool TextServerExtension::font_get_generate_mipmaps(const RID &p_font_rid) const { + bool ret; + if (GDVIRTUAL_CALL(font_get_generate_mipmaps, p_font_rid, ret)) { + return ret; + } + return false; +} + void TextServerExtension::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) { GDVIRTUAL_CALL(font_set_multichannel_signed_distance_field, p_font_rid, p_msdf); } @@ -787,6 +807,22 @@ void TextServerExtension::font_set_glyph_texture_idx(const RID &p_font_rid, cons GDVIRTUAL_CALL(font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx); } +RID TextServerExtension::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { + RID ret; + if (GDVIRTUAL_CALL(font_get_glyph_texture_rid, p_font_rid, p_size, p_glyph, ret)) { + return ret; + } + return RID(); +} + +Size2 TextServerExtension::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { + Size2 ret; + if (GDVIRTUAL_CALL(font_get_glyph_texture_size, p_font_rid, p_size, p_glyph, ret)) { + return ret; + } + return Size2(); +} + Dictionary TextServerExtension::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const { Dictionary ret; if (GDVIRTUAL_CALL(font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) { @@ -1459,6 +1495,14 @@ String TextServerExtension::string_to_lower(const String &p_string, const String return p_string; } +Array TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { + Array ret; + if (GDVIRTUAL_CALL(parse_structured_text, p_parser_type, p_args, p_text, ret)) { + return ret; + } + return Array(); +} + TextServerExtension::TextServerExtension() { //NOP } diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index c6e7bef4e8..ce781097f3 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -104,6 +104,11 @@ public: GDVIRTUAL2(font_set_antialiased, RID, bool); GDVIRTUAL1RC(bool, font_is_antialiased, RID); + virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; + virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; + GDVIRTUAL2(font_set_generate_mipmaps, RID, bool); + GDVIRTUAL1RC(bool, font_get_generate_mipmaps, RID); + virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override; virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override; GDVIRTUAL2(font_set_multichannel_signed_distance_field, RID, bool); @@ -245,6 +250,12 @@ public: GDVIRTUAL3RC(int64_t, font_get_glyph_texture_idx, RID, const Vector2i &, int64_t); GDVIRTUAL4(font_set_glyph_texture_idx, RID, const Vector2i &, int64_t, int64_t); + virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + GDVIRTUAL3RC(RID, font_get_glyph_texture_rid, RID, const Vector2i &, int64_t); + + virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override; + GDVIRTUAL3RC(Size2, font_get_glyph_texture_size, RID, const Vector2i &, int64_t); + virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override; GDVIRTUAL3RC(Dictionary, font_get_glyph_contours, RID, int64_t, int64_t); @@ -479,6 +490,9 @@ public: GDVIRTUAL2RC(String, string_to_upper, const String &, const String &); GDVIRTUAL2RC(String, string_to_lower, const String &, const String &); + Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; + GDVIRTUAL3RC(Array, parse_structured_text, StructuredTextParser, const Array &, const String &); + TextServerExtension(); ~TextServerExtension(); }; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 7e3fde6a1f..d66e769e3c 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -220,6 +220,9 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased); ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased); + ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps); + ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps); + ClassDB::bind_method(D_METHOD("font_set_multichannel_signed_distance_field", "font_rid", "msdf"), &TextServer::font_set_multichannel_signed_distance_field); ClassDB::bind_method(D_METHOD("font_is_multichannel_signed_distance_field", "font_rid"), &TextServer::font_is_multichannel_signed_distance_field); @@ -304,6 +307,9 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("font_get_glyph_texture_idx", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_idx); ClassDB::bind_method(D_METHOD("font_set_glyph_texture_idx", "font_rid", "size", "glyph", "texture_idx"), &TextServer::font_set_glyph_texture_idx); + ClassDB::bind_method(D_METHOD("font_get_glyph_texture_rid", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_rid); + ClassDB::bind_method(D_METHOD("font_get_glyph_texture_size", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_size); + ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::font_get_glyph_contours); ClassDB::bind_method(D_METHOD("font_get_kerning_list", "font_rid", "size"), &TextServer::font_get_kerning_list); @@ -438,6 +444,8 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL("")); ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL("")); + ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text); + /* Direction */ BIND_ENUM_CONSTANT(DIRECTION_AUTO); BIND_ENUM_CONSTANT(DIRECTION_LTR); @@ -526,6 +534,15 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(FONT_BOLD); BIND_ENUM_CONSTANT(FONT_ITALIC); BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH); + + /* Structured text parser */ + BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT); + BIND_ENUM_CONSTANT(STRUCTURED_TEXT_URI); + BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE); + BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL); + BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST); + BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE); + BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM); } Vector2 TextServer::get_hex_code_box_size(int64_t p_size, int64_t p_index) const { @@ -1533,6 +1550,83 @@ String TextServer::strip_diacritics(const String &p_string) const { return result; } +Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { + Array ret; + switch (p_parser_type) { + case STRUCTURED_TEXT_URI: { + int prev = 0; + for (int i = 0; i < p_text.length(); i++) { + if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) { + if (prev != i) { + ret.push_back(Vector2i(prev, i)); + } + ret.push_back(Vector2i(i, i + 1)); + prev = i + 1; + } + } + if (prev != p_text.length()) { + ret.push_back(Vector2i(prev, p_text.length())); + } + } break; + case STRUCTURED_TEXT_FILE: { + int prev = 0; + for (int i = 0; i < p_text.length(); i++) { + if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) { + if (prev != i) { + ret.push_back(Vector2i(prev, i)); + } + ret.push_back(Vector2i(i, i + 1)); + prev = i + 1; + } + } + if (prev != p_text.length()) { + ret.push_back(Vector2i(prev, p_text.length())); + } + } break; + case STRUCTURED_TEXT_EMAIL: { + bool local = true; + int prev = 0; + for (int i = 0; i < p_text.length(); i++) { + if ((p_text[i] == '@') && local) { // Add full "local" as single context. + local = false; + ret.push_back(Vector2i(prev, i)); + ret.push_back(Vector2i(i, i + 1)); + prev = i + 1; + } else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context. + if (prev != i) { + ret.push_back(Vector2i(prev, i)); + } + ret.push_back(Vector2i(i, i + 1)); + prev = i + 1; + } + } + if (prev != p_text.length()) { + ret.push_back(Vector2i(prev, p_text.length())); + } + } break; + case STRUCTURED_TEXT_LIST: { + if (p_args.size() == 1 && p_args[0].get_type() == Variant::STRING) { + Vector<String> tags = p_text.split(String(p_args[0])); + int prev = 0; + for (int i = 0; i < tags.size(); i++) { + if (prev != i) { + ret.push_back(Vector2i(prev, prev + tags[i].length())); + } + ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1)); + prev = prev + tags[i].length() + 1; + } + } + } break; + case STRUCTURED_TEXT_CUSTOM: + case STRUCTURED_TEXT_NONE: + case STRUCTURED_TEXT_DEFAULT: + default: { + ret.push_back(Vector2i(0, p_text.length())); + } + } + return ret; +} + Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const { Array ret; diff --git a/servers/text_server.h b/servers/text_server.h index 365b7ff663..7e7f26b32d 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -146,6 +146,16 @@ public: FONT_FIXED_WIDTH = 1 << 2, }; + enum StructuredTextParser { + STRUCTURED_TEXT_DEFAULT, + STRUCTURED_TEXT_URI, + STRUCTURED_TEXT_FILE, + STRUCTURED_TEXT_EMAIL, + STRUCTURED_TEXT_LIST, + STRUCTURED_TEXT_NONE, + STRUCTURED_TEXT_CUSTOM + }; + void _draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const; protected: @@ -191,6 +201,9 @@ public: virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0; virtual bool font_is_antialiased(const RID &p_font_rid) const = 0; + virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0; + virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0; + virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) = 0; virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const = 0; @@ -274,6 +287,8 @@ public: virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0; virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) = 0; + virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0; + virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0; virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const = 0; @@ -422,6 +437,8 @@ public: virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0; virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0; + Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const; + TextServer(); ~TextServer(); }; @@ -509,6 +526,7 @@ VARIANT_ENUM_CAST(TextServer::Feature); VARIANT_ENUM_CAST(TextServer::ContourPointTag); VARIANT_ENUM_CAST(TextServer::SpacingType); VARIANT_ENUM_CAST(TextServer::FontStyle); +VARIANT_ENUM_CAST(TextServer::StructuredTextParser); GDVIRTUAL_NATIVE_PTR(Glyph); GDVIRTUAL_NATIVE_PTR(CaretInfo); |