diff options
31 files changed, 1388 insertions, 657 deletions
diff --git a/core/vector.h b/core/vector.h index 5fb630c21c..5a61f0eae3 100644 --- a/core/vector.h +++ b/core/vector.h @@ -82,7 +82,7 @@ public: _FORCE_INLINE_ bool empty() const { return _cowdata.empty(); } _FORCE_INLINE_ T get(int p_index) { return _cowdata.get(p_index); } - _FORCE_INLINE_ const T get(int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ const T &get(int p_index) const { return _cowdata.get(p_index); } _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ int size() const { return _cowdata.size(); } Error resize(int p_size) { return _cowdata.resize(p_size); } diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml new file mode 100644 index 0000000000..f6bc9e2cca --- /dev/null +++ b/doc/classes/CodeEdit.xml @@ -0,0 +1,203 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CodeEdit" inherits="TextEdit" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="clear_bookmarked_lines"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="clear_breakpointed_lines"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="clear_executing_lines"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="get_bookmarked_lines" qualifiers="const"> + <return type="Array"> + </return> + <description> + </description> + </method> + <method name="get_breakpointed_lines" qualifiers="const"> + <return type="Array"> + </return> + <description> + </description> + </method> + <method name="get_executing_lines" qualifiers="const"> + <return type="Array"> + </return> + <description> + </description> + </method> + <method name="is_line_bookmarked" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_line_breakpointed" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_line_executing" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_line_as_bookmarked"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="bookmarked" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_line_as_breakpoint"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="breakpointed" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_line_as_executing"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="executing" type="bool"> + </argument> + <description> + </description> + </method> + </methods> + <members> + <member name="draw_bookmarks" type="bool" setter="set_draw_bookmarks_gutter" getter="is_drawing_bookmarks_gutter" default="false"> + </member> + <member name="draw_breakpoints_gutter" type="bool" setter="set_draw_breakpoints_gutter" getter="is_drawing_breakpoints_gutter" default="false"> + </member> + <member name="draw_executing_lines" type="bool" setter="set_draw_executing_lines_gutter" getter="is_drawing_executing_lines_gutter" default="false"> + </member> + <member name="draw_fold_gutter" type="bool" setter="set_draw_fold_gutter" getter="is_drawing_fold_gutter" default="false"> + </member> + <member name="draw_line_numbers" type="bool" setter="set_draw_line_numbers" getter="is_draw_line_numbers_enabled" default="false"> + </member> + <member name="zero_pad_line_numbers" type="bool" setter="set_line_numbers_zero_padded" getter="is_line_numbers_zero_padded" default="false"> + </member> + </members> + <signals> + <signal name="breakpoint_toggled"> + <argument index="0" name="line" type="int"> + </argument> + <description> + </description> + </signal> + </signals> + <constants> + </constants> + <theme_items> + <theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 0 )"> + </theme_item> + <theme_item name="bookmark" type="Texture2D"> + </theme_item> + <theme_item name="bookmark_color" type="Color" default="Color( 0.5, 0.64, 1, 0.8 )"> + </theme_item> + <theme_item name="brace_mismatch_color" type="Color" default="Color( 1, 0.2, 0.2, 1 )"> + </theme_item> + <theme_item name="breakpoint" type="Texture2D"> + </theme_item> + <theme_item name="breakpoint_color" type="Color" default="Color( 0.9, 0.29, 0.3, 1 )"> + </theme_item> + <theme_item name="can_fold" type="Texture2D"> + </theme_item> + <theme_item name="caret_background_color" type="Color" default="Color( 0, 0, 0, 1 )"> + </theme_item> + <theme_item name="caret_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> + </theme_item> + <theme_item name="code_folding_color" type="Color" default="Color( 0.8, 0.8, 0.8, 0.8 )"> + </theme_item> + <theme_item name="completion" type="StyleBox"> + </theme_item> + <theme_item name="completion_background_color" type="Color" default="Color( 0.17, 0.16, 0.2, 1 )"> + </theme_item> + <theme_item name="completion_existing_color" type="Color" default="Color( 0.87, 0.87, 0.87, 0.13 )"> + </theme_item> + <theme_item name="completion_font_color" type="Color" default="Color( 0.67, 0.67, 0.67, 1 )"> + </theme_item> + <theme_item name="completion_lines" type="int" default="7"> + </theme_item> + <theme_item name="completion_max_width" type="int" default="50"> + </theme_item> + <theme_item name="completion_scroll_color" type="Color" default="Color( 1, 1, 1, 1 )"> + </theme_item> + <theme_item name="completion_scroll_width" type="int" default="3"> + </theme_item> + <theme_item name="completion_selected_color" type="Color" default="Color( 0.26, 0.26, 0.27, 1 )"> + </theme_item> + <theme_item name="current_line_color" type="Color" default="Color( 0.25, 0.25, 0.26, 0.8 )"> + </theme_item> + <theme_item name="executing_line" type="Texture2D"> + </theme_item> + <theme_item name="executing_line_color" type="Color" default="Color( 0.98, 0.89, 0.27, 1 )"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="folded" type="Texture2D"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> + </theme_item> + <theme_item name="font_color_readonly" type="Color" default="Color( 0.88, 0.88, 0.88, 0.5 )"> + </theme_item> + <theme_item name="font_color_selected" type="Color" default="Color( 0, 0, 0, 1 )"> + </theme_item> + <theme_item name="line_number_color" type="Color" default="Color( 0.67, 0.67, 0.67, 0.4 )"> + </theme_item> + <theme_item name="line_spacing" type="int" default="4"> + </theme_item> + <theme_item name="mark_color" type="Color" default="Color( 1, 0.4, 0.4, 0.4 )"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + <theme_item name="read_only" type="StyleBox"> + </theme_item> + <theme_item name="safe_line_number_color" type="Color" default="Color( 0.67, 0.78, 0.67, 0.6 )"> + </theme_item> + <theme_item name="selection_color" type="Color" default="Color( 0.49, 0.49, 0.49, 1 )"> + </theme_item> + <theme_item name="space" type="Texture2D"> + </theme_item> + <theme_item name="tab" type="Texture2D"> + </theme_item> + <theme_item name="word_highlighted_color" type="Color" default="Color( 0.8, 0.9, 0.9, 0.15 )"> + </theme_item> + </theme_items> +</class> diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index 3fc9e73ccf..8444610f49 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -18,6 +18,22 @@ Returns the axis-aligned bounding box that contains all the particles that are active in the current frame. </description> </method> + <method name="emit_particle"> + <return type="void"> + </return> + <argument index="0" name="xform" type="Transform"> + </argument> + <argument index="1" name="velocity" type="Vector3"> + </argument> + <argument index="2" name="color" type="Color"> + </argument> + <argument index="3" name="custom" type="Color"> + </argument> + <argument index="4" name="flags" type="int"> + </argument> + <description> + </description> + </method> <method name="get_draw_pass_mesh" qualifiers="const"> <return type="Mesh"> </return> @@ -101,6 +117,8 @@ <member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0"> Speed scaling ratio. A value of [code]0[/code] can be used to pause the particles. </member> + <member name="sub_emitter" type="NodePath" setter="set_sub_emitter" getter="get_sub_emitter" default="NodePath("")"> + </member> <member name="visibility_aabb" type="AABB" setter="set_visibility_aabb" getter="get_visibility_aabb" default="AABB( -4, -4, -4, 8, 8, 8 )"> The [AABB] that determines the area of the world part of which needs to be visible on screen for the particle system to be active. </member> @@ -115,6 +133,16 @@ <constant name="DRAW_ORDER_VIEW_DEPTH" value="2" enum="DrawOrder"> Particles are drawn in order of depth. </constant> + <constant name="EMIT_FLAG_POSITION" value="1" enum="EmitFlags"> + </constant> + <constant name="EMIT_FLAG_ROTATION_SCALE" value="2" enum="EmitFlags"> + </constant> + <constant name="EMIT_FLAG_VELOCITY" value="4" enum="EmitFlags"> + </constant> + <constant name="EMIT_FLAG_COLOR" value="8" enum="EmitFlags"> + </constant> + <constant name="EMIT_FLAG_CUSTOM" value="16" enum="EmitFlags"> + </constant> <constant name="MAX_DRAW_PASSES" value="4"> Maximum number of draw passes supported. </constant> diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index 2ba2249d21..dc88c53810 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -135,7 +135,7 @@ </argument> <argument index="3" name="method" type="int" enum="HTTPClient.Method" default="0"> </argument> - <argument index="4" name="request_data_raw" type="PackedByteArray" default="PackedByteArray()"> + <argument index="4" name="request_data_raw" type="PackedByteArray" default="PackedByteArray( )"> </argument> <description> Creates request on the underlying [HTTPClient] using a raw array of bytes for the request body. If there is no configuration errors, it tries to connect using [method HTTPClient.connect_to_host] and passes parameters onto [method HTTPClient.request]. @@ -144,6 +144,12 @@ </method> </methods> <members> + <member name="accept_gzip" type="bool" setter="set_accept_gzip" getter="is_accepting_gzip" default="true"> + If [code]true[/code], this header will be added to each request: [code]Accept-Encoding: gzip, deflate[/code] telling servers that it's okay to compress response bodies. + Any Reponse body declaring a [code]Content-Encoding[/code] of either [code]gzip[/code] or [code]deflate[/code] will then be automatically decompressed, and the uncompressed bytes will be delivered via [code]request_completed[/code]. + If the user has specified their own [code]Accept-Encoding[/code] header, then no header will be added regaurdless of [code]accept_gzip[/code]. + If [code]false[/code] no header will be added, and no decompression will be performed on response bodies. The raw bytes of the response body will be returned via [code]request_completed[/code]. + </member> <member name="body_size_limit" type="int" setter="set_body_size_limit" getter="get_body_size_limit" default="-1"> Maximum allowed size for response bodies. If the response body is compressed, this will be used as the maximum allowed size for the decompressed body. </member> @@ -162,12 +168,6 @@ <member name="use_threads" type="bool" setter="set_use_threads" getter="is_using_threads" default="false"> If [code]true[/code], multithreading is used to improve performance. </member> - <member name="accept_gzip" type="bool" setter="set_accept_gzip" getter="is_accepting_gzip" default="true"> - If [code]true[/code], this header will be added to each request: [code]Accept-Encoding: gzip, deflate[/code] telling servers that it's okay to compress response bodies. - Any Reponse body declaring a [code]Content-Encoding[/code] of either [code]gzip[/code] or [code]deflate[/code] will then be automatically decompressed, and the uncompressed bytes will be delivered via [code]request_completed[/code]. - If the user has specified their own [code]Accept-Encoding[/code] header, then no header will be added regaurdless of [code]accept_gzip[/code]. - If [code]false[/code] no header will be added, and no decompression will be performed on response bodies. The raw bytes of the response body will be returned via [code]request_completed[/code]. - </member> </members> <signals> <signal name="request_completed"> @@ -208,19 +208,21 @@ <constant name="RESULT_BODY_SIZE_LIMIT_EXCEEDED" value="7" enum="Result"> Request exceeded its maximum size limit, see [member body_size_limit]. </constant> - <constant name="RESULT_REQUEST_FAILED" value="8" enum="Result"> + <constant name="RESULT_BODY_DECOMPRESS_FAILED" value="8" enum="Result"> + </constant> + <constant name="RESULT_REQUEST_FAILED" value="9" enum="Result"> Request failed (currently unused). </constant> - <constant name="RESULT_DOWNLOAD_FILE_CANT_OPEN" value="9" enum="Result"> + <constant name="RESULT_DOWNLOAD_FILE_CANT_OPEN" value="10" enum="Result"> HTTPRequest couldn't open the download file. </constant> - <constant name="RESULT_DOWNLOAD_FILE_WRITE_ERROR" value="10" enum="Result"> + <constant name="RESULT_DOWNLOAD_FILE_WRITE_ERROR" value="11" enum="Result"> HTTPRequest couldn't write to the download file. </constant> - <constant name="RESULT_REDIRECT_LIMIT_REACHED" value="11" enum="Result"> + <constant name="RESULT_REDIRECT_LIMIT_REACHED" value="12" enum="Result"> Request reached its maximum redirect limit, see [member max_redirects]. </constant> - <constant name="RESULT_TIMEOUT" value="12" enum="Result"> + <constant name="RESULT_TIMEOUT" value="13" enum="Result"> </constant> </constants> </class> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 5aa5de1dae..20be20db34 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -233,7 +233,7 @@ <return type="PackedByteArray"> </return> <description> - Returns the image's raw data. + Returns a copy of the image's raw data. </description> </method> <method name="get_format" qualifiers="const"> diff --git a/doc/classes/ImageTexture3D.xml b/doc/classes/ImageTexture3D.xml new file mode 100644 index 0000000000..d05082487d --- /dev/null +++ b/doc/classes/ImageTexture3D.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ImageTexture3D" inherits="Texture3D" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="create"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="format" type="int" enum="Image.Format"> + </argument> + <argument index="1" name="width" type="int"> + </argument> + <argument index="2" name="height" type="int"> + </argument> + <argument index="3" name="depth" type="int"> + </argument> + <argument index="4" name="use_mipmaps" type="bool"> + </argument> + <argument index="5" name="data" type="Image[]"> + </argument> + <description> + </description> + </method> + <method name="update"> + <return type="void"> + </return> + <argument index="0" name="data" type="Image[]"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index 7bfc502fbb..0fcfed0595 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -60,7 +60,7 @@ <method name="decompress_dynamic"> <return type="PackedByteArray"> </return> - <argument index="0" name="max_output_size" type="int" default="0"> + <argument index="0" name="max_output_size" type="int"> </argument> <argument index="1" name="compression_mode" type="int" default="0"> </argument> diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index d04ac5bdce..f6fa3cf38b 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -243,6 +243,14 @@ <member name="spread" type="float" setter="set_spread" getter="get_spread" default="45.0"> Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees. Applied to X/Z plane and Y/Z planes. </member> + <member name="sub_emitter_amount_at_end" type="int" setter="set_sub_emitter_amount_at_end" getter="get_sub_emitter_amount_at_end"> + </member> + <member name="sub_emitter_frequency" type="float" setter="set_sub_emitter_frequency" getter="get_sub_emitter_frequency"> + </member> + <member name="sub_emitter_keep_velocity" type="bool" setter="set_sub_emitter_keep_velocity" getter="get_sub_emitter_keep_velocity" default="false"> + </member> + <member name="sub_emitter_mode" type="int" setter="set_sub_emitter_mode" getter="get_sub_emitter_mode" enum="ParticlesMaterial.SubEmitterMode" default="0"> + </member> <member name="tangential_accel" type="float" setter="set_param" getter="get_param" default="0.0"> Tangential acceleration applied to each particle. Tangential acceleration is perpendicular to the particle's velocity giving the particles a swirling motion. </member> @@ -252,15 +260,6 @@ <member name="tangential_accel_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0"> Tangential acceleration randomness ratio. </member> - <member name="trail_color_modifier" type="GradientTexture" setter="set_trail_color_modifier" getter="get_trail_color_modifier"> - Trail particles' color will vary along this [GradientTexture]. - </member> - <member name="trail_divisor" type="int" setter="set_trail_divisor" getter="get_trail_divisor" default="1"> - Emitter will emit [code]amount[/code] divided by [code]trail_divisor[/code] particles. The remaining particles will be used as trail(s). - </member> - <member name="trail_size_modifier" type="CurveTexture" setter="set_trail_size_modifier" getter="get_trail_size_modifier"> - Trail particles' size will vary along this [CurveTexture]. - </member> </members> <constants> <constant name="PARAM_INITIAL_LINEAR_VELOCITY" value="0" enum="Parameter"> @@ -332,5 +331,15 @@ <constant name="EMISSION_SHAPE_MAX" value="5" enum="EmissionShape"> Represents the size of the [enum EmissionShape] enum. </constant> + <constant name="SUB_EMITTER_DISABLED" value="0" enum="SubEmitterMode"> + </constant> + <constant name="SUB_EMITTER_CONSTANT" value="1" enum="SubEmitterMode"> + </constant> + <constant name="SUB_EMITTER_AT_END" value="2" enum="SubEmitterMode"> + </constant> + <constant name="SUB_EMITTER_AT_COLLISION" value="3" enum="SubEmitterMode"> + </constant> + <constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode"> + </constant> </constants> </class> diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml index 5fc5b09833..e30d7df63f 100644 --- a/doc/classes/RayCast2D.xml +++ b/doc/classes/RayCast2D.xml @@ -123,9 +123,6 @@ </method> </methods> <members> - <member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2( 0, 50 )"> - The ray's destination point, relative to the RayCast's [code]position[/code]. - </member> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> If [code]true[/code], collision with [Area2D]s will be reported. </member> @@ -141,6 +138,9 @@ <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> If [code]true[/code], the parent node will be excluded from collision detection. </member> + <member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2( 0, 50 )"> + The ray's destination point, relative to the RayCast's [code]position[/code]. + </member> </members> <constants> </constants> diff --git a/doc/classes/RayCast3D.xml b/doc/classes/RayCast3D.xml index d8bff65bff..1d8edf0adb 100644 --- a/doc/classes/RayCast3D.xml +++ b/doc/classes/RayCast3D.xml @@ -126,9 +126,6 @@ </method> </methods> <members> - <member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3( 0, -1, 0 )"> - The ray's destination point, relative to the RayCast's [code]position[/code]. - </member> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> If [code]true[/code], collision with [Area3D]s will be reported. </member> @@ -144,6 +141,9 @@ <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> If [code]true[/code], collisions will be ignored for this RayCast3D's immediate parent. </member> + <member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3( 0, -1, 0 )"> + The ray's destination point, relative to the RayCast's [code]position[/code]. + </member> </members> <constants> </constants> diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml index f7c9be7900..1c7d84c5a2 100644 --- a/doc/classes/SpriteFrames.xml +++ b/doc/classes/SpriteFrames.xml @@ -54,7 +54,7 @@ <argument index="0" name="anim" type="StringName"> </argument> <description> - Returns [code]true[/code] if the given animation is configured to loop when it finishes playing. Otherwise, returns [code]false[/code]. + Returns [code]true[/code] if the given animation is configured to loop when it finishes playing. Otherwise, returns [code]false[/code]. </description> </method> <method name="get_animation_names" qualifiers="const"> diff --git a/doc/classes/StreamTexture3D.xml b/doc/classes/StreamTexture3D.xml new file mode 100644 index 0000000000..7054a4ee99 --- /dev/null +++ b/doc/classes/StreamTexture3D.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="StreamTexture3D" inherits="Texture3D" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="load"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <description> + </description> + </method> + </methods> + <members> + <member name="load_path" type="String" setter="load" getter="get_load_path" default=""""> + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index ccc99dc8e3..a23a4936f8 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -9,6 +9,14 @@ <tutorials> </tutorials> <methods> + <method name="add_gutter"> + <return type="void"> + </return> + <argument index="0" name="at" type="int" default="-1"> + </argument> + <description> + </description> + </method> <method name="can_fold" qualifiers="const"> <return type="bool"> </return> @@ -112,11 +120,34 @@ Folds the given line, if possible (see [method can_fold]). </description> </method> - <method name="get_breakpoints" qualifiers="const"> - <return type="Array"> + <method name="get_gutter_count" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_gutter_name" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_gutter_type" qualifiers="const"> + <return type="int" enum="TextEdit.GutterType"> </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_gutter_width" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> <description> - Returns an array containing the line number of each breakpoint. </description> </method> <method name="get_line" qualifiers="const"> @@ -135,6 +166,46 @@ Returns the amount of total lines in the text. </description> </method> + <method name="get_line_gutter_icon" qualifiers="const"> + <return type="Texture2D"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_line_gutter_item_color"> + <return type="Color"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_line_gutter_metadata" qualifiers="const"> + <return type="Variant"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_line_gutter_text" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> <method name="get_menu" qualifiers="const"> <return type="PopupMenu"> </return> @@ -202,6 +273,40 @@ Returns whether the line at the specified index is folded or not. </description> </method> + <method name="is_gutter_clickable" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_gutter_drawn" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_gutter_overwritable" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_line_gutter_clickable" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> <method name="is_line_hidden" qualifiers="const"> <return type="bool"> </return> @@ -241,11 +346,12 @@ Perform redo operation. </description> </method> - <method name="remove_breakpoints"> + <method name="remove_gutter"> <return type="void"> </return> + <argument index="0" name="gutter" type="int"> + </argument> <description> - Removes all the breakpoints. This will not fire the [signal breakpoint_toggled] signal. </description> </method> <method name="search" qualifiers="const"> @@ -295,6 +401,78 @@ If [member selecting_enabled] is [code]false[/code], no selection will occur. </description> </method> + <method name="set_gutter_clickable"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="clickable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_custom_draw"> + <return type="void"> + </return> + <argument index="0" name="column" type="int"> + </argument> + <argument index="1" name="object" type="Object"> + </argument> + <argument index="2" name="callback" type="StringName"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_draw"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="draw" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_name"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="name" type="String"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_overwritable"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="overwritable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_type"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="type" type="int" enum="TextEdit.GutterType"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_width"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="width" type="int"> + </argument> + <description> + </description> + </method> <method name="set_line"> <return type="void"> </return> @@ -317,6 +495,66 @@ If [code]true[/code], hides the line of the specified index. </description> </method> + <method name="set_line_gutter_clickable"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="clickable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_line_gutter_icon"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="icon" type="Texture2D"> + </argument> + <description> + </description> + </method> + <method name="set_line_gutter_item_color"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="set_line_gutter_metadata"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="metadata" type="Variant"> + </argument> + <description> + </description> + </method> + <method name="set_line_gutter_text"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="text" type="String"> + </argument> + <description> + </description> + </method> <method name="toggle_fold_line"> <return type="void"> </return> @@ -351,9 +589,6 @@ </method> </methods> <members> - <member name="breakpoint_gutter" type="bool" setter="set_breakpoint_gutter_enabled" getter="is_breakpoint_gutter_enabled" default="false"> - If [code]true[/code], the breakpoint gutter is visible. - </member> <member name="caret_blink" type="bool" setter="cursor_set_blink_enabled" getter="cursor_get_blink_enabled" default="false"> If [code]true[/code], the caret (visual cursor) blinks. </member> @@ -378,9 +613,6 @@ If [code]true[/code], the "tab" character will have a visible representation. </member> <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" /> - <member name="fold_gutter" type="bool" setter="set_draw_fold_gutter" getter="is_drawing_fold_gutter" default="false"> - If [code]true[/code], the fold gutter is visible. This enables folding groups of indented lines. - </member> <member name="hiding_enabled" type="bool" setter="set_hiding_enabled" getter="is_hiding_enabled" default="false"> If [code]true[/code], all lines that have been set to hidden by [method set_line_as_hidden], will not be visible. </member> @@ -416,9 +648,6 @@ <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="show_line_numbers" type="bool" setter="set_show_line_numbers" getter="is_show_line_numbers_enabled" default="false"> - If [code]true[/code], line numbers are displayed to the left of the text. - </member> <member name="smooth_scrolling" type="bool" setter="set_smooth_scroll_enable" getter="is_smooth_scroll_enabled" default="false"> If [code]true[/code], sets the [code]step[/code] of the scrollbars to [code]0.25[/code] which results in smoother scrolling. </member> @@ -438,29 +667,31 @@ </member> </members> <signals> - <signal name="breakpoint_toggled"> - <argument index="0" name="row" type="int"> - </argument> + <signal name="cursor_changed"> <description> - Emitted when a breakpoint is placed via the breakpoint gutter. + Emitted when the cursor changes. </description> </signal> - <signal name="cursor_changed"> + <signal name="gutter_added"> <description> - Emitted when the cursor changes. </description> </signal> - <signal name="info_clicked"> - <argument index="0" name="row" type="int"> + <signal name="gutter_clicked"> + <argument index="0" name="line" type="int"> </argument> - <argument index="1" name="info" type="String"> + <argument index="1" name="gutter" type="int"> </argument> <description> - Emitted when the info icon is clicked. </description> </signal> - <signal name="line_edited_from"> - <argument index="0" name="line" type="int"> + <signal name="gutter_removed"> + <description> + </description> + </signal> + <signal name="lines_edited_from"> + <argument index="0" name="from_line" type="int"> + </argument> + <argument index="1" name="to_line" type="int"> </argument> <description> </description> @@ -501,6 +732,12 @@ <constant name="SEARCH_BACKWARDS" value="4" enum="SearchFlags"> Search from end to beginning. </constant> + <constant name="GUTTER_TYPE_STRING" value="0" enum="GutterType"> + </constant> + <constant name="GUTTER_TPYE_ICON" value="1" enum="GutterType"> + </constant> + <constant name="GUTTER_TPYE_CUSTOM" value="2" enum="GutterType"> + </constant> <constant name="MENU_CUT" value="0" enum="MenuItems"> Cuts (copies and clears) the selected text. </constant> @@ -530,14 +767,8 @@ <theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 0 )"> Sets the background [Color] of this [TextEdit]. [member syntax_highlighting] has to be enabled. </theme_item> - <theme_item name="bookmark_color" type="Color" default="Color( 0.08, 0.49, 0.98, 1 )"> - Sets the [Color] of the bookmark marker. [member syntax_highlighting] has to be enabled. - </theme_item> <theme_item name="brace_mismatch_color" type="Color" default="Color( 1, 0.2, 0.2, 1 )"> </theme_item> - <theme_item name="breakpoint_color" type="Color" default="Color( 0.8, 0.8, 0.4, 0.2 )"> - Sets the [Color] of the breakpoints. [member breakpoint_gutter] has to be enabled. - </theme_item> <theme_item name="caret_background_color" type="Color" default="Color( 0, 0, 0, 1 )"> </theme_item> <theme_item name="caret_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> @@ -565,14 +796,8 @@ <theme_item name="current_line_color" type="Color" default="Color( 0.25, 0.25, 0.26, 0.8 )"> Sets the [Color] of the breakpoints. [member breakpoint_gutter] has to be enabled. </theme_item> - <theme_item name="executing_line_color" type="Color" default="Color( 0.2, 0.8, 0.2, 0.4 )"> - </theme_item> <theme_item name="focus" type="StyleBox"> </theme_item> - <theme_item name="fold" type="Texture2D"> - </theme_item> - <theme_item name="folded" type="Texture2D"> - </theme_item> <theme_item name="font" type="Font"> Sets the default [Font]. </theme_item> @@ -584,9 +809,6 @@ <theme_item name="font_color_selected" type="Color" default="Color( 0, 0, 0, 1 )"> Sets the [Color] of the selected text. [member override_selected_font_color] has to be enabled. </theme_item> - <theme_item name="line_number_color" type="Color" default="Color( 0.67, 0.67, 0.67, 0.4 )"> - Sets the [Color] of the line numbers. [member show_line_numbers] has to be enabled. - </theme_item> <theme_item name="line_spacing" type="int" default="4"> Sets the spacing between the lines. </theme_item> @@ -599,8 +821,6 @@ <theme_item name="read_only" type="StyleBox"> Sets the [StyleBox] of this [TextEdit] when [member readonly] is enabled. </theme_item> - <theme_item name="safe_line_number_color" type="Color" default="Color( 0.67, 0.78, 0.67, 0.6 )"> - </theme_item> <theme_item name="selection_color" type="Color" default="Color( 0.49, 0.49, 0.49, 1 )"> Sets the highlight [Color] of text selections. </theme_item> diff --git a/doc/classes/VisualShader.xml b/doc/classes/VisualShader.xml index 12954beb43..f03550bd5e 100644 --- a/doc/classes/VisualShader.xml +++ b/doc/classes/VisualShader.xml @@ -209,10 +209,13 @@ <constant name="TYPE_LIGHT" value="2" enum="Type"> A shader for light calculations. </constant> - <constant name="TYPE_COMPUTE" value="3" enum="Type"> - A compute shader, to use the GPU for abstract computation. + <constant name="TYPE_EMIT" value="3" enum="Type"> </constant> - <constant name="TYPE_MAX" value="4" enum="Type"> + <constant name="TYPE_PROCESS" value="4" enum="Type"> + </constant> + <constant name="TYPE_END" value="5" enum="Type"> + </constant> + <constant name="TYPE_MAX" value="6" enum="Type"> Represents the size of the [enum Type] enum. </constant> <constant name="NODE_ID_INVALID" value="-1"> diff --git a/doc/classes/VisualShaderNode.xml b/doc/classes/VisualShaderNode.xml index 6327ab534f..3bb527f3d4 100644 --- a/doc/classes/VisualShaderNode.xml +++ b/doc/classes/VisualShaderNode.xml @@ -57,6 +57,12 @@ Emitted when the node requests an editor refresh. Currently called only in setter of [member VisualShaderNodeTexture.source], [VisualShaderNodeTexture], and [VisualShaderNodeCubemap] (and their derivatives). </description> </signal> + <signal name="show_port_preview"> + <argument index="0" name="port_id" type="int"> + </argument> + <description> + </description> + </signal> </signals> <constants> <constant name="PORT_TYPE_SCALAR" value="0" enum="PortType"> diff --git a/editor/editor_builders.py b/editor/editor_builders.py index ea32e24f6e..86c5c87a68 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -54,7 +54,6 @@ def make_fonts_header(target, source, env): g.write("#define _EDITOR_FONTS_H\n") # saving uncompressed, since freetype will reference from memory pointer - xl_names = [] for i in range(len(source)): with open(source[i], "rb") as f: buf = f.read() diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index adca639896..62eb06874c 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -60,25 +60,50 @@ void VisualShaderNodePlugin::_bind_methods() { /////////////////// +static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { + Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); + style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE); + style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE); + style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE); + style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE); + return style; +} + +/////////////////// + VisualShaderGraphPlugin::VisualShaderGraphPlugin() { } void VisualShaderGraphPlugin::_bind_methods() { + ClassDB::bind_method("add_node", &VisualShaderGraphPlugin::add_node); + ClassDB::bind_method("remove_node", &VisualShaderGraphPlugin::remove_node); + ClassDB::bind_method("connect_nodes", &VisualShaderGraphPlugin::connect_nodes); + ClassDB::bind_method("disconnect_nodes", &VisualShaderGraphPlugin::disconnect_nodes); + ClassDB::bind_method("set_node_position", &VisualShaderGraphPlugin::set_node_position); + ClassDB::bind_method("set_node_size", &VisualShaderGraphPlugin::set_node_size); ClassDB::bind_method("show_port_preview", &VisualShaderGraphPlugin::show_port_preview); + ClassDB::bind_method("update_property_editor", &VisualShaderGraphPlugin::update_property_editor); + ClassDB::bind_method("update_property_editor_deferred", &VisualShaderGraphPlugin::update_property_editor_deferred); + ClassDB::bind_method("set_input_port_default_value", &VisualShaderGraphPlugin::set_input_port_default_value); } void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) { visual_shader = Ref<VisualShader>(p_shader); } -void VisualShaderGraphPlugin::show_port_preview(int p_port_id, int p_node_id) { - if (links.has(p_node_id) && links[p_node_id].type == visual_shader->get_shader_type()) { +void VisualShaderGraphPlugin::set_connections(List<VisualShader::Connection> &p_connections) { + connections = p_connections; +} + +void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id) { + if (visual_shader->get_shader_type() == p_type && links.has(p_node_id)) { for (Map<int, Port>::Element *E = links[p_node_id].output_ports.front(); E; E = E->next()) { E->value().preview_button->set_pressed(false); } - if (links[p_node_id].preview_visible && !is_dirty()) { + if (links[p_node_id].preview_visible && !is_dirty() && links[p_node_id].preview_box != nullptr) { links[p_node_id].graph_node->remove_child(links[p_node_id].preview_box); + memdelete(links[p_node_id].preview_box); links[p_node_id].graph_node->set_size(Vector2(-1, -1)); links[p_node_id].preview_visible = false; } @@ -109,6 +134,102 @@ void VisualShaderGraphPlugin::show_port_preview(int p_port_id, int p_node_id) { } } +void VisualShaderGraphPlugin::update_property_editor_deferred(VisualShader::Type p_type, int p_node_id) { + call_deferred("update_property_editor", p_type, p_node_id); +} + +void VisualShaderGraphPlugin::update_property_editor(VisualShader::Type p_type, int p_node_id) { + if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id)) { + return; + } + Control *custom_editor = links[p_node_id].custom_editor; + if (custom_editor != nullptr) { + links[p_node_id].graph_node->remove_child(custom_editor); + memdelete(custom_editor); + custom_editor = nullptr; + } + + links[p_node_id].visual_node->set_meta("id", p_node_id); + links[p_node_id].visual_node->set_meta("shader_type", (int)p_type); + + for (int i = 0; i < VisualShaderEditor::get_singleton()->plugins.size(); i++) { + custom_editor = VisualShaderEditor::get_singleton()->plugins.write[i]->create_editor(visual_shader, links[p_node_id].visual_node); + if (custom_editor) { + break; + } + } + links[p_node_id].visual_node->remove_meta("id"); + links[p_node_id].visual_node->remove_meta("shader_type"); + links[p_node_id].custom_editor = custom_editor; + if (custom_editor) { + links[p_node_id].graph_node->add_child(custom_editor); + links[p_node_id].graph_node->move_child(custom_editor, links[p_node_id].editor_pos); + + Ref<VisualShaderNode> vsnode = Ref<VisualShaderNode>(links[p_node_id].visual_node); + Ref<VisualShaderNodeFloatUniform> float_uniform = vsnode; + Ref<VisualShaderNodeIntUniform> int_uniform = vsnode; + Ref<VisualShaderNodeVec3Uniform> vec3_uniform = vsnode; + Ref<VisualShaderNodeColorUniform> color_uniform = vsnode; + Ref<VisualShaderNodeBooleanUniform> bool_uniform = vsnode; + Ref<VisualShaderNodeTransformUniform> transform_uniform = vsnode; + + if (float_uniform.is_valid() || int_uniform.is_valid() || vec3_uniform.is_valid() || color_uniform.is_valid() || bool_uniform.is_valid() || transform_uniform.is_valid()) { + custom_editor->call_deferred("_show_prop_names", true); + } + } + links[p_node_id].graph_node->set_size(Vector2(-1, -1)); +} + +void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, Variant p_value) { + if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id)) { + return; + } + + Button *button = links[p_node_id].input_ports[p_port_id].default_input_button; + + switch (p_value.get_type()) { + case Variant::COLOR: { + button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); + if (!button->is_connected("draw", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_draw_color_over_button))) { + button->connect("draw", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_draw_color_over_button), varray(button, p_value)); + } + } break; + case Variant::BOOL: { + button->set_text(((bool)p_value) ? "true" : "false"); + } break; + case Variant::INT: + case Variant::FLOAT: { + button->set_text(String::num(p_value, 4)); + } break; + case Variant::VECTOR3: { + Vector3 v = p_value; + button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3)); + } break; + default: { + } + } +} + +void VisualShaderGraphPlugin::register_default_input_button(int p_node_id, int p_port_id, Button *p_button) { + links[p_node_id].input_ports.insert(p_port_id, { p_button }); +} + +VisualShader::Type VisualShaderGraphPlugin::get_shader_type() const { + return visual_shader->get_shader_type(); +} + +void VisualShaderGraphPlugin::set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + links[p_id].graph_node->set_offset(p_position); + } +} + +void VisualShaderGraphPlugin::set_node_size(VisualShader::Type p_type, int p_id, const Vector2 &p_size) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + links[p_id].graph_node->set_size(p_size); + } +} + bool VisualShaderGraphPlugin::is_preview_visible(int p_id) const { return links[p_id].preview_visible; } @@ -126,17 +247,422 @@ void VisualShaderGraphPlugin::make_dirty(bool p_enabled) { } void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) { - links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, Port>(), nullptr }); - - if (!p_visual_node->is_connected("show_port_preview", callable_mp(this, &VisualShaderGraphPlugin::show_port_preview))) { - p_visual_node->connect("show_port_preview", callable_mp(this, &VisualShaderGraphPlugin::show_port_preview), varray(p_id), CONNECT_DEFERRED); - } + links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, -1 }); } void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) { links[p_node_id].output_ports.insert(p_port, { p_button }); } +void VisualShaderGraphPlugin::register_custom_editor(int p_node_id, Control *p_custom_editor) { + links[p_node_id].custom_editor = p_custom_editor; +} + +void VisualShaderGraphPlugin::register_editor_pos(int p_node_id, int p_pos) { + links[p_node_id].editor_pos = p_pos; +} + +void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { + if (p_type != visual_shader->get_shader_type()) { + return; + } + + Control *offset; + + static Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); + + static const Color type_color[6] = { + Color(0.38, 0.85, 0.96), // scalar (float) + Color(0.49, 0.78, 0.94), // scalar (int) + Color(0.84, 0.49, 0.93), // vector + Color(0.55, 0.65, 0.94), // boolean + Color(0.96, 0.66, 0.43), // transform + Color(1.0, 1.0, 0.0), // sampler + }; + + Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id); + + Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr()); + bool is_group = !group_node.is_null(); + Size2 size = Size2(0, 0); + + Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr()); + bool is_expression = !expression_node.is_null(); + String expression = ""; + + GraphNode *node = memnew(GraphNode); + register_link(p_type, p_id, vsnode.ptr(), node); + + if (is_group) { + size = group_node->get_size(); + + node->set_resizable(true); + node->connect("resize_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_resized), varray((int)p_type, p_id)); + } + if (is_expression) { + expression = expression_node->get_expression(); + } + + node->set_offset(visual_shader->get_node_position(p_type, p_id)); + node->set_title(vsnode->get_caption()); + node->set_name(itos(p_id)); + + if (p_id >= 2) { + node->set_show_close_button(true); + node->connect("close_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_delete_request), varray(p_id), CONNECT_DEFERRED); + } + + node->connect("dragged", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_dragged), varray(p_id)); + + Control *custom_editor = nullptr; + int port_offset = 0; + + if (is_group) { + port_offset += 2; + } + + Ref<VisualShaderNodeUniform> uniform = vsnode; + + if (uniform.is_valid()) { + VisualShaderEditor::get_singleton()->call_deferred("_update_uniforms"); + } + + Ref<VisualShaderNodeFloatUniform> float_uniform = vsnode; + Ref<VisualShaderNodeIntUniform> int_uniform = vsnode; + Ref<VisualShaderNodeVec3Uniform> vec3_uniform = vsnode; + Ref<VisualShaderNodeColorUniform> color_uniform = vsnode; + Ref<VisualShaderNodeBooleanUniform> bool_uniform = vsnode; + Ref<VisualShaderNodeTransformUniform> transform_uniform = vsnode; + if (uniform.is_valid()) { + VisualShaderEditor::get_singleton()->graph->add_child(node); + VisualShaderEditor::get_singleton()->_update_created_node(node); + + LineEdit *uniform_name = memnew(LineEdit); + uniform_name->set_text(uniform->get_uniform_name()); + node->add_child(uniform_name); + uniform_name->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_line_edit_changed), varray(uniform_name, p_id)); + uniform_name->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_line_edit_focus_out), varray(uniform_name, p_id)); + + String error = vsnode->get_warning(visual_shader->get_mode(), p_type); + if (error != String()) { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); + node->add_child(offset); + Label *error_label = memnew(Label); + error_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("error_color", "Editor")); + error_label->set_text(error); + node->add_child(error_label); + } + + if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") { + //shortcut + VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); + node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); + if (!float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !color_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid()) { + return; + } + } + port_offset++; + } + + for (int i = 0; i < VisualShaderEditor::get_singleton()->plugins.size(); i++) { + vsnode->set_meta("id", p_id); + vsnode->set_meta("shader_type", (int)p_type); + custom_editor = VisualShaderEditor::get_singleton()->plugins.write[i]->create_editor(visual_shader, vsnode); + vsnode->remove_meta("id"); + vsnode->remove_meta("shader_type"); + if (custom_editor) { + break; + } + } + + if (custom_editor && !float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid() && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { + //will be embedded in first port + } else if (custom_editor) { + register_editor_pos(p_id, port_offset); + port_offset++; + node->add_child(custom_editor); + register_custom_editor(p_id, custom_editor); + if (color_uniform.is_valid()) { + custom_editor->call_deferred("_show_prop_names", true); + } + if (float_uniform.is_valid() || int_uniform.is_valid() || vec3_uniform.is_valid() || bool_uniform.is_valid() || transform_uniform.is_valid()) { + custom_editor->call_deferred("_show_prop_names", true); + return; + } + custom_editor = nullptr; + } + + if (is_group) { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE)); + node->add_child(offset); + + if (group_node->is_editable()) { + HBoxContainer *hb2 = memnew(HBoxContainer); + + Button *add_input_btn = memnew(Button); + add_input_btn->set_text(TTR("Add Input")); + add_input_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_add_input_port), varray(p_id, group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED); + hb2->add_child(add_input_btn); + + hb2->add_spacer(); + + Button *add_output_btn = memnew(Button); + add_output_btn->set_text(TTR("Add Output")); + add_output_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_add_output_port), varray(p_id, group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED); + hb2->add_child(add_output_btn); + + node->add_child(hb2); + } + } + + for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) { + if (vsnode->is_port_separator(i)) { + node->add_child(memnew(HSeparator)); + port_offset++; + } + + bool valid_left = i < vsnode->get_input_port_count(); + VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR; + bool port_left_used = false; + String name_left; + if (valid_left) { + name_left = vsnode->get_input_port_name(i); + port_left = vsnode->get_input_port_type(i); + for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { + if (E->get().to_node == p_id && E->get().to_port == i) { + port_left_used = true; + } + } + } + + bool valid_right = i < vsnode->get_output_port_count(); + VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR; + String name_right; + if (valid_right) { + name_right = vsnode->get_output_port_name(i); + port_right = vsnode->get_output_port_type(i); + } + + HBoxContainer *hb = memnew(HBoxContainer); + hb->add_theme_constant_override("separation", 7 * EDSCALE); + + Variant default_value; + + if (valid_left && !port_left_used) { + default_value = vsnode->get_input_port_default_value(i); + } + + if (default_value.get_type() != Variant::NIL) { // only a label + Button *button = memnew(Button); + hb->add_child(button); + button->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_edit_port_default_input), varray(button, p_id, i)); + register_default_input_button(p_id, i, button); + set_input_port_default_value(p_type, p_id, i, default_value); + } + + if (i == 0 && custom_editor) { + hb->add_child(custom_editor); + custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + } else { + if (valid_left) { + if (is_group) { + OptionButton *type_box = memnew(OptionButton); + hb->add_child(type_box); + type_box->add_item(TTR("Float")); + type_box->add_item(TTR("Int")); + type_box->add_item(TTR("Vector")); + type_box->add_item(TTR("Boolean")); + type_box->add_item(TTR("Transform")); + type_box->add_item(TTR("Sampler")); + type_box->select(group_node->get_input_port_type(i)); + type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + type_box->connect("item_selected", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_input_port_type), varray(p_id, i), CONNECT_DEFERRED); + + LineEdit *name_box = memnew(LineEdit); + hb->add_child(name_box); + name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); + name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + name_box->set_text(name_left); + name_box->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_input_port_name), varray(name_box, p_id, i)); + name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, false)); + + Button *remove_btn = memnew(Button); + remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); + remove_btn->set_tooltip(TTR("Remove") + " " + name_left); + remove_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_remove_input_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(remove_btn); + } else { + Label *label = memnew(Label); + label->set_text(name_left); + label->add_theme_style_override("normal", label_style); //more compact + hb->add_child(label); + + if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) { + Label *hint_label = memnew(Label); + hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]"); + hint_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("font_color_readonly", "TextEdit")); + hint_label->add_theme_style_override("normal", label_style); + hb->add_child(hint_label); + } + } + } + + if (!is_group) { + hb->add_spacer(); + } + + if (valid_right) { + if (is_group) { + Button *remove_btn = memnew(Button); + remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); + remove_btn->set_tooltip(TTR("Remove") + " " + name_left); + remove_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_remove_output_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(remove_btn); + + LineEdit *name_box = memnew(LineEdit); + hb->add_child(name_box); + name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); + name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + name_box->set_text(name_right); + name_box->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_output_port_name), varray(name_box, p_id, i)); + name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, true)); + + OptionButton *type_box = memnew(OptionButton); + hb->add_child(type_box); + type_box->add_item(TTR("Float")); + type_box->add_item(TTR("Int")); + type_box->add_item(TTR("Vector")); + type_box->add_item(TTR("Boolean")); + type_box->add_item(TTR("Transform")); + type_box->select(group_node->get_output_port_type(i)); + type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + type_box->connect("item_selected", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_output_port_type), varray(p_id, i), CONNECT_DEFERRED); + } else { + Label *label = memnew(Label); + label->set_text(name_right); + label->add_theme_style_override("normal", label_style); //more compact + hb->add_child(label); + } + } + } + + if (valid_right && visual_shader->get_shader_type() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) { + TextureButton *preview = memnew(TextureButton); + preview->set_toggle_mode(true); + preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons")); + preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons")); + preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + + register_output_port(p_id, i, preview); + + preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(preview); + } + + if (is_group) { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); + node->add_child(offset); + port_offset++; + } + + node->add_child(hb); + + node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]); + } + + if (vsnode->get_output_port_for_preview() >= 0) { + show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview()); + } + + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); + node->add_child(offset); + + String error = vsnode->get_warning(visual_shader->get_mode(), p_type); + if (error != String()) { + Label *error_label = memnew(Label); + error_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("error_color", "Editor")); + error_label->set_text(error); + node->add_child(error_label); + } + + if (is_expression) { + CodeEdit *expression_box = memnew(CodeEdit); + Ref<CodeHighlighter> expression_syntax_highlighter; + expression_syntax_highlighter.instance(); + expression_node->set_control(expression_box, 0); + node->add_child(expression_box); + + Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); + Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); + Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); + Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); + Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); + Color function_color = EDITOR_GET("text_editor/highlighting/function_color"); + Color number_color = EDITOR_GET("text_editor/highlighting/number_color"); + Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + + expression_box->set_syntax_highlighter(expression_syntax_highlighter); + expression_box->add_theme_color_override("background_color", background_color); + + for (List<String>::Element *E = VisualShaderEditor::get_singleton()->keyword_list.front(); E; E = E->next()) { + expression_syntax_highlighter->add_keyword_color(E->get(), keyword_color); + } + + expression_box->add_theme_font_override("font", VisualShaderEditor::get_singleton()->get_theme_font("expression", "EditorFonts")); + expression_box->add_theme_color_override("font_color", text_color); + expression_syntax_highlighter->set_number_color(number_color); + expression_syntax_highlighter->set_symbol_color(symbol_color); + expression_syntax_highlighter->set_function_color(function_color); + expression_syntax_highlighter->set_member_variable_color(members_color); + expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false); + expression_syntax_highlighter->add_color_region("//", "", comment_color, true); + + expression_box->set_text(expression); + expression_box->set_context_menu_enabled(false); + expression_box->set_draw_line_numbers(true); + + expression_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_expression_focus_out), varray(expression_box, p_id)); + } + + if (!uniform.is_valid()) { + VisualShaderEditor::get_singleton()->graph->add_child(node); + VisualShaderEditor::get_singleton()->_update_created_node(node); + if (is_group) { + call_deferred("_set_node_size", (int)p_type, p_id, size); + } + } +} + +void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + Ref<VisualShaderNodeUniform> uniform = Ref<VisualShaderNode>(links[p_id].visual_node); + + if (uniform.is_valid()) { + VisualShaderEditor::get_singleton()->call_deferred("_update_uniforms"); + } + + links[p_id].graph_node->get_parent()->remove_child(links[p_id].graph_node); + memdelete(links[p_id].graph_node); + links.erase(p_id); + } +} + +void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { + if (visual_shader->get_shader_type() == p_type) { + VisualShaderEditor::get_singleton()->graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); + } +} + +void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { + if (visual_shader->get_shader_type() == p_type) { + VisualShaderEditor::get_singleton()->graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); + } +} + VisualShaderGraphPlugin::~VisualShaderGraphPlugin() { } @@ -164,19 +690,7 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { } #endif visual_shader->set_graph_offset(graph->get_scroll_ofs() / EDSCALE); - - if (visual_shader->get_mode() == VisualShader::MODE_PARTICLES) { - edit_type_standart->set_visible(false); - edit_type_particles->set_visible(true); - edit_type = edit_type_particles; - particles_mode = true; - } else { - edit_type_particles->set_visible(false); - edit_type_standart->set_visible(true); - edit_type = edit_type_standart; - particles_mode = false; - } - visual_shader->set_shader_type(get_current_shader_type()); + _set_mode(visual_shader->get_mode()); } else { if (visual_shader.is_valid()) { if (visual_shader->is_connected("changed", callable_mp(this, &VisualShaderEditor::_update_preview))) { @@ -193,8 +707,8 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { _clear_buffer(); _update_options_menu(); _update_preview(); + _update_graph(); } - _update_graph(); } } @@ -484,6 +998,21 @@ void VisualShaderEditor::_update_options_menu() { } } +void VisualShaderEditor::_set_mode(int p_which) { + if (p_which == VisualShader::MODE_PARTICLES) { + edit_type_standart->set_visible(false); + edit_type_particles->set_visible(true); + edit_type = edit_type_particles; + particles_mode = true; + } else { + edit_type_particles->set_visible(false); + edit_type_standart->set_visible(true); + edit_type = edit_type_standart; + particles_mode = false; + } + visual_shader->set_shader_type(get_current_shader_type()); +} + Size2 VisualShaderEditor::get_minimum_size() const { return Size2(10, 200); } @@ -498,15 +1027,6 @@ void VisualShaderEditor::_draw_color_over_button(Object *obj, Color p_color) { button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } -static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { - Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); - style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE); - style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE); - style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE); - style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE); - return style; -} - void VisualShaderEditor::_update_created_node(GraphNode *node) { if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); @@ -530,50 +1050,9 @@ void VisualShaderEditor::_update_created_node(GraphNode *node) { } } -void VisualShaderEditor::_update_graph() { - if (updating) { - return; - } - - if (visual_shader.is_null()) { - return; - } - - graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE); - - VisualShader::Type type = get_current_shader_type(); - - graph->clear_connections(); - //erase all nodes - for (int i = 0; i < graph->get_child_count(); i++) { - if (Object::cast_to<GraphNode>(graph->get_child(i))) { - Node *node = graph->get_child(i); - graph->remove_child(node); - memdelete(node); - i--; - } - } - - static const Color type_color[6] = { - Color(0.38, 0.85, 0.96), // scalar (float) - Color(0.49, 0.78, 0.94), // scalar (int) - Color(0.84, 0.49, 0.93), // vector - Color(0.55, 0.65, 0.94), // boolean - Color(0.96, 0.66, 0.43), // transform - Color(1.0, 1.0, 0.0), // sampler - }; - - List<VisualShader::Connection> connections; - visual_shader->get_node_connections(type, &connections); - - Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); - - Vector<int> nodes = visual_shader->get_node_list(type); - +void VisualShaderEditor::_update_uniforms() { VisualShaderNodeUniformRef::clear_uniforms(); - // scan for all uniforms - for (int t = 0; t < VisualShader::TYPE_MAX; t++) { Vector<int> tnodes = visual_shader->get_node_list((VisualShader::Type)t); for (int i = 0; i < tnodes.size(); i++) { @@ -608,378 +1087,45 @@ void VisualShaderEditor::_update_graph() { } } } +} - Control *offset; - - graph_plugin->clear_links(); - graph_plugin->make_dirty(true); - - for (int n_i = 0; n_i < nodes.size(); n_i++) { - Vector2 position = visual_shader->get_node_position(type, nodes[n_i]); - Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, nodes[n_i]); - - Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr()); - bool is_group = !group_node.is_null(); - Size2 size = Size2(0, 0); - - Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr()); - bool is_expression = !expression_node.is_null(); - String expression = ""; - - GraphNode *node = memnew(GraphNode); - visual_shader->set_graph_node(type, nodes[n_i], node); - graph_plugin->register_link(type, nodes[n_i], vsnode.ptr(), node); - - if (is_group) { - size = group_node->get_size(); - - node->set_resizable(true); - node->connect("resize_request", callable_mp(this, &VisualShaderEditor::_node_resized), varray((int)type, nodes[n_i])); - } - if (is_expression) { - expression = expression_node->get_expression(); - } - - node->set_offset(position); - - node->set_title(vsnode->get_caption()); - node->set_name(itos(nodes[n_i])); - - if (nodes[n_i] >= 2) { - node->set_show_close_button(true); - node->connect("close_request", callable_mp(this, &VisualShaderEditor::_delete_request), varray(nodes[n_i]), CONNECT_DEFERRED); - } - - node->connect("dragged", callable_mp(this, &VisualShaderEditor::_node_dragged), varray(nodes[n_i])); - - Control *custom_editor = nullptr; - int port_offset = 0; - - if (is_group) { - port_offset += 2; - } - - Ref<VisualShaderNodeUniform> uniform = vsnode; - Ref<VisualShaderNodeFloatUniform> float_uniform = vsnode; - Ref<VisualShaderNodeIntUniform> int_uniform = vsnode; - Ref<VisualShaderNodeVec3Uniform> vec3_uniform = vsnode; - Ref<VisualShaderNodeColorUniform> color_uniform = vsnode; - Ref<VisualShaderNodeBooleanUniform> bool_uniform = vsnode; - Ref<VisualShaderNodeTransformUniform> transform_uniform = vsnode; - if (uniform.is_valid()) { - graph->add_child(node); - _update_created_node(node); - - LineEdit *uniform_name = memnew(LineEdit); - uniform_name->set_text(uniform->get_uniform_name()); - node->add_child(uniform_name); - uniform_name->connect("text_entered", callable_mp(this, &VisualShaderEditor::_line_edit_changed), varray(uniform_name, nodes[n_i])); - uniform_name->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_line_edit_focus_out), varray(uniform_name, nodes[n_i])); - - String error = vsnode->get_warning(visual_shader->get_mode(), type); - if (error != String()) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); - node->add_child(offset); - Label *error_label = memnew(Label); - error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); - error_label->set_text(error); - node->add_child(error_label); - } - - if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") { - //shortcut - VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); - node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); - if (!float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !color_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid()) { - continue; - } - } - port_offset++; - } - - for (int i = 0; i < plugins.size(); i++) { - custom_editor = plugins.write[i]->create_editor(visual_shader, vsnode); - if (custom_editor) { - break; - } - } - - if (custom_editor && !float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid() && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { - //will be embedded in first port - } else if (custom_editor) { - port_offset++; - node->add_child(custom_editor); - if (color_uniform.is_valid()) { - custom_editor->call_deferred("_show_prop_names", true); - } - if (float_uniform.is_valid() || int_uniform.is_valid() || vec3_uniform.is_valid() || bool_uniform.is_valid() || transform_uniform.is_valid()) { - custom_editor->call_deferred("_show_prop_names", true); - continue; - } - custom_editor = nullptr; - } - - if (is_group) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE)); - node->add_child(offset); - - if (group_node->is_editable()) { - HBoxContainer *hb2 = memnew(HBoxContainer); - - Button *add_input_btn = memnew(Button); - add_input_btn->set_text(TTR("Add Input")); - add_input_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_add_input_port), varray(nodes[n_i], group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED); - hb2->add_child(add_input_btn); - - hb2->add_spacer(); - - Button *add_output_btn = memnew(Button); - add_output_btn->set_text(TTR("Add Output")); - add_output_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_add_output_port), varray(nodes[n_i], group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED); - hb2->add_child(add_output_btn); - - node->add_child(hb2); - } - } - - for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) { - if (vsnode->is_port_separator(i)) { - node->add_child(memnew(HSeparator)); - port_offset++; - } - - bool valid_left = i < vsnode->get_input_port_count(); - VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR; - bool port_left_used = false; - String name_left; - if (valid_left) { - name_left = vsnode->get_input_port_name(i); - port_left = vsnode->get_input_port_type(i); - for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { - if (E->get().to_node == nodes[n_i] && E->get().to_port == i) { - port_left_used = true; - } - } - } - - bool valid_right = i < vsnode->get_output_port_count(); - VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR; - String name_right; - if (valid_right) { - name_right = vsnode->get_output_port_name(i); - port_right = vsnode->get_output_port_type(i); - } - - HBoxContainer *hb = memnew(HBoxContainer); - hb->add_theme_constant_override("separation", 7 * EDSCALE); - - Variant default_value; - - if (valid_left && !port_left_used) { - default_value = vsnode->get_input_port_default_value(i); - } - - if (default_value.get_type() != Variant::NIL) { // only a label - Button *button = memnew(Button); - hb->add_child(button); - button->connect("pressed", callable_mp(this, &VisualShaderEditor::_edit_port_default_input), varray(button, nodes[n_i], i)); - - switch (default_value.get_type()) { - case Variant::COLOR: { - button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); - button->connect("draw", callable_mp(this, &VisualShaderEditor::_draw_color_over_button), varray(button, default_value)); - } break; - case Variant::BOOL: { - button->set_text(((bool)default_value) ? "true" : "false"); - } break; - case Variant::INT: - case Variant::FLOAT: { - button->set_text(String::num(default_value, 4)); - } break; - case Variant::VECTOR3: { - Vector3 v = default_value; - button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3)); - } break; - default: { - } - } - } - - if (i == 0 && custom_editor) { - hb->add_child(custom_editor); - custom_editor->set_h_size_flags(SIZE_EXPAND_FILL); - } else { - if (valid_left) { - if (is_group) { - OptionButton *type_box = memnew(OptionButton); - hb->add_child(type_box); - type_box->add_item(TTR("Float")); - type_box->add_item(TTR("Int")); - type_box->add_item(TTR("Vector")); - type_box->add_item(TTR("Boolean")); - type_box->add_item(TTR("Transform")); - type_box->add_item(TTR("Sampler")); - type_box->select(group_node->get_input_port_type(i)); - type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - type_box->connect("item_selected", callable_mp(this, &VisualShaderEditor::_change_input_port_type), varray(nodes[n_i], i), CONNECT_DEFERRED); - - LineEdit *name_box = memnew(LineEdit); - hb->add_child(name_box); - name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); - name_box->set_h_size_flags(SIZE_EXPAND_FILL); - name_box->set_text(name_left); - name_box->connect("text_entered", callable_mp(this, &VisualShaderEditor::_change_input_port_name), varray(name_box, nodes[n_i], i)); - name_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_port_name_focus_out), varray(name_box, nodes[n_i], i, false)); - - Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); - remove_btn->set_tooltip(TTR("Remove") + " " + name_left); - remove_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_remove_input_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(remove_btn); - } else { - Label *label = memnew(Label); - label->set_text(name_left); - label->add_theme_style_override("normal", label_style); //more compact - hb->add_child(label); - - if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) { - Label *hint_label = memnew(Label); - hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]"); - hint_label->add_theme_color_override("font_color", get_theme_color("font_color_readonly", "TextEdit")); - hint_label->add_theme_style_override("normal", label_style); - hb->add_child(hint_label); - } - } - } - - if (!is_group) { - hb->add_spacer(); - } - - if (valid_right) { - if (is_group) { - Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); - remove_btn->set_tooltip(TTR("Remove") + " " + name_left); - remove_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_remove_output_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(remove_btn); - - LineEdit *name_box = memnew(LineEdit); - hb->add_child(name_box); - name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); - name_box->set_h_size_flags(SIZE_EXPAND_FILL); - name_box->set_text(name_right); - name_box->connect("text_entered", callable_mp(this, &VisualShaderEditor::_change_output_port_name), varray(name_box, nodes[n_i], i)); - name_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_port_name_focus_out), varray(name_box, nodes[n_i], i, true)); - - OptionButton *type_box = memnew(OptionButton); - hb->add_child(type_box); - type_box->add_item(TTR("Float")); - type_box->add_item(TTR("Int")); - type_box->add_item(TTR("Vector")); - type_box->add_item(TTR("Boolean")); - type_box->add_item(TTR("Transform")); - type_box->select(group_node->get_output_port_type(i)); - type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - type_box->connect("item_selected", callable_mp(this, &VisualShaderEditor::_change_output_port_type), varray(nodes[n_i], i), CONNECT_DEFERRED); - } else { - Label *label = memnew(Label); - label->set_text(name_right); - label->add_theme_style_override("normal", label_style); //more compact - hb->add_child(label); - } - } - } - - if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) { - TextureButton *preview = memnew(TextureButton); - preview->set_toggle_mode(true); - preview->set_normal_texture(get_theme_icon("GuiVisibilityHidden", "EditorIcons")); - preview->set_pressed_texture(get_theme_icon("GuiVisibilityVisible", "EditorIcons")); - preview->set_v_size_flags(SIZE_SHRINK_CENTER); - - graph_plugin->register_output_port(nodes[n_i], i, preview); - - preview->connect("pressed", callable_mp(this, &VisualShaderEditor::_preview_select_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(preview); - } - - if (is_group) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); - node->add_child(offset); - port_offset++; - } - - node->add_child(hb); +void VisualShaderEditor::_update_graph() { + if (updating) { + return; + } - node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]); - } + if (visual_shader.is_null()) { + return; + } - if (vsnode->get_output_port_for_preview() >= 0) { - graph_plugin->show_port_preview(vsnode->get_output_port_for_preview(), nodes[n_i]); - } + graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE); - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); - node->add_child(offset); + VisualShader::Type type = get_current_shader_type(); - String error = vsnode->get_warning(visual_shader->get_mode(), type); - if (error != String()) { - Label *error_label = memnew(Label); - error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); - error_label->set_text(error); - node->add_child(error_label); + graph->clear_connections(); + //erase all nodes + for (int i = 0; i < graph->get_child_count(); i++) { + if (Object::cast_to<GraphNode>(graph->get_child(i))) { + Node *node = graph->get_child(i); + graph->remove_child(node); + memdelete(node); + i--; } + } - if (is_expression) { - CodeEdit *expression_box = memnew(CodeEdit); - Ref<CodeHighlighter> expression_syntax_highlighter; - expression_syntax_highlighter.instance(); - expression_node->set_control(expression_box, 0); - node->add_child(expression_box); - - Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); - Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); - Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); - Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); - Color function_color = EDITOR_GET("text_editor/highlighting/function_color"); - Color number_color = EDITOR_GET("text_editor/highlighting/number_color"); - Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); - - expression_box->set_syntax_highlighter(expression_syntax_highlighter); - expression_box->add_theme_color_override("background_color", background_color); - - for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) { - expression_syntax_highlighter->add_keyword_color(E->get(), keyword_color); - } + List<VisualShader::Connection> connections; + visual_shader->get_node_connections(type, &connections); + graph_plugin->set_connections(connections); - expression_box->add_theme_font_override("font", get_theme_font("expression", "EditorFonts")); - expression_box->add_theme_color_override("font_color", text_color); - expression_syntax_highlighter->set_number_color(number_color); - expression_syntax_highlighter->set_symbol_color(symbol_color); - expression_syntax_highlighter->set_function_color(function_color); - expression_syntax_highlighter->set_member_variable_color(members_color); - expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false); - expression_syntax_highlighter->add_color_region("//", "", comment_color, true); + Vector<int> nodes = visual_shader->get_node_list(type); - expression_box->set_text(expression); - expression_box->set_context_menu_enabled(false); - expression_box->set_draw_line_numbers(true); + _update_uniforms(); - expression_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_expression_focus_out), varray(expression_box, nodes[n_i])); - } + graph_plugin->clear_links(); + graph_plugin->make_dirty(true); - if (!uniform.is_valid()) { - graph->add_child(node); - _update_created_node(node); - if (is_group) { - call_deferred("_set_node_size", (int)type, nodes[n_i], size); - } - } + for (int n_i = 0; n_i < nodes.size(); n_i++) { + graph_plugin->add_node(type, nodes[n_i]); } graph_plugin->make_dirty(false); @@ -1280,13 +1426,15 @@ void VisualShaderEditor::_preview_select_port(int p_node, int p_port) { if (node.is_null()) { return; } - + int prev_port = node->get_output_port_for_preview(); if (node->get_output_port_for_preview() == p_port) { p_port = -1; //toggle it } undo_redo->create_action(p_port == -1 ? TTR("Hide Port Preview") : TTR("Show Port Preview")); undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", p_port); - undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", node->get_output_port_for_preview()); + undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", prev_port); + undo_redo->add_do_method(graph_plugin.ptr(), "show_port_preview", (int)type, p_node, p_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "show_port_preview", (int)type, p_node, prev_port); undo_redo->commit_action(); } @@ -1376,8 +1524,8 @@ void VisualShaderEditor::_port_edited() { undo_redo->create_action(TTR("Set Input Default Port")); undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value); undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, value); + undo_redo->add_undo_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, vsn->get_input_port_default_value(editing_port)); undo_redo->commit_action(); property_editor->hide(); @@ -1557,6 +1705,8 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { undo_redo->create_action(TTR("Add Node to Visual Shader")); undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use); undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use); + undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_to_use); + undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_to_use); VisualShaderNodeExpression *expr = Object::cast_to<VisualShaderNodeExpression>(vsnode.ptr()); if (expr) { @@ -1571,6 +1721,8 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(_from_slot), visual_shader->get_node(type, to_node)->get_input_port_type(to_slot))) { undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot); } } } else if (from_node != -1 && from_slot != -1) { @@ -1579,14 +1731,14 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { int _to_slot = 0; if (visual_shader->is_port_types_compatible(visual_shader->get_node(type, from_node)->get_output_port_type(from_slot), vsnode->get_input_port_type(_to_slot))) { - undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); } } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); return vsnode.ptr(); } @@ -1597,6 +1749,8 @@ void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_t undo_redo->create_action(TTR("Node Moved")); undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", type, p_node, p_to); undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", type, p_node, p_from); + undo_redo->add_do_method(graph_plugin.ptr(), "set_node_position", type, p_node, p_to); + undo_redo->add_undo_method(graph_plugin.ptr(), "set_node_position", type, p_node, p_from); undo_redo->commit_action(); } @@ -1619,13 +1773,15 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in if (E->get().to_node == to && E->get().to_port == p_to_index) { undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->commit_action(); } @@ -1641,8 +1797,8 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from undo_redo->create_action(TTR("Nodes Disconnected")); undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->commit_action(); //updating = false; } @@ -1664,8 +1820,18 @@ void VisualShaderEditor::_delete_request(int which) { Ref<VisualShaderNode> node = Ref<VisualShaderNode>(visual_shader->get_node(type, which)); undo_redo->create_action(TTR("Delete Node")); + + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().from_node == which || E->get().to_node == which) { + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } + undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, which); undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, which), which); + undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, which); undo_redo->add_do_method(this, "_clear_buffer"); undo_redo->add_undo_method(this, "_clear_buffer"); @@ -1684,17 +1850,14 @@ void VisualShaderEditor::_delete_request(int which) { undo_redo->add_undo_method(expression, "set_expression", expression->get_expression()); } - List<VisualShader::Connection> conns; - visual_shader->get_node_connections(type, &conns); - for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { if (E->get().from_node == which || E->get().to_node == which) { undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } - - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + // delete a node from the graph + undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, which); undo_redo->commit_action(); } @@ -1953,12 +2116,13 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in Ref<VisualShaderNode> dupli = node->duplicate(); undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(pasted_type, E->get()) + p_offset, id_from); - undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from); + undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_from); // duplicate size, inputs and outputs if node is group Ref<VisualShaderNodeGroupBase> group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr()); if (!group.is_null()) { undo_redo->add_do_method(dupli.ptr(), "set_size", group->get_size()); + undo_redo->add_do_method(graph_plugin.ptr(), "set_node_size", type, id_from, group->get_size()); undo_redo->add_do_method(dupli.ptr(), "set_inputs", group->get_inputs()); undo_redo->add_do_method(dupli.ptr(), "set_outputs", group->get_outputs()); } @@ -1979,12 +2143,19 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in continue; } if (connection_remap.has(E->get().from_node) && connection_remap.has(E->get().to_node)) { - undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + id_from = base_id; + for (List<int>::Element *E = r_nodes.front(); E; E = E->next()) { + undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from); + undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_from); + id_from++; + } + undo_redo->commit_action(); if (p_select) { @@ -2075,11 +2246,23 @@ void VisualShaderEditor::_delete_nodes() { undo_redo->create_action(TTR("Delete Nodes")); + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().from_node == F->get() || E->get().to_node == F->get()) { + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } + } + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { Ref<VisualShaderNode> node = visual_shader->get_node(type, F->get()); undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get()); undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F->get()), F->get()); + undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F->get()); undo_redo->add_do_method(this, "_clear_buffer"); undo_redo->add_undo_method(this, "_clear_buffer"); @@ -2099,9 +2282,6 @@ void VisualShaderEditor::_delete_nodes() { } } - List<VisualShader::Connection> conns; - visual_shader->get_node_connections(type, &conns); - List<VisualShader::Connection> used_conns; for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { @@ -2115,19 +2295,23 @@ void VisualShaderEditor::_delete_nodes() { } if (!cancel) { undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); used_conns.push_back(E->get()); } } } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + // delete nodes from the graph + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { + undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F->get()); + } + undo_redo->commit_action(); } void VisualShaderEditor::_mode_selected(int p_id) { - visual_shader->set_shader_type(VisualShader::Type(p_id)); + visual_shader->set_shader_type(particles_mode ? VisualShader::Type(p_id + 3) : VisualShader::Type(p_id)); _update_options_menu(); _update_graph(); } @@ -2429,6 +2613,8 @@ void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_uniform_select_item", &VisualShaderEditor::_uniform_select_item); ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size); ClassDB::bind_method("_clear_buffer", &VisualShaderEditor::_clear_buffer); + ClassDB::bind_method("_update_uniforms", &VisualShaderEditor::_update_uniforms); + ClassDB::bind_method("_set_mode", &VisualShaderEditor::_set_mode); ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw); ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw); @@ -3251,6 +3437,8 @@ public: class VisualShaderNodePluginDefaultEditor : public VBoxContainer { GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer); Ref<Resource> parent_resource; + int node_id; + VisualShader::Type shader_type; public: void _property_changed(const String &p_property, const Variant &p_value, const String &p_field = "", bool p_changing = false) { @@ -3279,8 +3467,10 @@ public: } else { undo_redo->add_undo_method(this, "_open_inspector", (RES)parent_resource.ptr()); } - undo_redo->add_do_method(this, "_refresh_request"); - undo_redo->add_undo_method(this, "_refresh_request"); + } + if (p_property != "constant") { + undo_redo->add_do_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_property_editor_deferred", shader_type, node_id); + undo_redo->add_undo_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_property_editor_deferred", shader_type, node_id); } undo_redo->commit_action(); @@ -3296,10 +3486,6 @@ public: } } - void _refresh_request() { - VisualShaderEditor::get_singleton()->call_deferred("_update_graph"); - } - void _resource_selected(const String &p_path, RES p_resource) { _open_inspector(p_resource); } @@ -3325,6 +3511,9 @@ public: node = p_node; properties = p_properties; + node_id = (int)p_node->get_meta("id"); + shader_type = VisualShader::Type((int)p_node->get_meta("shader_type")); + for (int i = 0; i < p_properties.size(); i++) { HBoxContainer *hbox = memnew(HBoxContainer); hbox->set_h_size_flags(SIZE_EXPAND_FILL); @@ -3352,11 +3541,9 @@ public: properties[i]->set_name_split_ratio(0); } node->connect("changed", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_node_changed)); - node->connect("editor_refresh_request", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_refresh_request), varray(), CONNECT_DEFERRED); } static void _bind_methods() { - ClassDB::bind_method("_refresh_request", &VisualShaderNodePluginDefaultEditor::_refresh_request); // Used by UndoRedo. ClassDB::bind_method("_open_inspector", &VisualShaderNodePluginDefaultEditor::_open_inspector); // Used by UndoRedo. ClassDB::bind_method("_show_prop_names", &VisualShaderNodePluginDefaultEditor::_show_prop_names); // Used with call_deferred. } @@ -3445,6 +3632,10 @@ void EditorPropertyShaderMode::_option_selected(int p_which) { //do is easy undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which); undo_redo->add_undo_method(visual_shader.ptr(), "set_mode", visual_shader->get_mode()); + + undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_set_mode", p_which); + undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_set_mode", visual_shader->get_mode()); + //now undo is hell //1. restore connections to output diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 125687c424..e5e4add6a2 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -54,6 +54,10 @@ class VisualShaderGraphPlugin : public Reference { GDCLASS(VisualShaderGraphPlugin, Reference); private: + struct InputPort { + Button *default_input_button; + }; + struct Port { TextureButton *preview_button; }; @@ -64,12 +68,16 @@ private: GraphNode *graph_node; bool preview_visible; int preview_pos; + Map<int, InputPort> input_ports; Map<int, Port> output_ports; VBoxContainer *preview_box; + Control *custom_editor; + int editor_pos; }; Ref<VisualShader> visual_shader; Map<int, Link> links; + List<VisualShader::Connection> connections; bool dirty = false; protected: @@ -77,15 +85,29 @@ protected: public: void register_shader(VisualShader *p_visual_shader); + void set_connections(List<VisualShader::Connection> &p_connections); void register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node); void register_output_port(int p_id, int p_port, TextureButton *p_button); + void register_custom_editor(int p_node_id, Control *p_custom_editor); + void register_editor_pos(int p_node_id, int p_pos); void clear_links(); void set_shader_type(VisualShader::Type p_type); bool is_preview_visible(int p_id) const; bool is_dirty() const; void make_dirty(bool p_enabled); - - void show_port_preview(int p_node_id, int p_port_id); + void add_node(VisualShader::Type p_type, int p_id); + void remove_node(VisualShader::Type p_type, int p_id); + void connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port); + void disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port); + void show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id); + void set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position); + void set_node_size(VisualShader::Type p_type, int p_id, const Vector2 &p_size); + void refresh_node_ports(VisualShader::Type p_type, int p_node); + void update_property_editor(VisualShader::Type p_type, int p_node_id); + void update_property_editor_deferred(VisualShader::Type p_type, int p_node_id); + void set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, Variant p_value); + void register_default_input_button(int p_node_id, int p_port_id, Button *p_button); + VisualShader::Type get_shader_type() const; VisualShaderGraphPlugin(); ~VisualShaderGraphPlugin(); @@ -229,6 +251,7 @@ class VisualShaderEditor : public VBoxContainer { void _add_texture_node(const String &p_path); VisualShaderNode *_add_node(int p_idx, int p_op_idx = -1); void _update_options_menu(); + void _set_mode(int p_which); void _show_preview_text(); void _update_preview(); @@ -328,6 +351,7 @@ class VisualShaderEditor : public VBoxContainer { bool _is_available(int p_mode); void _update_created_node(GraphNode *node); + void _update_uniforms(); protected: void _notification(int p_what); @@ -339,6 +363,7 @@ public: void remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin); static VisualShaderEditor *get_singleton() { return singleton; } + VisualShaderGraphPlugin *get_graph_plugin() { return graph_plugin.ptr(); } void clear_custom_types(); void add_custom_type(const String &p_name, const Ref<Script> &p_script, const String &p_description, int p_return_icon_type, const String &p_category, bool p_highend); diff --git a/glsl_builders.py b/glsl_builders.py index e1a6e41bea..29971fd4e7 100644 --- a/glsl_builders.py +++ b/glsl_builders.py @@ -96,8 +96,6 @@ def build_rd_header(filename): out_file = filename + ".gen.h" fd = open(out_file, "w") - enum_constants = [] - fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n") out_file_base = out_file @@ -165,7 +163,6 @@ class RAWHeaderStruct: def include_file_in_raw_header(filename, header_data, depth): fs = open(filename, "r") line = fs.readline() - text = "" while line: @@ -192,8 +189,6 @@ def build_raw_header(filename): out_file = filename + ".gen.h" fd = open(out_file, "w") - enum_constants = [] - fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n") out_file_base = out_file.replace(".glsl.gen.h", "_shader_glsl") diff --git a/tests/test_gdnative_string.h b/modules/gdnative/tests/test_string.h index 76868ba842..aeb855a1c4 100644 --- a/tests/test_gdnative_string.h +++ b/modules/gdnative/tests/test_string.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* test_gdnative_string.h */ +/* test_string.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TEST_GDNATVIE_STRING_H -#define TEST_GDNATVIE_STRING_H +#ifndef TEST_GDNATIVE_STRING_H +#define TEST_GDNATIVE_STRING_H namespace TestGDNativeString { -#include "modules/modules_enabled.gen.h" -#ifdef MODULE_GDNATIVE_ENABLED - #include "gdnative/string.h" #include "tests/test_macros.h" @@ -46,7 +43,7 @@ int u32scmp(const char32_t *l, const char32_t *r) { return *l - *r; } -TEST_CASE("[GDNatvie String] Construct from Latin-1 char string") { +TEST_CASE("[GDNative String] Construct from Latin-1 char string") { godot_string s; godot_string_new_with_latin1_chars(&s, "Hello"); @@ -58,7 +55,7 @@ TEST_CASE("[GDNatvie String] Construct from Latin-1 char string") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Construct from wchar_t string") { +TEST_CASE("[GDNative String] Construct from wchar_t string") { godot_string s; godot_string_new_with_wide_chars(&s, L"Give me"); @@ -70,7 +67,7 @@ TEST_CASE("[GDNatvie String] Construct from wchar_t string") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Construct from UTF-8 char string") { +TEST_CASE("[GDNative String] Construct from UTF-8 char string") { static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; static const char32_t u32str_short[] = { 0x0045, 0x0020, 0x304A, 0 }; static const uint8_t u8str[] = { 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 }; @@ -100,7 +97,7 @@ TEST_CASE("[GDNatvie String] Construct from UTF-8 char string") { godot_char_string_destroy(&cs); } -TEST_CASE("[GDNatvie String] Construct from UTF-8 string with BOM") { +TEST_CASE("[GDNative String] Construct from UTF-8 string with BOM") { static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; static const char32_t u32str_short[] = { 0x0045, 0x0020, 0x304A, 0 }; static const uint8_t u8str[] = { 0xEF, 0xBB, 0xBF, 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 }; @@ -116,7 +113,7 @@ TEST_CASE("[GDNatvie String] Construct from UTF-8 string with BOM") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Construct from UTF-16 string") { +TEST_CASE("[GDNative String] Construct from UTF-16 string") { static const char32_t u32str[] = { 0x0045, 0x0020, 0x1F3A4, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; static const char32_t u32str_short[] = { 0x0045, 0x0020, 0x1F3A4, 0 }; static const char16_t u16str[] = { 0x0045, 0x0020, 0xD83C, 0xDFA4, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 }; @@ -146,7 +143,7 @@ TEST_CASE("[GDNatvie String] Construct from UTF-16 string") { godot_char16_string_destroy(&cs); } -TEST_CASE("[GDNatvie String] Construct from UTF-16 string with BOM ") { +TEST_CASE("[GDNative String] Construct from UTF-16 string with BOM ") { static const char32_t u32str[] = { 0x0045, 0x0020, 0x1F3A4, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; static const char32_t u32str_short[] = { 0x0045, 0x0020, 0x1F3A4, 0 }; static const char16_t u16str[] = { 0xFEFF, 0x0045, 0x0020, 0xD83C, 0xDFA4, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 }; @@ -171,7 +168,7 @@ TEST_CASE("[GDNatvie String] Construct from UTF-16 string with BOM ") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Construct string copy") { +TEST_CASE("[GDNative String] Construct string copy") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "Hello"); @@ -181,7 +178,7 @@ TEST_CASE("[GDNatvie String] Construct string copy") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Construct empty string") { +TEST_CASE("[GDNative String] Construct empty string") { godot_string s; godot_string_new(&s); @@ -189,7 +186,7 @@ TEST_CASE("[GDNatvie String] Construct empty string") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] ASCII/Latin-1") { +TEST_CASE("[GDNative String] ASCII/Latin-1") { godot_string s; godot_string_new_with_utf32_chars(&s, U"Primero Leche"); @@ -204,7 +201,7 @@ TEST_CASE("[GDNatvie String] ASCII/Latin-1") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Comparisons (equal)") { +TEST_CASE("[GDNative String] Comparisons (equal)") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "Test Compare"); @@ -214,7 +211,7 @@ TEST_CASE("[GDNatvie String] Comparisons (equal)") { godot_string_destroy(&t); } -TEST_CASE("[GDNatvie String] Comparisons (operator <)") { +TEST_CASE("[GDNative String] Comparisons (operator <)") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "Bees"); @@ -234,7 +231,7 @@ TEST_CASE("[GDNatvie String] Comparisons (operator <)") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Concatenation (operator +)") { +TEST_CASE("[GDNative String] Concatenation (operator +)") { godot_string s, t, x; godot_string_new_with_latin1_chars(&s, "Hel"); @@ -246,7 +243,7 @@ TEST_CASE("[GDNatvie String] Concatenation (operator +)") { godot_string_destroy(&t); } -TEST_CASE("[GDNatvie String] Testing size and length of string") { +TEST_CASE("[GDNative String] Testing size and length of string") { godot_string s; godot_string_new_with_latin1_chars(&s, "Mellon"); @@ -258,7 +255,7 @@ TEST_CASE("[GDNatvie String] Testing size and length of string") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Testing for empty string") { +TEST_CASE("[GDNative String] Testing for empty string") { godot_string s; godot_string_new_with_latin1_chars(&s, "Mellon"); @@ -270,7 +267,7 @@ TEST_CASE("[GDNatvie String] Testing for empty string") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Test chr") { +TEST_CASE("[GDNative String] Test chr") { godot_string s; s = godot_string_chr('H'); @@ -292,7 +289,7 @@ TEST_CASE("[GDNatvie String] Test chr") { ERR_PRINT_ON } -TEST_CASE("[GDNatvie String] Operator []") { +TEST_CASE("[GDNative String] Operator []") { godot_string s; godot_string_new_with_latin1_chars(&s, "Hello"); @@ -302,7 +299,7 @@ TEST_CASE("[GDNatvie String] Operator []") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Case function test") { +TEST_CASE("[GDNative String] Case function test") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "MoMoNgA"); @@ -318,7 +315,7 @@ TEST_CASE("[GDNatvie String] Case function test") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Case compare function test") { +TEST_CASE("[GDNative String] Case compare function test") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "MoMoNgA"); @@ -331,7 +328,7 @@ TEST_CASE("[GDNatvie String] Case compare function test") { godot_string_destroy(&t); } -TEST_CASE("[GDNatvie String] Natural compare function test") { +TEST_CASE("[GDNative String] Natural compare function test") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "img2.png"); @@ -344,14 +341,14 @@ TEST_CASE("[GDNatvie String] Natural compare function test") { godot_string_destroy(&t); } -TEST_CASE("[GDNatvie String] hex_encode_buffer") { +TEST_CASE("[GDNative String] hex_encode_buffer") { static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3 }; godot_string s = godot_string_hex_encode_buffer(u8str, 6); CHECK(u32scmp(godot_string_get_data(&s), U"45e3818a8fe3") == 0); godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Substr") { +TEST_CASE("[GDNative String] Substr") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "Killer Baby"); t = godot_string_substr(&s, 3, 4); @@ -360,7 +357,7 @@ TEST_CASE("[GDNatvie String] Substr") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Find") { +TEST_CASE("[GDNative String] Find") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "Pretty Woman Woman"); @@ -383,7 +380,7 @@ TEST_CASE("[GDNatvie String] Find") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Find no case") { +TEST_CASE("[GDNative String] Find no case") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "Pretty Whale Whale"); @@ -406,7 +403,7 @@ TEST_CASE("[GDNatvie String] Find no case") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Find MK") { +TEST_CASE("[GDNative String] Find MK") { godot_packed_string_array keys; godot_packed_string_array_new(&keys); @@ -440,7 +437,7 @@ TEST_CASE("[GDNatvie String] Find MK") { #undef PUSH_KEY } -TEST_CASE("[GDNatvie String] Find and replace") { +TEST_CASE("[GDNative String] Find and replace") { godot_string s, c, w; godot_string_new_with_latin1_chars(&s, "Happy Birthday, Anna!"); godot_string_new_with_latin1_chars(&c, "Birthday"); @@ -462,7 +459,7 @@ TEST_CASE("[GDNatvie String] Find and replace") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Insertion") { +TEST_CASE("[GDNative String] Insertion") { godot_string s, t, r, u; godot_string_new_with_latin1_chars(&s, "Who is Frederic?"); godot_string_new_with_latin1_chars(&t, "?"); @@ -477,7 +474,7 @@ TEST_CASE("[GDNatvie String] Insertion") { godot_string_destroy(&u); } -TEST_CASE("[GDNatvie String] Number to string") { +TEST_CASE("[GDNative String] Number to string") { godot_string s; s = godot_string_num(3.141593); CHECK(u32scmp(godot_string_get_data(&s), U"3.141593") == 0); @@ -508,7 +505,7 @@ TEST_CASE("[GDNatvie String] Number to string") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] String to integer") { +TEST_CASE("[GDNative String] String to integer") { static const wchar_t *wnums[4] = { L"1237461283", L"- 22", L"0", L" - 1123412" }; static const char *nums[4] = { "1237461283", "- 22", "0", " - 1123412" }; static const int num[4] = { 1237461283, -22, 0, -1123412 }; @@ -524,7 +521,7 @@ TEST_CASE("[GDNatvie String] String to integer") { } } -TEST_CASE("[GDNatvie String] Hex to integer") { +TEST_CASE("[GDNative String] Hex to integer") { static const char *nums[4] = { "0xFFAE", "22", "0", "AADDAD" }; static const int64_t num[4] = { 0xFFAE, 0x22, 0, 0xAADDAD }; static const bool wo_prefix[4] = { false, true, true, true }; @@ -539,7 +536,7 @@ TEST_CASE("[GDNatvie String] Hex to integer") { } } -TEST_CASE("[GDNatvie String] String to float") { +TEST_CASE("[GDNative String] String to float") { static const wchar_t *wnums[4] = { L"-12348298412.2", L"0.05", L"2.0002", L" -0.0001" }; static const char *nums[4] = { "-12348298412.2", "0.05", "2.0002", " -0.0001" }; static const double num[4] = { -12348298412.2, 0.05, 2.0002, -0.0001 }; @@ -555,7 +552,7 @@ TEST_CASE("[GDNatvie String] String to float") { } } -TEST_CASE("[GDNatvie String] CamelCase to underscore") { +TEST_CASE("[GDNative String] CamelCase to underscore") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "TestTestStringGD"); @@ -570,7 +567,7 @@ TEST_CASE("[GDNatvie String] CamelCase to underscore") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Slicing") { +TEST_CASE("[GDNative String] Slicing") { godot_string s, c; godot_string_new_with_latin1_chars(&s, "Mars,Jupiter,Saturn,Uranus"); godot_string_new_with_latin1_chars(&c, ","); @@ -591,7 +588,7 @@ TEST_CASE("[GDNatvie String] Slicing") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Splitting") { +TEST_CASE("[GDNative String] Splitting") { godot_string s, c; godot_string_new_with_latin1_chars(&s, "Mars,Jupiter,Saturn,Uranus"); godot_string_new_with_latin1_chars(&c, ","); @@ -682,7 +679,7 @@ TEST_CASE("[GDNatvie String] Splitting") { godot_packed_string_array_destroy(&keys); } -TEST_CASE("[GDNatvie String] Erasing") { +TEST_CASE("[GDNative String] Erasing") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "Josephine is such a cute girl!"); godot_string_new_with_latin1_chars(&t, "cute "); @@ -701,7 +698,7 @@ struct test_27_data { bool expected; }; -TEST_CASE("[GDNatvie String] Begins with") { +TEST_CASE("[GDNative String] Begins with") { test_27_data tc[] = { { "res://foobar", "res://", true }, { "res", "res://", false }, @@ -730,7 +727,7 @@ TEST_CASE("[GDNatvie String] Begins with") { CHECK(state); } -TEST_CASE("[GDNatvie String] Ends with") { +TEST_CASE("[GDNative String] Ends with") { test_27_data tc[] = { { "res://foobar", "foobar", true }, { "res", "res://", false }, @@ -759,7 +756,7 @@ TEST_CASE("[GDNatvie String] Ends with") { CHECK(state); } -TEST_CASE("[GDNatvie String] format") { +TEST_CASE("[GDNative String] format") { godot_string value_format, t; godot_string_new_with_latin1_chars(&value_format, "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\""); @@ -813,7 +810,7 @@ TEST_CASE("[GDNatvie String] format") { godot_string_destroy(&value_format); } -TEST_CASE("[GDNatvie String] sprintf") { +TEST_CASE("[GDNative String] sprintf") { //godot_string GDAPI (const godot_string *p_self, const godot_array *p_values, godot_bool *p_error); godot_string format, output; godot_array args; @@ -1215,7 +1212,7 @@ TEST_CASE("[GDNatvie String] sprintf") { #undef ARRAY_PUSH_STRING } -TEST_CASE("[GDNatvie String] is_numeric") { +TEST_CASE("[GDNative String] is_numeric") { #define IS_NUM_TEST(x, r) \ { \ godot_string t; \ @@ -1233,7 +1230,7 @@ TEST_CASE("[GDNatvie String] is_numeric") { #undef IS_NUM_TEST } -TEST_CASE("[GDNatvie String] pad") { +TEST_CASE("[GDNative String] pad") { godot_string s, c; godot_string_new_with_latin1_chars(&s, "test"); godot_string_new_with_latin1_chars(&c, "x"); @@ -1260,7 +1257,7 @@ TEST_CASE("[GDNatvie String] pad") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] is_subsequence_of") { +TEST_CASE("[GDNative String] is_subsequence_of") { godot_string a, t; godot_string_new_with_latin1_chars(&a, "is subsequence of"); @@ -1279,7 +1276,7 @@ TEST_CASE("[GDNatvie String] is_subsequence_of") { godot_string_destroy(&a); } -TEST_CASE("[GDNatvie String] match") { +TEST_CASE("[GDNative String] match") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "*.png"); @@ -1299,7 +1296,7 @@ TEST_CASE("[GDNatvie String] match") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] IPVX address to string") { +TEST_CASE("[GDNative String] IPVX address to string") { godot_string ip; godot_string_new_with_latin1_chars(&ip, "192.168.0.1"); @@ -1331,7 +1328,7 @@ TEST_CASE("[GDNatvie String] IPVX address to string") { godot_string_destroy(&ip); } -TEST_CASE("[GDNatvie String] Capitalize against many strings") { +TEST_CASE("[GDNative String] Capitalize against many strings") { #define CAP_TEST(i, o) \ godot_string_new_with_latin1_chars(&input, i); \ godot_string_new_with_latin1_chars(&output, o); \ @@ -1361,7 +1358,7 @@ TEST_CASE("[GDNatvie String] Capitalize against many strings") { #undef CAP_TEST } -TEST_CASE("[GDNatvie String] lstrip and rstrip") { +TEST_CASE("[GDNative String] lstrip and rstrip") { #define LSTRIP_TEST(x, y, z) \ { \ godot_string xx, yy, zz, rr; \ @@ -1484,7 +1481,7 @@ TEST_CASE("[GDNatvie String] lstrip and rstrip") { #undef RSTRIP_UTF8_TEST } -TEST_CASE("[GDNatvie String] Cyrillic to_lower()") { +TEST_CASE("[GDNative String] Cyrillic to_lower()") { godot_string upper, lower, test; godot_string_new_with_utf8_chars(&upper, "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"); godot_string_new_with_utf8_chars(&lower, "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"); @@ -1498,7 +1495,7 @@ TEST_CASE("[GDNatvie String] Cyrillic to_lower()") { godot_string_destroy(&test); } -TEST_CASE("[GDNatvie String] Count and countn functionality") { +TEST_CASE("[GDNative String] Count and countn functionality") { #define COUNT_TEST(x, y, r) \ { \ godot_string s, t; \ @@ -1570,7 +1567,7 @@ TEST_CASE("[GDNatvie String] Count and countn functionality") { #undef COUNTNR_TEST } -TEST_CASE("[GDNatvie String] Bigrams") { +TEST_CASE("[GDNative String] Bigrams") { godot_string s, t; godot_string_new_with_latin1_chars(&s, "abcd"); godot_packed_string_array bigr = godot_string_bigrams(&s); @@ -1593,7 +1590,7 @@ TEST_CASE("[GDNatvie String] Bigrams") { godot_packed_string_array_destroy(&bigr); } -TEST_CASE("[GDNatvie String] c-escape/unescape") { +TEST_CASE("[GDNative String] c-escape/unescape") { godot_string s; godot_string_new_with_latin1_chars(&s, "\\1\a2\b\f3\n45\r6\t7\v8\'9\?0\""); godot_string t = godot_string_c_escape(&s); @@ -1604,7 +1601,7 @@ TEST_CASE("[GDNatvie String] c-escape/unescape") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] dedent") { +TEST_CASE("[GDNative String] dedent") { godot_string s, t; godot_string_new_with_latin1_chars(&s, " aaa\n bbb"); godot_string_new_with_latin1_chars(&t, "aaa\nbbb"); @@ -1615,7 +1612,7 @@ TEST_CASE("[GDNatvie String] dedent") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Path functions") { +TEST_CASE("[GDNative String] Path functions") { static const char *path[4] = { "C:\\Godot\\project\\test.tscn", "/Godot/project/test.xscn", "../Godot/project/test.scn", "Godot\\test.doc" }; static const char *base_dir[4] = { "C:\\Godot\\project", "/Godot/project", "../Godot/project", "Godot" }; static const char *base_name[4] = { "C:\\Godot\\project\\test", "/Godot/project/test", "../Godot/project/test", "Godot\\test" }; @@ -1678,7 +1675,7 @@ TEST_CASE("[GDNatvie String] Path functions") { } } -TEST_CASE("[GDNatvie String] hash") { +TEST_CASE("[GDNative String] hash") { godot_string a, b, c; godot_string_new_with_latin1_chars(&a, "Test"); godot_string_new_with_latin1_chars(&b, "Test"); @@ -1694,7 +1691,7 @@ TEST_CASE("[GDNatvie String] hash") { godot_string_destroy(&c); } -TEST_CASE("[GDNatvie String] http_escape/unescape") { +TEST_CASE("[GDNative String] http_escape/unescape") { godot_string s, t, u; godot_string_new_with_latin1_chars(&s, "Godot Engine:'docs'"); godot_string_new_with_latin1_chars(&t, "Godot%20Engine%3A%27docs%27"); @@ -1711,7 +1708,7 @@ TEST_CASE("[GDNatvie String] http_escape/unescape") { godot_string_destroy(&t); } -TEST_CASE("[GDNatvie String] percent_encode/decode") { +TEST_CASE("[GDNative String] percent_encode/decode") { godot_string s, t, u; godot_string_new_with_latin1_chars(&s, "Godot Engine:'docs'"); godot_string_new_with_latin1_chars(&t, "Godot%20Engine%3a%27docs%27"); @@ -1728,7 +1725,7 @@ TEST_CASE("[GDNatvie String] percent_encode/decode") { godot_string_destroy(&t); } -TEST_CASE("[GDNatvie String] xml_escape/unescape") { +TEST_CASE("[GDNative String] xml_escape/unescape") { godot_string s, t, u; godot_string_new_with_latin1_chars(&s, "\"Test\" <test@test&'test'>"); @@ -1747,7 +1744,7 @@ TEST_CASE("[GDNatvie String] xml_escape/unescape") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Strip escapes") { +TEST_CASE("[GDNative String] Strip escapes") { godot_string s, t, u; godot_string_new_with_latin1_chars(&s, "\t\tTest Test\r\n Test"); godot_string_new_with_latin1_chars(&t, "Test Test Test"); @@ -1760,7 +1757,7 @@ TEST_CASE("[GDNatvie String] Strip escapes") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Strip edges") { +TEST_CASE("[GDNative String] Strip edges") { godot_string s, t, u; godot_string_new_with_latin1_chars(&s, "\t Test Test "); @@ -1785,7 +1782,7 @@ TEST_CASE("[GDNatvie String] Strip edges") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Similarity") { +TEST_CASE("[GDNative String] Similarity") { godot_string a, b, c; godot_string_new_with_latin1_chars(&a, "Test"); godot_string_new_with_latin1_chars(&b, "West"); @@ -1798,7 +1795,7 @@ TEST_CASE("[GDNatvie String] Similarity") { godot_string_destroy(&c); } -TEST_CASE("[GDNatvie String] Trim") { +TEST_CASE("[GDNative String] Trim") { godot_string s, t, u, p; godot_string_new_with_latin1_chars(&s, "aaaTestbbb"); @@ -1827,7 +1824,7 @@ TEST_CASE("[GDNatvie String] Trim") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Right/Left") { +TEST_CASE("[GDNative String] Right/Left") { godot_string s, t, u; godot_string_new_with_latin1_chars(&s, "aaaTestbbb"); // ^ @@ -1847,7 +1844,7 @@ TEST_CASE("[GDNatvie String] Right/Left") { godot_string_destroy(&s); } -TEST_CASE("[GDNatvie String] Repeat") { +TEST_CASE("[GDNative String] Repeat") { godot_string t, u; godot_string_new_with_latin1_chars(&t, "ab"); @@ -1858,7 +1855,7 @@ TEST_CASE("[GDNatvie String] Repeat") { godot_string_destroy(&t); } -TEST_CASE("[GDNatvie String] SHA1/SHA256/MD5") { +TEST_CASE("[GDNative String] SHA1/SHA256/MD5") { godot_string s, t, sha1, sha256, md5; godot_string_new_with_latin1_chars(&s, "Godot"); godot_string_new_with_latin1_chars(&sha1, "a1e91f39b9fce6a9998b14bdbe2aa2b39dc2d201"); @@ -1906,7 +1903,7 @@ TEST_CASE("[GDNatvie String] SHA1/SHA256/MD5") { godot_string_destroy(&md5); } -TEST_CASE("[GDNatvie String] Join") { +TEST_CASE("[GDNative String] Join") { godot_string s, t, u; godot_string_new_with_latin1_chars(&s, ", "); @@ -1932,7 +1929,7 @@ TEST_CASE("[GDNatvie String] Join") { godot_packed_string_array_destroy(&parts); } -TEST_CASE("[GDNatvie String] Is_*") { +TEST_CASE("[GDNative String] Is_*") { static const char *data[12] = { "-30", "100", "10.1", "10,1", "1e2", "1e-2", "1e2e3", "0xAB", "AB", "Test1", "1Test", "Test*1" }; static bool isnum[12] = { true, true, true, false, false, false, false, false, false, false, false, false }; static bool isint[12] = { true, true, false, false, false, false, false, false, false, false, false, false }; @@ -1954,7 +1951,7 @@ TEST_CASE("[GDNatvie String] Is_*") { } } -TEST_CASE("[GDNatvie String] humanize_size") { +TEST_CASE("[GDNative String] humanize_size") { godot_string s; s = godot_string_humanize_size(1000); @@ -1978,8 +1975,6 @@ TEST_CASE("[GDNatvie String] humanize_size") { godot_string_destroy(&s); } -#endif - } // namespace TestGDNativeString -#endif // TEST_GDNATVIE_STRING_H +#endif // TEST_GDNATIVE_STRING_H diff --git a/modules/mono/build_scripts/solution_builder.py b/modules/mono/build_scripts/solution_builder.py index 03f4e57f02..6a621c3c8b 100644 --- a/modules/mono/build_scripts/solution_builder.py +++ b/modules/mono/build_scripts/solution_builder.py @@ -8,9 +8,6 @@ def find_dotnet_cli(): import os.path if os.name == "nt": - windows_exts = os.environ["PATHEXT"] - windows_exts = windows_exts.split(os.pathsep) if windows_exts else [] - for hint_dir in os.environ["PATH"].split(os.pathsep): hint_dir = hint_dir.strip('"') hint_path = os.path.join(hint_dir, "dotnet") diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 2b506b686b..da0169b60b 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -631,6 +631,7 @@ void HTTPRequest::_bind_methods() { BIND_ENUM_CONSTANT(RESULT_SSL_HANDSHAKE_ERROR); BIND_ENUM_CONSTANT(RESULT_NO_RESPONSE); BIND_ENUM_CONSTANT(RESULT_BODY_SIZE_LIMIT_EXCEEDED); + BIND_ENUM_CONSTANT(RESULT_BODY_DECOMPRESS_FAILED); BIND_ENUM_CONSTANT(RESULT_REQUEST_FAILED); BIND_ENUM_CONSTANT(RESULT_DOWNLOAD_FILE_CANT_OPEN); BIND_ENUM_CONSTANT(RESULT_DOWNLOAD_FILE_WRITE_ERROR); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 49b8cbe7e0..4bbfa8965a 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -1246,6 +1246,12 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); + + BIND_ENUM_CONSTANT(SUB_EMITTER_DISABLED); + BIND_ENUM_CONSTANT(SUB_EMITTER_CONSTANT); + BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END); + BIND_ENUM_CONSTANT(SUB_EMITTER_AT_COLLISION); + BIND_ENUM_CONSTANT(SUB_EMITTER_MAX); } ParticlesMaterial::ParticlesMaterial() : diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index 9d41c91937..fa8858f67f 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -50,7 +50,6 @@ class ParticlesMaterial : public Material { public: enum Parameter { - PARAM_INITIAL_LINEAR_VELOCITY, PARAM_ANGULAR_VELOCITY, PARAM_ORBIT_VELOCITY, diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 4ee9b22b25..803ab265d4 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -40,7 +40,6 @@ bool VisualShaderNode::is_simple_decl() const { void VisualShaderNode::set_output_port_for_preview(int p_index) { port_preview = p_index; - emit_signal("show_port_preview", p_index); } int VisualShaderNode::get_output_port_for_preview() const { @@ -162,7 +161,6 @@ void VisualShaderNode::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values"); ADD_SIGNAL(MethodInfo("editor_refresh_request")); - ADD_SIGNAL(MethodInfo("show_port_preview", PropertyInfo(Variant::INT, "port_id"))); BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR); BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_INT); @@ -319,13 +317,6 @@ VisualShaderNodeCustom::VisualShaderNodeCustom() { ///////////////////////////////////////////////////////// -void VisualShader::set_graph_node(Type p_type, int p_id, GraphNode *p_graph_node) { - ERR_FAIL_INDEX(p_type, TYPE_MAX); - Graph *g = &graph[p_type]; - ERR_FAIL_COND(!g->nodes.has(p_id)); - g->nodes[p_id].graph_node = p_graph_node; -} - void VisualShader::set_shader_type(Type p_type) { current_type = p_type; } @@ -417,11 +408,6 @@ void VisualShader::set_node_position(Type p_type, int p_id, const Vector2 &p_pos Graph *g = &graph[p_type]; ERR_FAIL_COND(!g->nodes.has(p_id)); g->nodes[p_id].position = p_position; - if (current_type == p_type) { - if (g->nodes[p_id].graph_node != nullptr) { - g->nodes[p_id].graph_node->set_offset(p_position); - } - } } Vector2 VisualShader::get_node_position(Type p_type, int p_id) const { @@ -1523,11 +1509,11 @@ void VisualShader::_update_shader() const { if (shader_mode != Shader::MODE_PARTICLES) { func_code += "\nvoid " + String(func_name[i]) + "() {\n"; } + insertion_pos.insert(i, code.get_string_length() + func_code.get_string_length()); Set<int> processed; Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes); ERR_FAIL_COND(err != OK); - insertion_pos.insert(i, code.get_string_length()); if (shader_mode == Shader::MODE_PARTICLES) { code_map.insert(i, func_code); @@ -1638,6 +1624,9 @@ void VisualShader::_bind_methods() { BIND_ENUM_CONSTANT(TYPE_VERTEX); BIND_ENUM_CONSTANT(TYPE_FRAGMENT); BIND_ENUM_CONSTANT(TYPE_LIGHT); + BIND_ENUM_CONSTANT(TYPE_EMIT); + BIND_ENUM_CONSTANT(TYPE_PROCESS); + BIND_ENUM_CONSTANT(TYPE_END); BIND_ENUM_CONSTANT(TYPE_MAX); BIND_CONSTANT(NODE_ID_INVALID); diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 2b9115879e..513a17b024 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -33,7 +33,6 @@ #include "core/string_builder.h" #include "scene/gui/control.h" -#include "scene/gui/graph_edit.h" #include "scene/resources/shader.h" class VisualShaderNodeUniform; @@ -76,7 +75,6 @@ private: Ref<VisualShaderNode> node; Vector2 position; List<int> prev_connected_nodes; - GraphNode *graph_node; }; struct Graph { @@ -129,7 +127,6 @@ protected: void _get_property_list(List<PropertyInfo> *p_list) const; public: // internal methods - void set_graph_node(Type p_type, int p_id, GraphNode *p_graph_node); void set_shader_type(Type p_type); Type get_shader_type() const; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index dfc915c5b4..0e10682daf 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -4359,13 +4359,13 @@ String VisualShaderNodeTextureUniformTriplanar::generate_code(Shader::Mode p_mod String code = "\t{\n"; if (p_input_vars[0] == String() && p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal, triplanar_pos );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n"; } else if (p_input_vars[0] != String() && p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", triplanar_pos );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n"; } else if (p_input_vars[0] == String() && p_input_vars[1] != String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal," + p_input_vars[1] + " );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n"; } else { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n"; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index efa16628e4..c56c208098 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -2734,6 +2734,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.renames["LIGHT_COLOR"] = "light_color"; actions.renames["LIGHT"] = "light"; actions.renames["ATTENUATION"] = "attenuation"; + actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation"; actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; actions.renames["SPECULAR_LIGHT"] = "specular_light"; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index f3ef322ad7..ad5cbc9e51 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -145,7 +145,8 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SHADOW_ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["BACKLIGHT"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT); diff --git a/tests/SCsub b/tests/SCsub index 44b4cdc4b0..7aab28531d 100644 --- a/tests/SCsub +++ b/tests/SCsub @@ -7,7 +7,8 @@ env.tests_sources = [] env_tests = env.Clone() # Include GDNative headers. -env_tests.Append(CPPPATH=["#modules/gdnative/include"]) +if env["module_gdnative_enabled"]: + env_tests.Append(CPPPATH=["#modules/gdnative/include"]) # We must disable the THREAD_LOCAL entirely in doctest to prevent crashes on debugging # Since we link with /MT thread_local is always expired when the header is used diff --git a/tests/test_main.cpp b/tests/test_main.cpp index d41581883a..4e172caadb 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -37,7 +37,6 @@ #include "test_class_db.h" #include "test_color.h" #include "test_expression.h" -#include "test_gdnative_string.h" #include "test_gradient.h" #include "test_gui.h" #include "test_math.h" |