diff options
106 files changed, 1133 insertions, 410 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2fa0493544..56f64ad079 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -187,7 +187,8 @@ repos: modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment\.notest\.gd$| modules/gdscript/tests/scripts/parser/warnings/empty_file_newline\.notest\.gd$| platform/android/java/editor/src/main/java/com/android/.*| - platform/android/java/lib/src/com/google/.* + platform/android/java/lib/src/com/google/.*| + tests/data/.*\.bin$ ) - id: dotnet-format diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index ef5ca502d4..29027cade1 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -268,6 +268,10 @@ uint64_t FileAccess::get_64() const { return data; } +float FileAccess::get_half() const { + return Math::half_to_float(get_16()); +} + float FileAccess::get_float() const { MarshallFloat m; m.i = get_32(); @@ -527,6 +531,10 @@ void FileAccess::store_real(real_t p_real) { } } +void FileAccess::store_half(float p_dest) { + store_16(Math::make_half_float(p_dest)); +} + void FileAccess::store_float(float p_dest) { MarshallFloat m; m.f = p_dest; @@ -833,6 +841,7 @@ void FileAccess::_bind_methods() { ClassDB::bind_method(D_METHOD("get_16"), &FileAccess::get_16); ClassDB::bind_method(D_METHOD("get_32"), &FileAccess::get_32); ClassDB::bind_method(D_METHOD("get_64"), &FileAccess::get_64); + ClassDB::bind_method(D_METHOD("get_half"), &FileAccess::get_half); ClassDB::bind_method(D_METHOD("get_float"), &FileAccess::get_float); ClassDB::bind_method(D_METHOD("get_double"), &FileAccess::get_double); ClassDB::bind_method(D_METHOD("get_real"), &FileAccess::get_real); @@ -851,6 +860,7 @@ void FileAccess::_bind_methods() { ClassDB::bind_method(D_METHOD("store_16", "value"), &FileAccess::store_16); ClassDB::bind_method(D_METHOD("store_32", "value"), &FileAccess::store_32); ClassDB::bind_method(D_METHOD("store_64", "value"), &FileAccess::store_64); + ClassDB::bind_method(D_METHOD("store_half", "value"), &FileAccess::store_half); ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float); ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double); ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real); diff --git a/core/io/file_access.h b/core/io/file_access.h index 88c8110a51..48984c6c1b 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -148,6 +148,7 @@ public: virtual uint32_t get_32() const; ///< get 32 bits uint virtual uint64_t get_64() const; ///< get 64 bits uint + virtual float get_half() const; virtual float get_float() const; virtual double get_double() const; virtual real_t get_real() const; @@ -179,6 +180,7 @@ public: virtual void store_32(uint32_t p_dest); ///< store 32 bits uint virtual void store_64(uint64_t p_dest); ///< store 64 bits uint + virtual void store_half(float p_dest); virtual void store_float(float p_dest); virtual void store_double(double p_dest); virtual void store_real(real_t p_real); diff --git a/core/io/marshalls.h b/core/io/marshalls.h index 6f015ac386..82c760c28d 100644 --- a/core/io/marshalls.h +++ b/core/io/marshalls.h @@ -84,6 +84,12 @@ static inline unsigned int encode_uint32(uint32_t p_uint, uint8_t *p_arr) { return sizeof(uint32_t); } +static inline unsigned int encode_half(float p_float, uint8_t *p_arr) { + encode_uint16(Math::make_half_float(p_float), p_arr); + + return sizeof(uint16_t); +} + static inline unsigned int encode_float(float p_float, uint8_t *p_arr) { MarshallFloat mf; mf.f = p_float; @@ -172,6 +178,10 @@ static inline uint32_t decode_uint32(const uint8_t *p_arr) { return u; } +static inline float decode_half(const uint8_t *p_arr) { + return Math::half_to_float(decode_uint16(p_arr)); +} + static inline float decode_float(const uint8_t *p_arr) { MarshallFloat mf; mf.i = decode_uint32(p_arr); diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index 3f1c468fb3..045904fb5d 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -178,6 +178,18 @@ void StreamPeer::put_64(int64_t p_val) { put_data(buf, 8); } +void StreamPeer::put_half(float p_val) { + uint8_t buf[2]; + + encode_half(p_val, buf); + uint16_t *p16 = (uint16_t *)buf; + if (big_endian) { + *p16 = BSWAP16(*p16); + } + + put_data(buf, 2); +} + void StreamPeer::put_float(float p_val) { uint8_t buf[4]; @@ -294,6 +306,18 @@ int64_t StreamPeer::get_64() { return r; } +float StreamPeer::get_half() { + uint8_t buf[2]; + get_data(buf, 2); + + uint16_t *p16 = (uint16_t *)buf; + if (big_endian) { + *p16 = BSWAP16(*p16); + } + + return decode_half(buf); +} + float StreamPeer::get_float() { uint8_t buf[4]; get_data(buf, 4); @@ -385,6 +409,7 @@ void StreamPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("put_u32", "value"), &StreamPeer::put_u32); ClassDB::bind_method(D_METHOD("put_64", "value"), &StreamPeer::put_64); ClassDB::bind_method(D_METHOD("put_u64", "value"), &StreamPeer::put_u64); + ClassDB::bind_method(D_METHOD("put_half", "value"), &StreamPeer::put_half); ClassDB::bind_method(D_METHOD("put_float", "value"), &StreamPeer::put_float); ClassDB::bind_method(D_METHOD("put_double", "value"), &StreamPeer::put_double); ClassDB::bind_method(D_METHOD("put_string", "value"), &StreamPeer::put_string); @@ -399,6 +424,7 @@ void StreamPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_u32"), &StreamPeer::get_u32); ClassDB::bind_method(D_METHOD("get_64"), &StreamPeer::get_64); ClassDB::bind_method(D_METHOD("get_u64"), &StreamPeer::get_u64); + ClassDB::bind_method(D_METHOD("get_half"), &StreamPeer::get_half); ClassDB::bind_method(D_METHOD("get_float"), &StreamPeer::get_float); ClassDB::bind_method(D_METHOD("get_double"), &StreamPeer::get_double); ClassDB::bind_method(D_METHOD("get_string", "bytes"), &StreamPeer::get_string, DEFVAL(-1)); diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index 29cdb82615..44bbfbf1d5 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -73,6 +73,7 @@ public: void put_u32(uint32_t p_val); void put_64(int64_t p_val); void put_u64(uint64_t p_val); + void put_half(float p_val); void put_float(float p_val); void put_double(double p_val); void put_string(const String &p_string); @@ -87,6 +88,7 @@ public: int32_t get_32(); uint64_t get_u64(); int64_t get_64(); + float get_half(); float get_float(); double get_double(); String get_string(int p_bytes = -1); diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h index 62296ac040..58e86e3e48 100644 --- a/core/object/worker_thread_pool.h +++ b/core/object/worker_thread_pool.h @@ -258,7 +258,13 @@ public: bool is_group_task_completed(GroupID p_group) const; void wait_for_group_task_completion(GroupID p_group); - _FORCE_INLINE_ int get_thread_count() const { return threads.size(); } + _FORCE_INLINE_ int get_thread_count() const { +#ifdef THREADS_ENABLED + return threads.size(); +#else + return 1; +#endif + } static WorkerThreadPool *get_singleton() { return singleton; } static int get_thread_index(); diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 020949371f..d944135a70 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -80,8 +80,10 @@ void Translation::set_locale(const String &p_locale) { if (Thread::is_main_thread()) { _notify_translation_changed_if_applies(); } else { - // Avoid calling non-thread-safe functions here. - callable_mp(this, &Translation::_notify_translation_changed_if_applies).call_deferred(); + // This has to happen on the main thread (bypassing the ResourceLoader per-thread call queue) + // because it interacts with the generally non-thread-safe window management, leading to + // different issues across platforms otherwise. + MessageQueue::get_main_singleton()->push_callable(callable_mp(this, &Translation::_notify_translation_changed_if_applies)); } } diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index ae2de055cb..57ac241eb2 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -345,14 +345,14 @@ </methods> <members> <member name="end" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> - The ending point. This is usually the corner on the top-right and forward of the bounding box, and is equivalent to [code]position + size[/code]. Setting this point affects the [member size]. + The ending point. This is usually the corner on the top-right and back of the bounding box, and is equivalent to [code]position + size[/code]. Setting this point affects the [member size]. </member> <member name="position" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> - The origin point. This is usually the corner on the bottom-left and back of the bounding box. + The origin point. This is usually the corner on the bottom-left and forward of the bounding box. </member> <member name="size" type="Vector3" setter="" getter="" default="Vector3(0, 0, 0)"> The bounding box's width, height, and depth starting from [member position]. Setting this value also affects the [member end] point. - [b]Note:[/b] It's recommended setting the width, height, and depth to non-negative values. This is because most methods in Godot assume that the [member position] is the bottom-left-back corner, and the [member end] is the top-right-forward corner. To get an equivalent bounding box with non-negative size, use [method abs]. + [b]Note:[/b] It's recommended setting the width, height, and depth to non-negative values. This is because most methods in Godot assume that the [member position] is the bottom-left-forward corner, and the [member end] is the top-right-back corner. To get an equivalent bounding box with non-negative size, use [method abs]. </member> </members> <operators> diff --git a/doc/classes/AnimationMixer.xml b/doc/classes/AnimationMixer.xml index d762ffa5a6..36cb675776 100644 --- a/doc/classes/AnimationMixer.xml +++ b/doc/classes/AnimationMixer.xml @@ -112,13 +112,13 @@ The most basic example is applying position to [CharacterBody3D]: [codeblocks] [gdscript] - var current_rotation: Quaternion + var current_rotation func _process(delta): if Input.is_action_just_pressed("animate"): current_rotation = get_quaternion() state_machine.travel("Animate") - var velocity: Vector3 = current_rotation * animation_tree.get_root_motion_position() / delta + var velocity = current_rotation * animation_tree.get_root_motion_position() / delta set_velocity(velocity) move_and_slide() [/gdscript] @@ -130,7 +130,20 @@ if Input.is_action_just_pressed("animate"): state_machine.travel("Animate") set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation()) - var velocity: Vector3 = (animation_tree.get_root_motion_rotation_accumulator().inverse() * get_quaternion()) * animation_tree.get_root_motion_position() / delta + var velocity = (animation_tree.get_root_motion_rotation_accumulator().inverse() * get_quaternion()) * animation_tree.get_root_motion_position() / delta + set_velocity(velocity) + move_and_slide() + [/gdscript] + [/codeblocks] + If [member root_motion_local] is [code]true[/code], return the pre-multiplied translation value with the inverted rotation. + In this case, the code can be written as follows: + [codeblocks] + [gdscript] + func _process(delta): + if Input.is_action_just_pressed("animate"): + state_machine.travel("Animate") + set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation()) + var velocity = get_quaternion() * animation_tree.get_root_motion_position() / delta set_velocity(velocity) move_and_slide() [/gdscript] @@ -145,13 +158,13 @@ For example, if an animation with only one key [code]Vector3(0, 0, 0)[/code] is played in the previous frame and then an animation with only one key [code]Vector3(1, 0, 1)[/code] is played in the next frame, the difference can be calculated as follows: [codeblocks] [gdscript] - var prev_root_motion_position_accumulator: Vector3 + var prev_root_motion_position_accumulator func _process(delta): if Input.is_action_just_pressed("animate"): state_machine.travel("Animate") - var current_root_motion_position_accumulator: Vector3 = animation_tree.get_root_motion_position_accumulator() - var difference: Vector3 = current_root_motion_position_accumulator - prev_root_motion_position_accumulator + var current_root_motion_position_accumulator = animation_tree.get_root_motion_position_accumulator() + var difference = current_root_motion_position_accumulator - prev_root_motion_position_accumulator prev_root_motion_position_accumulator = current_root_motion_position_accumulator transform.origin += difference [/gdscript] @@ -185,13 +198,13 @@ For example, if an animation with only one key [code]Quaternion(0, 0, 0, 1)[/code] is played in the previous frame and then an animation with only one key [code]Quaternion(0, 0.707, 0, 0.707)[/code] is played in the next frame, the difference can be calculated as follows: [codeblocks] [gdscript] - var prev_root_motion_rotation_accumulator: Quaternion + var prev_root_motion_rotation_accumulator func _process(delta): if Input.is_action_just_pressed("animate"): state_machine.travel("Animate") - var current_root_motion_rotation_accumulator: Quaternion = animation_tree.get_root_motion_rotation_accumulator() - var difference: Quaternion = prev_root_motion_rotation_accumulator.inverse() * current_root_motion_rotation_accumulator + var current_root_motion_rotation_accumulator = animation_tree.get_root_motion_rotation_accumulator() + var difference = prev_root_motion_rotation_accumulator.inverse() * current_root_motion_rotation_accumulator prev_root_motion_rotation_accumulator = current_root_motion_rotation_accumulator transform.basis *= Basis(difference) [/gdscript] @@ -208,8 +221,8 @@ The most basic example is applying scale to [CharacterBody3D]: [codeblocks] [gdscript] - var current_scale: Vector3 = Vector3(1, 1, 1) - var scale_accum: Vector3 = Vector3(1, 1, 1) + var current_scale = Vector3(1, 1, 1) + var scale_accum = Vector3(1, 1, 1) func _process(delta): if Input.is_action_just_pressed("animate"): @@ -229,13 +242,13 @@ For example, if an animation with only one key [code]Vector3(1, 1, 1)[/code] is played in the previous frame and then an animation with only one key [code]Vector3(2, 2, 2)[/code] is played in the next frame, the difference can be calculated as follows: [codeblocks] [gdscript] - var prev_root_motion_scale_accumulator: Vector3 + var prev_root_motion_scale_accumulator func _process(delta): if Input.is_action_just_pressed("animate"): state_machine.travel("Animate") - var current_root_motion_scale_accumulator: Vector3 = animation_tree.get_root_motion_scale_accumulator() - var difference: Vector3 = current_root_motion_scale_accumulator - prev_root_motion_scale_accumulator + var current_root_motion_scale_accumulator = animation_tree.get_root_motion_scale_accumulator() + var difference = current_root_motion_scale_accumulator - prev_root_motion_scale_accumulator prev_root_motion_scale_accumulator = current_root_motion_scale_accumulator transform.basis = transform.basis.scaled(difference) [/gdscript] @@ -304,6 +317,9 @@ This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation (the animation with the key [code]"RESET"[/code]) applied as if it had been seeked to time 0, with the editor keeping the values that the scene had before saving. This makes it more convenient to preview and edit animations in the editor, as changes to the scene will not be saved as long as they are set in the reset animation. </member> + <member name="root_motion_local" type="bool" setter="set_root_motion_local" getter="is_root_motion_local"> + If [code]true[/code], [method get_root_motion_position] value is extracted as a local translation value before blending. In other words, it is treated like the translation is done after the rotation. + </member> <member name="root_motion_track" type="NodePath" setter="set_root_motion_track" getter="get_root_motion_track" default="NodePath("")"> The path to the Animation track used for root motion. Paths must be valid scene-tree paths to a node, and must be specified starting from the parent node of the node that will reproduce the animation. The [member root_motion_track] uses the same format as [method Animation.track_set_path], but note that a bone must be specified. If the track has type [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_ROTATION_3D], or [constant Animation.TYPE_SCALE_3D] the transformation will be canceled visually, and the animation will appear to stay in place. See also [method get_root_motion_position], [method get_root_motion_rotation], [method get_root_motion_scale], and [RootMotionView]. diff --git a/doc/classes/AnimationNodeTimeSeek.xml b/doc/classes/AnimationNodeTimeSeek.xml index d00b3fca3a..865e94ec43 100644 --- a/doc/classes/AnimationNodeTimeSeek.xml +++ b/doc/classes/AnimationNodeTimeSeek.xml @@ -30,4 +30,9 @@ <tutorials> <link title="Using AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> + <members> + <member name="explicit_elapse" type="bool" setter="set_explicit_elapse" getter="is_explicit_elapse" default="true"> + If [code]true[/code], some processes are executed to handle keys between seeks, such as calculating root motion and finding the nearest discrete key. + </member> + </members> </class> diff --git a/doc/classes/FileAccess.xml b/doc/classes/FileAccess.xml index d7ca8afc2c..846897a463 100644 --- a/doc/classes/FileAccess.xml +++ b/doc/classes/FileAccess.xml @@ -173,6 +173,12 @@ Returns the next 32 bits from the file as a floating-point number. </description> </method> + <method name="get_half" qualifiers="const"> + <return type="float" /> + <description> + Returns the next 16 bits from the file as a half-precision floating-point number. + </description> + </method> <method name="get_hidden_attribute" qualifiers="static"> <return type="bool" /> <param index="0" name="file" type="String" /> @@ -471,6 +477,13 @@ Stores a floating-point number as 32 bits in the file. </description> </method> + <method name="store_half"> + <return type="void" /> + <param index="0" name="value" type="float" /> + <description> + Stores a half-precision floating-point number as 16 bits in the file. + </description> + </method> <method name="store_line"> <return type="void" /> <param index="0" name="line" type="String" /> diff --git a/doc/classes/LookAtModifier3D.xml b/doc/classes/LookAtModifier3D.xml index e85da06c3a..b6d106c4c5 100644 --- a/doc/classes/LookAtModifier3D.xml +++ b/doc/classes/LookAtModifier3D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="LookAtModifier3D" inherits="SkeletonModifier3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - The [SkeletonModifier3D] rotates a bone to look a target. + The [LookAtModifier3D] rotates a bone to look at a target. </brief_description> <description> - This [SkeletonModifier3D] rotates a bone to look a target. This is helpful for moving character's head to look at the player, rotating a turret to look at a target, or any other case where you want to make a bone rotate towards something quickly and easily. + This [SkeletonModifier3D] rotates a bone to look at a target. This is helpful for moving a character's head to look at the player, rotating a turret to look at a target, or any other case where you want to make a bone rotate towards something quickly and easily. When applying multiple [LookAtModifier3D]s, the [LookAtModifier3D] assigned to the parent bone must be put above the [LookAtModifier3D] assigned to the child bone in the list in order for the child bone results to be correct. </description> <tutorials> diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml index cfaf012a55..b82d0de350 100644 --- a/doc/classes/PackedInt64Array.xml +++ b/doc/classes/PackedInt64Array.xml @@ -6,7 +6,7 @@ <description> An array specifically designed to hold 64-bit integer values. Packs data tightly, so it saves memory for large array sizes. [b]Note:[/b] This type stores signed 64-bit integers, which means it can take values in the interval [code][-2^63, 2^63 - 1][/code], i.e. [code][-9223372036854775808, 9223372036854775807][/code]. Exceeding those bounds will wrap around. If you only need to pack 32-bit integers tightly, see [PackedInt32Array] for a more memory-friendly alternative. - [b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedInt32Array] versus [code]Array[int][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays. + [b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedInt64Array] versus [code]Array[int][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays. [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again. </description> <tutorials> diff --git a/doc/classes/PackedVector4Array.xml b/doc/classes/PackedVector4Array.xml index 6dbfc7413d..7bebee79c7 100644 --- a/doc/classes/PackedVector4Array.xml +++ b/doc/classes/PackedVector4Array.xml @@ -5,6 +5,7 @@ </brief_description> <description> An array specifically designed to hold [Vector4]. Packs data tightly, so it saves memory for large array sizes. + [b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedVector4Array] versus [code]Array[Vector4][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays. [b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again. </description> <tutorials> diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml index ad5c5472b8..acff5cf604 100644 --- a/doc/classes/StreamPeer.xml +++ b/doc/classes/StreamPeer.xml @@ -59,6 +59,12 @@ Gets a single-precision float from the stream. </description> </method> + <method name="get_half"> + <return type="float" /> + <description> + Gets a half-precision float from the stream. + </description> + </method> <method name="get_partial_data"> <return type="Array" /> <param index="0" name="bytes" type="int" /> @@ -162,6 +168,13 @@ Puts a single-precision float into the stream. </description> </method> + <method name="put_half"> + <return type="void" /> + <param index="0" name="value" type="float" /> + <description> + Puts a half-precision float into the stream. + </description> + </method> <method name="put_partial_data"> <return type="Array" /> <param index="0" name="data" type="PackedByteArray" /> diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 2fd3f7d7e2..5fd90744a4 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -720,11 +720,14 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou } } - bool success = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization); + bool success = material_storage->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization); if (!success) { continue; } + // Bind per-batch uniforms. + material_storage->shaders.canvas_shader.version_set_uniform(CanvasShaderGLES3::BATCH_FLAGS, state.canvas_instance_batches[i].flags, shader_version, variant, specialization); + GLES3::CanvasShaderData::BlendMode blend_mode = state.canvas_instance_batches[i].blend_mode; Color blend_color = state.canvas_instance_batches[i].blend_color; @@ -847,6 +850,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend uint32_t lights[4] = { 0, 0, 0, 0 }; uint16_t light_count = 0; + uint16_t shadow_mask = 0; { Light *light = p_lights; @@ -856,6 +860,10 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend uint32_t light_index = light->render_index_cache; lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); + if (p_item->light_mask & light->item_shadow_mask) { + shadow_mask |= 1 << light_count; + } + light_count++; if (light_count == data.max_lights_per_item - 1) { @@ -865,7 +873,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend light = light->next_ptr; } - base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; + base_flags |= light_count << INSTANCE_FLAGS_LIGHT_COUNT_SHIFT; + base_flags |= shadow_mask << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT; } bool lights_disabled = light_count == 0 && !state.using_directional_lights; @@ -906,7 +915,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.instance_data_array[r_index].lights[2] = lights[2]; state.instance_data_array[r_index].lights[3] = lights[3]; - state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); // Reset on each command for safety, keep canvastexture binding config. + state.instance_data_array[r_index].flags = base_flags; Color blend_color = base_color; GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode; @@ -939,6 +948,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_RECT; state.canvas_instance_batches[state.current_batch_index].command = c; state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; + state.canvas_instance_batches[state.current_batch_index].flags = 0; } _prepare_canvas_texture(rect->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -961,20 +971,18 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend if (rect->flags & CANVAS_RECT_FLIP_H) { src_rect.size.x *= -1; - state.instance_data_array[r_index].flags |= FLAGS_FLIP_H; } if (rect->flags & CANVAS_RECT_FLIP_V) { src_rect.size.y *= -1; - state.instance_data_array[r_index].flags |= FLAGS_FLIP_V; } if (rect->flags & CANVAS_RECT_TRANSPOSE) { - state.instance_data_array[r_index].flags |= FLAGS_TRANSPOSE_RECT; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_TRANSPOSE_RECT; } if (rect->flags & CANVAS_RECT_CLIP_UV) { - state.instance_data_array[r_index].flags |= FLAGS_CLIP_RECT_UV; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_CLIP_RECT_UV; } } else { @@ -993,13 +1001,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend } if (rect->flags & CANVAS_RECT_MSDF) { - state.instance_data_array[r_index].flags |= FLAGS_USE_MSDF; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_USE_MSDF; state.instance_data_array[r_index].msdf[0] = rect->px_range; // Pixel range. state.instance_data_array[r_index].msdf[1] = rect->outline; // Outline size. state.instance_data_array[r_index].msdf[2] = 0.f; // Reserved. state.instance_data_array[r_index].msdf[3] = 0.f; // Reserved. } else if (rect->flags & CANVAS_RECT_LCD) { - state.instance_data_array[r_index].flags |= FLAGS_USE_LCD; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_USE_LCD; } state.instance_data_array[r_index].modulation[0] = rect->modulate.r * base_color.r; @@ -1030,6 +1038,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].command = c; state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_NINEPATCH; + state.canvas_instance_batches[state.current_batch_index].flags = 0; } _prepare_canvas_texture(np->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1067,11 +1076,11 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.instance_data_array[r_index].dst_rect[2] = dst_rect.size.width; state.instance_data_array[r_index].dst_rect[3] = dst_rect.size.height; - state.instance_data_array[r_index].flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT; - state.instance_data_array[r_index].flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT; + state.instance_data_array[r_index].flags |= int(np->axis_x) << INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT; + state.instance_data_array[r_index].flags |= int(np->axis_y) << INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT; if (np->draw_center) { - state.instance_data_array[r_index].flags |= FLAGS_NINEPACH_DRAW_CENTER; + state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_NINEPACH_DRAW_CENTER; } state.instance_data_array[r_index].ninepatch_margins[0] = np->margin[SIDE_LEFT]; @@ -1097,6 +1106,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].command = c; state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES; + state.canvas_instance_batches[state.current_batch_index].flags = 0; _prepare_canvas_texture(polygon->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1125,6 +1135,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].command = c; state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_PRIMITIVE; + state.canvas_instance_batches[state.current_batch_index].flags = 0; } _prepare_canvas_texture(state.canvas_instance_batches[state.current_batch_index].tex, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); @@ -1165,12 +1176,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend case Item::Command::TYPE_MESH: case Item::Command::TYPE_MULTIMESH: case Item::Command::TYPE_PARTICLES: { - // Mesh's can't be batched, so always create a new batch + // Meshes can't be batched, so always create a new batch. _new_batch(r_batch_broken); Color modulate(1, 1, 1, 1); state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask; state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES; + state.canvas_instance_batches[state.current_batch_index].flags = 0; if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c); state.canvas_instance_batches[state.current_batch_index].tex = m->texture; @@ -1183,10 +1195,10 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING; if (GLES3::MeshStorage::get_singleton()->multimesh_uses_colors(mm->multimesh)) { - state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS; } if (GLES3::MeshStorage::get_singleton()->multimesh_uses_custom_data(mm->multimesh)) { - state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA; } } else if (c->type == Item::Command::TYPE_PARTICLES) { GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton(); @@ -1196,8 +1208,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend RID particles = pt->particles; state.canvas_instance_batches[state.current_batch_index].tex = pt->texture; state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING; - state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS; - state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA; if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) { // Pass collision information. @@ -2364,15 +2376,15 @@ void RasterizerCanvasGLES3::_prepare_canvas_texture(RID p_texture, RS::CanvasIte GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map); if (ct->specular_color.a < 0.999) { - state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED; } else { - state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_SPECULAR_MAP_USED; + state.canvas_instance_batches[state.current_batch_index].flags &= ~BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED; } if (normal_map) { - state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED; } else { - state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_NORMAL_MAP_USED; + state.canvas_instance_batches[state.current_batch_index].flags &= ~BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED; } state.instance_data_array[r_index].specular_shininess = uint32_t(CLAMP(ct->specular_color.a * 255.0, 0, 255)) << 24; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index b9d9a44e2a..e099fd0cc0 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -54,29 +54,27 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender { _FORCE_INLINE_ void _update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4); enum { + INSTANCE_FLAGS_LIGHT_COUNT_SHIFT = 0, // 4 bits for light count. - FLAGS_INSTANCING_MASK = 0x7F, - FLAGS_INSTANCING_HAS_COLORS = (1 << 7), - FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), + INSTANCE_FLAGS_CLIP_RECT_UV = (1 << 4), + INSTANCE_FLAGS_TRANSPOSE_RECT = (1 << 5), + INSTANCE_FLAGS_USE_MSDF = (1 << 6), + INSTANCE_FLAGS_USE_LCD = (1 << 7), - FLAGS_CLIP_RECT_UV = (1 << 9), - FLAGS_TRANSPOSE_RECT = (1 << 10), + INSTANCE_FLAGS_NINEPACH_DRAW_CENTER = (1 << 8), + INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT = 9, + INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT = 11, - FLAGS_NINEPACH_DRAW_CENTER = (1 << 12), - - FLAGS_USE_SKELETON = (1 << 15), - FLAGS_NINEPATCH_H_MODE_SHIFT = 16, - FLAGS_NINEPATCH_V_MODE_SHIFT = 18, - FLAGS_LIGHT_COUNT_SHIFT = 20, - - FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26), - FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), + INSTANCE_FLAGS_SHADOW_MASKED_SHIFT = 13, // 16 bits. + }; - FLAGS_USE_MSDF = (1 << 28), - FLAGS_USE_LCD = (1 << 29), + enum { + BATCH_FLAGS_INSTANCING_MASK = 0x7F, + BATCH_FLAGS_INSTANCING_HAS_COLORS = (1 << 7), + BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), - FLAGS_FLIP_H = (1 << 30), - FLAGS_FLIP_V = (1 << 31), + BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 9), + BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 10), }; enum { @@ -279,6 +277,8 @@ public: const Item::Command *command = nullptr; Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch. uint32_t primitive_points = 0; + + uint32_t flags = 0; }; // DataBuffer contains our per-frame data. I.e. the resources that are updated each frame. diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 1ac289d5a2..3857aa8841 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -110,6 +110,9 @@ layout(std140) uniform MaterialUniforms{ //ubo:4 }; #endif + +uniform mediump uint batch_flags; + /* clang-format on */ #include "canvas_uniforms_inc.glsl" @@ -179,13 +182,13 @@ void main() { vec2 uv = uv_attrib; #ifdef USE_INSTANCING - if (bool(read_draw_data_flags & FLAGS_INSTANCING_HAS_COLORS)) { + if (bool(batch_flags & BATCH_FLAGS_INSTANCING_HAS_COLORS)) { vec4 instance_color; instance_color.xy = unpackHalf2x16(uint(instance_color_custom_data.x)); instance_color.zw = unpackHalf2x16(uint(instance_color_custom_data.y)); color *= instance_color; } - if (bool(read_draw_data_flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { + if (bool(batch_flags & BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { instance_custom.xy = unpackHalf2x16(instance_color_custom_data.z); instance_custom.zw = unpackHalf2x16(instance_color_custom_data.w); } @@ -218,7 +221,7 @@ void main() { else if (vertex_id == 5) vertex_base = vec2(1.0, 1.0); - vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy); + vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & INSTANCE_FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy); vec4 color = read_draw_data_modulation; vec2 vertex = read_draw_data_dst_rect.xy + abs(read_draw_data_dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(read_draw_data_src_rect.zw, vec2(0.0, 0.0))); @@ -336,6 +339,8 @@ uniform sampler2D specular_texture; //texunit:-7 uniform sampler2D color_texture; //texunit:0 +uniform mediump uint batch_flags; + layout(location = 0) out vec4 frag_color; /* clang-format off */ @@ -519,7 +524,7 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo } else if (pixel >= draw_size - margin_end) { return (tex_size - (draw_size - pixel)) * tex_pixel_size; } else { - if (!bool(read_draw_data_flags & FLAGS_NINEPACH_DRAW_CENTER)) { + if (!bool(read_draw_data_flags & INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER)) { draw_center--; } @@ -567,8 +572,8 @@ void main() { int draw_center = 2; uv = vec2( - map_ninepatch_axis(pixel_size_interp.x, abs(read_draw_data_dst_rect_z), read_draw_data_color_texture_pixel_size.x, read_draw_data_ninepatch_margins.x, read_draw_data_ninepatch_margins.z, int(read_draw_data_flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center), - map_ninepatch_axis(pixel_size_interp.y, abs(read_draw_data_dst_rect_w), read_draw_data_color_texture_pixel_size.y, read_draw_data_ninepatch_margins.y, read_draw_data_ninepatch_margins.w, int(read_draw_data_flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center)); + map_ninepatch_axis(pixel_size_interp.x, abs(read_draw_data_dst_rect_z), read_draw_data_color_texture_pixel_size.x, read_draw_data_ninepatch_margins.x, read_draw_data_ninepatch_margins.z, int(read_draw_data_flags >> INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center), + map_ninepatch_axis(pixel_size_interp.y, abs(read_draw_data_dst_rect_w), read_draw_data_color_texture_pixel_size.y, read_draw_data_ninepatch_margins.y, read_draw_data_ninepatch_margins.w, int(read_draw_data_flags >> INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center)); if (draw_center == 0) { color.a = 0.0; @@ -577,7 +582,7 @@ void main() { uv = uv * read_draw_data_src_rect.zw + read_draw_data_src_rect.xy; //apply region if needed #endif - if (bool(read_draw_data_flags & FLAGS_CLIP_RECT_UV)) { + if (bool(read_draw_data_flags & INSTANCE_FLAGS_CLIP_RECT_UV)) { vec2 half_texpixel = read_draw_data_color_texture_pixel_size * 0.5; uv = clamp(uv, read_draw_data_src_rect.xy + half_texpixel, read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) - half_texpixel); } @@ -585,7 +590,7 @@ void main() { #endif #ifndef USE_PRIMITIVE - if (bool(read_draw_data_flags & FLAGS_USE_MSDF)) { + if (bool(read_draw_data_flags & INSTANCE_FLAGS_USE_MSDF)) { float px_range = read_draw_data_ninepatch_margins.x; float outline_thickness = read_draw_data_ninepatch_margins.y; @@ -603,7 +608,7 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - } else if (bool(read_draw_data_flags & FLAGS_USE_LCD)) { + } else if (bool(read_draw_data_flags & INSTANCE_FLAGS_USE_LCD)) { vec4 lcd_sample = texture(color_texture, uv); if (lcd_sample.a == 1.0) { color.rgb = lcd_sample.rgb * color.a; @@ -617,7 +622,7 @@ void main() { color *= texture(color_texture, uv); } - uint light_count = (read_draw_data_flags >> uint(FLAGS_LIGHT_COUNT_SHIFT)) & uint(0xF); //max 16 lights + uint light_count = read_draw_data_flags & uint(0xF); // Max 16 lights. bool using_light = light_count > 0u || directional_light_count > 0u; vec3 normal; @@ -628,17 +633,16 @@ void main() { bool normal_used = false; #endif - if (normal_used || (using_light && bool(read_draw_data_flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { + if (normal_used || (using_light && bool(batch_flags & BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED))) { normal.xy = texture(normal_texture, uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); - if (bool(read_draw_data_flags & FLAGS_TRANSPOSE_RECT)) { + +#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) + if (bool(read_draw_data_flags & INSTANCE_FLAGS_TRANSPOSE_RECT)) { normal.xy = normal.yx; } - if (bool(read_draw_data_flags & FLAGS_FLIP_H)) { - normal.x = -normal.x; - } - if (bool(read_draw_data_flags & FLAGS_FLIP_V)) { - normal.y = -normal.y; - } + normal.xy *= sign(read_draw_data_src_rect.zw); +#endif + normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy, normal.xy))); normal_used = true; } else { @@ -654,7 +658,7 @@ void main() { bool specular_shininess_used = false; #endif - if (specular_shininess_used || (using_light && normal_used && bool(read_draw_data_flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { + if (specular_shininess_used || (using_light && normal_used && bool(batch_flags & BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED))) { specular_shininess = texture(specular_texture, uv); specular_shininess *= godot_unpackUnorm4x8(read_draw_data_specular_shininess); specular_shininess_used = true; @@ -727,7 +731,7 @@ void main() { } #endif - if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(read_draw_data_flags & uint(INSTANCE_FLAGS_SHADOW_MASKED << i))) { vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array[light_base].shadow_matrix[0], light_array[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. vec4 shadow_uv = vec4(shadow_pos.x, light_array[light_base].shadow_y_ofs, shadow_pos.y * light_array[light_base].shadow_zfar_inv, 1.0); @@ -802,7 +806,7 @@ void main() { } #endif - if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(read_draw_data_flags & uint(INSTANCE_FLAGS_SHADOW_MASKED << i))) { vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array[light_base].shadow_matrix[0], light_array[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. vec2 pos_norm = normalize(shadow_pos); diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl index f6ad2b730a..7abd5f0eee 100644 --- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl +++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl @@ -5,29 +5,29 @@ #define SDF_MAX_LENGTH 16384.0 -//1 means enabled, 2+ means trails in use -#define FLAGS_INSTANCING_MASK uint(0x7F) -#define FLAGS_INSTANCING_HAS_COLORS uint(1 << 7) -#define FLAGS_INSTANCING_HAS_CUSTOM_DATA uint(1 << 8) +#define INSTANCE_FLAGS_LIGHT_COUNT_SHIFT 0 // 4 bits. -#define FLAGS_CLIP_RECT_UV uint(1 << 9) -#define FLAGS_TRANSPOSE_RECT uint(1 << 10) -// (1 << 11) is for FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR in RD backends, unused here. -#define FLAGS_NINEPACH_DRAW_CENTER uint(1 << 12) +#define INSTANCE_FLAGS_CLIP_RECT_UV uint(1 << 4) +#define INSTANCE_FLAGS_TRANSPOSE_RECT uint(1 << 5) +#define INSTANCE_FLAGS_USE_MSDF uint(1 << 6) +#define INSTANCE_FLAGS_USE_LCD uint(1 << 7) -#define FLAGS_NINEPATCH_H_MODE_SHIFT 16 -#define FLAGS_NINEPATCH_V_MODE_SHIFT 18 +#define INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER uint(1 << 8) +#define INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT 9 +#define INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT 11 -#define FLAGS_LIGHT_COUNT_SHIFT 20 +#define INSTANCE_FLAGS_SHADOW_MASKED_SHIFT 13u // 16 bits. +#define INSTANCE_FLAGS_SHADOW_MASKED uint(1 << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT) -#define FLAGS_DEFAULT_NORMAL_MAP_USED uint(1 << 26) -#define FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 27) +// 1 means enabled, 2+ means trails in use +#define BATCH_FLAGS_INSTANCING_MASK uint(0x7F) +#define BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT 7 +#define BATCH_FLAGS_INSTANCING_HAS_COLORS uint(1 << BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT) +#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8 +#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA uint(1 << BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT) -#define FLAGS_USE_MSDF uint(1 << 28) -#define FLAGS_USE_LCD uint(1 << 29) - -#define FLAGS_FLIP_H uint(1 << 30) -#define FLAGS_FLIP_V uint(1 << 31) +#define BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED uint(1 << 9) +#define BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 10) layout(std140) uniform GlobalShaderUniformData { //ubo:1 vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 91c9ff9807..27216c2399 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -1495,7 +1495,15 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<String> forced_export = get_forced_export_files(); for (int i = 0; i < forced_export.size(); i++) { - Vector<uint8_t> array = FileAccess::get_file_as_bytes(forced_export[i]); + Vector<uint8_t> array; + if (GDExtension::get_extension_list_config_file() == forced_export[i]) { + array = _filter_extension_list_config_file(forced_export[i], paths); + if (array.size() == 0) { + continue; + } + } else { + array = FileAccess::get_file_as_bytes(forced_export[i]); + } err = p_save_func(p_udata, forced_export[i], array, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; @@ -1534,6 +1542,22 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & return OK; } +Vector<uint8_t> EditorExportPlatform::_filter_extension_list_config_file(const String &p_config_path, const HashSet<String> &p_paths) { + Ref<FileAccess> f = FileAccess::open(p_config_path, FileAccess::READ); + if (f.is_null()) { + ERR_FAIL_V_MSG(Vector<uint8_t>(), "Can't open file from path '" + String(p_config_path) + "'."); + } + Vector<uint8_t> data; + while (!f->eof_reached()) { + String l = f->get_line().strip_edges(); + if (p_paths.has(l)) { + data.append_array(l.to_utf8_buffer()); + data.append('\n'); + } + } + return data; +} + Error EditorExportPlatform::_pack_add_shared_object(void *p_userdata, const SharedObject &p_so) { PackData *pack_data = (PackData *)p_userdata; if (pack_data->so_files) { diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h index c7378ffec7..a33bdce72a 100644 --- a/editor/export/editor_export_platform.h +++ b/editor/export/editor_export_platform.h @@ -135,6 +135,8 @@ private: void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, HashSet<String> &r_list, bool exclude); void _edit_filter_list(HashSet<String> &r_list, const String &p_filter, bool exclude); + static Vector<uint8_t> _filter_extension_list_config_file(const String &p_config_path, const HashSet<String> &p_paths); + struct FileExportCache { uint64_t source_modified_time = 0; String source_md5; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index f91a052a24..d3bae447cc 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -3612,7 +3612,7 @@ void CanvasItemEditor::_draw_selection() { // Remove non-movable nodes. for (CanvasItem *ci : selection) { - if (!_is_node_movable(ci, true)) { + if (!_is_node_movable(ci)) { selection.erase(ci); } } @@ -3913,7 +3913,7 @@ void CanvasItemEditor::_draw_message() { Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label")); int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label")); - Point2 msgpos = Point2(RULER_WIDTH + 5 * EDSCALE, viewport->get_size().y - 20 * EDSCALE); + Point2 msgpos = Point2(RULER_WIDTH + 10 * EDSCALE, viewport->get_size().y - 14 * EDSCALE); viewport->draw_string(font, msgpos + Point2(1, 1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); viewport->draw_string(font, msgpos + Point2(-1, -1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); viewport->draw_string(font, msgpos, message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 1)); diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp index 4cff3504f5..3f21d5d11c 100644 --- a/editor/plugins/lightmap_gi_editor_plugin.cpp +++ b/editor/plugins/lightmap_gi_editor_plugin.cpp @@ -152,7 +152,7 @@ EditorProgress *LightmapGIEditorPlugin::tmp_progress = nullptr; bool LightmapGIEditorPlugin::bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh) { if (!tmp_progress) { - tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, false)); + tmp_progress = memnew(EditorProgress("bake_lightmaps", TTR("Bake Lightmaps"), 1000, true)); ERR_FAIL_NULL_V(tmp_progress, false); } return tmp_progress->step(p_description, p_progress * 1000, p_refresh); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 810d1674ca..daede895b5 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -3265,7 +3265,7 @@ void Node3DEditorViewport::_draw() { if (message_time > 0) { Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label")); int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label")); - Point2 msgpos = Point2(5, get_size().y - 20); + Point2 msgpos = Point2(10 * EDSCALE, get_size().y - 14 * EDSCALE); font->draw_string(ci, msgpos + Point2(1, 1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); font->draw_string(ci, msgpos + Point2(-1, -1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); font->draw_string(ci, msgpos, message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 1)); diff --git a/main/performance.cpp b/main/performance.cpp index c73fb62b76..398511995b 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -132,11 +132,9 @@ String Performance::get_monitor_name(Monitor p_monitor) const { PNAME("physics_2d/active_objects"), PNAME("physics_2d/collision_pairs"), PNAME("physics_2d/islands"), -#ifndef _3D_DISABLED PNAME("physics_3d/active_objects"), PNAME("physics_3d/collision_pairs"), PNAME("physics_3d/islands"), -#endif // _3D_DISABLED PNAME("audio/driver/output_latency"), PNAME("navigation/active_maps"), PNAME("navigation/regions"), @@ -280,11 +278,9 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, -#ifndef _3D_DISABLED MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, -#endif // _3D_DISABLED MONITOR_TYPE_TIME, MONITOR_TYPE_QUANTITY, MONITOR_TYPE_QUANTITY, diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index d58cd2c3f7..cfff20f6d3 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -1139,10 +1139,12 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, continue; } option = ScriptLanguage::CodeCompletionOption(member.function->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (member.function->parameters.size() > 0) { + if (member.function->parameters.size() > 0 || (member.function->info.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } break; case GDScriptParser::ClassNode::Member::SIGNAL: @@ -1184,6 +1186,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base if (!p_types_only && base_type.is_meta_type && base_type.kind != GDScriptParser::DataType::BUILTIN && base_type.kind != GDScriptParser::DataType::ENUM) { ScriptLanguage::CodeCompletionOption option("new", ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, ScriptLanguage::LOCATION_LOCAL); option.insert_text += "("; + option.display += U"(\u2026)"; r_result.insert(option.display, option); } @@ -1241,10 +1244,12 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } int location = p_recursion_depth + _get_method_location(scr->get_class_name(), E.name); ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size()) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } r_result.insert(option.display, option); } @@ -1327,10 +1332,12 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } int location = p_recursion_depth + _get_method_location(type, E.name); ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size()) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } r_result.insert(option.display, option); } @@ -1398,10 +1405,12 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base continue; } ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size()) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } r_result.insert(option.display, option); } @@ -1433,8 +1442,10 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context ScriptLanguage::CodeCompletionOption option(String(E), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); if (function.arguments.size() || (function.flags & METHOD_FLAG_VARARG)) { option.insert_text += "("; + option.display += U"(\u2026)"; } else { option.insert_text += "()"; + option.display += "()"; } r_result.insert(option.display, option); } @@ -1481,6 +1492,7 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context while (*kwa) { ScriptLanguage::CodeCompletionOption option(*kwa, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); option.insert_text += "("; + option.display += U"(\u2026)"; r_result.insert(option.display, option); kwa++; } @@ -1491,6 +1503,7 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context for (List<StringName>::Element *E = utility_func_names.front(); E; E = E->next()) { ScriptLanguage::CodeCompletionOption option(E->get(), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); option.insert_text += "("; + option.display += U"(\u2026)"; // As all utility functions contain an argument or more, this is hardcoded here. r_result.insert(option.display, option); } diff --git a/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute.cfg b/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute.cfg index e4759ac76b..a2c332adad 100644 --- a/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute.cfg +++ b/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute.cfg @@ -1,6 +1,6 @@ [output] include=[ - {"display": "new"}, + {"display": "new(…)"}, {"display": "SIZE_EXPAND"}, {"display": "SIZE_EXPAND_FILL"}, {"display": "SIZE_FILL"}, diff --git a/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute_identifier.cfg b/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute_identifier.cfg index e4759ac76b..a2c332adad 100644 --- a/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute_identifier.cfg +++ b/modules/gdscript/tests/scripts/completion/assignment_options/enum_attribute_identifier.cfg @@ -1,6 +1,6 @@ [output] include=[ - {"display": "new"}, + {"display": "new(…)"}, {"display": "SIZE_EXPAND"}, {"display": "SIZE_EXPAND_FILL"}, {"display": "SIZE_FILL"}, diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg index 5f08f9c265..f2dff734b6 100644 --- a/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg +++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg @@ -2,13 +2,13 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: identifiers.gd @@ -16,8 +16,8 @@ include=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, {"display": "test_parameter_1"}, {"display": "test_parameter_2"}, {"display": "local_test_var_1"}, diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg index 5f08f9c265..f2dff734b6 100644 --- a/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg +++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg @@ -2,13 +2,13 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: identifiers.gd @@ -16,8 +16,8 @@ include=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, {"display": "test_parameter_1"}, {"display": "test_parameter_2"}, {"display": "local_test_var_1"}, diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg index 5f08f9c265..f2dff734b6 100644 --- a/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg +++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg @@ -2,13 +2,13 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: identifiers.gd @@ -16,8 +16,8 @@ include=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, {"display": "test_parameter_1"}, {"display": "test_parameter_2"}, {"display": "local_test_var_1"}, diff --git a/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg index 462846c9b2..e012919051 100644 --- a/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg +++ b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg @@ -2,14 +2,14 @@ scene="res://completion/get_node/get_node.tscn" [output] exclude=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, - {"display": "add_child"}, + {"display": "add_child(…)"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: no_completion_in_string.gd @@ -17,8 +17,8 @@ exclude=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, {"display": "test_parameter_1"}, {"display": "test_parameter_2"}, {"display": "local_test_var_1"}, diff --git a/modules/gdscript/tests/scripts/completion/common/self.cfg b/modules/gdscript/tests/scripts/completion/common/self.cfg index 871a404e3a..dcce1df0d0 100644 --- a/modules/gdscript/tests/scripts/completion/common/self.cfg +++ b/modules/gdscript/tests/scripts/completion/common/self.cfg @@ -2,13 +2,13 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ; GDScript: self.gd @@ -16,6 +16,6 @@ include=[ {"display": "test_signal_2"}, {"display": "test_var_1"}, {"display": "test_var_2"}, - {"display": "test_func_1"}, - {"display": "test_func_2"}, + {"display": "test_func_1(…)"}, + {"display": "test_func_2(…)"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal/dollar.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal/dollar.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal/dollar.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal/dollar.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal/percent.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal/percent.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal/percent.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal/percent.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_class_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_class_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_class_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_class_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_native_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_native_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_native_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/dollar_native_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_class_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_class_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_class_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_class_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_native_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_native_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_native_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/literal_scene/percent_native_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local/local.cfg b/modules/gdscript/tests/scripts/completion/get_node/local/local.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local/local.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local/local.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_scene/class_local_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_scene/class_local_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_scene/class_local_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_scene/class_local_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_scene/native_local_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_scene/native_local_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_scene/native_local_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_scene/native_local_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint/class_local_typehint.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint/class_local_typehint.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint/class_local_typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint/class_local_typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint/native_local_typehint.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint/native_local_typehint.cfg index 72c0549d3b..d647135bc6 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint/native_local_typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint/native_local_typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/class_local_typehint_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/class_local_typehint_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/class_local_typehint_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/class_local_typehint_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/native_local_typehint_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/native_local_typehint_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/native_local_typehint_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene/native_local_typehint_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/class_local_typehint_scene_broad.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/class_local_typehint_scene_broad.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/class_local_typehint_scene_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/class_local_typehint_scene_broad.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/native_local_typehint_scene_broad.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/native_local_typehint_scene_broad.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/native_local_typehint_scene_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_broad/native_local_typehint_scene_broad.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/class_local_typehint_scene_incompatible.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/class_local_typehint_scene_incompatible.cfg index 1894e72c65..a6118908de 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/class_local_typehint_scene_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/class_local_typehint_scene_incompatible.cfg @@ -3,18 +3,18 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; Area2D - {"display": "get_overlapping_areas"}, + {"display": "get_overlapping_areas()"}, {"display": "linear_damp"}, {"display": "area_entered"}, ] exclude=[ ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/native_local_typehint_scene_incompatible.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/native_local_typehint_scene_incompatible.cfg index c8ab63f6d6..d8390ca33c 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/native_local_typehint_scene_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/local_typehint_scene_incompatible/native_local_typehint_scene_incompatible.cfg @@ -3,18 +3,18 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; Area2D - {"display": "get_overlapping_areas"}, + {"display": "get_overlapping_areas()"}, {"display": "linear_damp"}, {"display": "area_entered"}, ] exclude=[ ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member/member.cfg b/modules/gdscript/tests/scripts/completion/get_node/member/member.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member/member.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member/member.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg index ae7d34d87d..319c5121b5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg @@ -1,7 +1,7 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_scene/class_member_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_scene/class_member_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_scene/class_member_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_scene/class_member_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_scene/native_member_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_scene/native_member_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_scene/native_member_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_scene/native_member_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint/class_member_typehint.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint/class_member_typehint.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint/class_member_typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint/class_member_typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint/native_member_typehint.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint/native_member_typehint.cfg index 72c0549d3b..d647135bc6 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint/native_member_typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint/native_member_typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/class_member_typehint_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/class_member_typehint_scene.cfg index 9c580b711d..7518bf5ae5 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/class_member_typehint_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/class_member_typehint_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/native_member_typehint_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/native_member_typehint_scene.cfg index 446198dd35..174fdcb184 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/native_member_typehint_scene.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene/native_member_typehint_scene.cfg @@ -3,12 +3,12 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/class_member_typehint_scene_broad.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/class_member_typehint_scene_broad.cfg index 502038bef7..2f747e0bac 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/class_member_typehint_scene_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/class_member_typehint_scene_broad.cfg @@ -3,7 +3,7 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, @@ -11,6 +11,6 @@ include=[ exclude=[ ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/native_member_typehint_scene_broad.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/native_member_typehint_scene_broad.cfg index 1810e9fe5f..f060413898 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/native_member_typehint_scene_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_broad/native_member_typehint_scene_broad.cfg @@ -3,7 +3,7 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, @@ -11,6 +11,6 @@ include=[ exclude=[ ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/class_member_typehint_scene_incompatible.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/class_member_typehint_scene_incompatible.cfg index 1894e72c65..a6118908de 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/class_member_typehint_scene_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/class_member_typehint_scene_incompatible.cfg @@ -3,18 +3,18 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; Area2D - {"display": "get_overlapping_areas"}, + {"display": "get_overlapping_areas()"}, {"display": "linear_damp"}, {"display": "area_entered"}, ] exclude=[ ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/native_member_typehint_scene_incompatible.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/native_member_typehint_scene_incompatible.cfg index c8ab63f6d6..d8390ca33c 100644 --- a/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/native_member_typehint_scene_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/get_node/member_typehint_scene_incompatible/native_member_typehint_scene_incompatible.cfg @@ -3,18 +3,18 @@ scene="res://completion/get_node/get_node.tscn" [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; Area2D - {"display": "get_overlapping_areas"}, + {"display": "get_overlapping_areas()"}, {"display": "linear_damp"}, {"display": "area_entered"}, ] exclude=[ ; AnimationPlayer {"display": "autoplay"}, - {"display": "play"}, + {"display": "play(…)"}, {"display": "animation_changed"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/infered.cfg b/modules/gdscript/tests/scripts/completion/types/local/infered.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/infered.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/infered.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/no_type.cfg b/modules/gdscript/tests/scripts/completion/types/local/no_type.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/no_type.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/no_type.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/typehint.cfg b/modules/gdscript/tests/scripts/completion/types/local/typehint.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/typehint_broad.cfg b/modules/gdscript/tests/scripts/completion/types/local/typehint_broad.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/typehint_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/typehint_broad.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/local/typehint_incompatible.cfg b/modules/gdscript/tests/scripts/completion/types/local/typehint_incompatible.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/local/typehint_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/types/local/typehint_incompatible.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/infered.cfg b/modules/gdscript/tests/scripts/completion/types/member/infered.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/infered.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/infered.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/no_type.cfg b/modules/gdscript/tests/scripts/completion/types/member/no_type.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/no_type.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/no_type.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/typehint.cfg b/modules/gdscript/tests/scripts/completion/types/member/typehint.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/typehint.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/typehint.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/typehint_broad.cfg b/modules/gdscript/tests/scripts/completion/types/member/typehint_broad.cfg index 81401316ec..d32bbac65e 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/typehint_broad.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/typehint_broad.cfg @@ -1,13 +1,13 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ] exclude=[ ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/gdscript/tests/scripts/completion/types/member/typehint_incompatible.cfg b/modules/gdscript/tests/scripts/completion/types/member/typehint_incompatible.cfg index 8b68d51a89..050b0d61a3 100644 --- a/modules/gdscript/tests/scripts/completion/types/member/typehint_incompatible.cfg +++ b/modules/gdscript/tests/scripts/completion/types/member/typehint_incompatible.cfg @@ -1,12 +1,12 @@ [output] include=[ ; Node - {"display": "add_child"}, + {"display": "add_child(…)"}, {"display": "owner"}, {"display": "child_entered_tree"}, ; GDScript: class_a.notest.gd {"display": "property_of_a"}, - {"display": "func_of_a"}, + {"display": "func_of_a()"}, {"display": "signal_of_a"}, ] diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 8ba6f9e2ba..bd71e29d0a 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -247,7 +247,9 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ } if (p_step_function) { - p_step_function(0.1, RTR("Determining optimal atlas size"), p_bake_userdata, true); + if (p_step_function(0.1, RTR("Determining optimal atlas size"), p_bake_userdata, true)) { + return BAKE_ERROR_USER_ABORTED; + } } atlas_size = Size2i(max, max); @@ -324,7 +326,9 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ emission_images.resize(atlas_slices); if (p_step_function) { - p_step_function(0.2, RTR("Blitting albedo and emission"), p_bake_userdata, true); + if (p_step_function(0.2, RTR("Blitting albedo and emission"), p_bake_userdata, true)) { + return BAKE_ERROR_USER_ABORTED; + } } for (int i = 0; i < atlas_slices; i++) { @@ -1013,7 +1017,9 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh if (p_step_function) { int percent = (s + 1) * 100 / p_atlas_slices; float p = float(s) / p_atlas_slices * 0.1; - p_step_function(0.8 + p, vformat(RTR("Denoising %d%%"), percent), p_bake_userdata, false); + if (p_step_function(0.8 + p, vformat(RTR("Denoising %d%%"), percent), p_bake_userdata, false)) { + return BAKE_ERROR_USER_ABORTED; + } } } @@ -1265,7 +1271,15 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d rd->buffer_update(bake_parameters_buffer, 0, sizeof(BakeParameters), &bake_parameters); if (p_step_function) { - p_step_function(0.47, RTR("Preparing shaders"), p_bake_userdata, true); + if (p_step_function(0.47, RTR("Preparing shaders"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } //shaders @@ -1497,7 +1511,17 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d rd->sync(); if (p_step_function) { - p_step_function(0.49, RTR("Un-occluding geometry"), p_bake_userdata, true); + if (p_step_function(0.49, RTR("Un-occluding geometry"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } PushConstant push_constant; @@ -1539,7 +1563,17 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d } if (p_step_function) { - p_step_function(0.5, RTR("Plot direct lighting"), p_bake_userdata, true); + if (p_step_function(0.5, RTR("Plot direct lighting"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } // Set ray count to the quality used for direct light and bounces. @@ -1699,7 +1733,17 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d rd->sync(); if (p_step_function) { - p_step_function(0.6, RTR("Integrate indirect lighting"), p_bake_userdata, true); + if (p_step_function(0.6, RTR("Integrate indirect lighting"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } int count = 0; @@ -1738,7 +1782,17 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d int total = (atlas_slices * x_regions * y_regions * ray_iterations); int percent = count * 100 / total; float p = float(count) / total * 0.1; - p_step_function(0.6 + p, vformat(RTR("Integrate indirect lighting %d%%"), percent), p_bake_userdata, false); + if (p_step_function(0.6 + p, vformat(RTR("Integrate indirect lighting %d%%"), percent), p_bake_userdata, false)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } } } @@ -1754,7 +1808,20 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d light_probe_buffer = rd->storage_buffer_create(sizeof(float) * 4 * 9 * probe_positions.size()); if (p_step_function) { - p_step_function(0.7, RTR("Baking light probes"), p_bake_userdata, true); + if (p_step_function(0.7, RTR("Baking light probes"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + if (probe_positions.size() > 0) { + rd->free(light_probe_buffer); + } + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } Vector<RD::Uniform> uniforms; @@ -1822,7 +1889,20 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d if (p_step_function) { int percent = i * 100 / ray_iterations; float p = float(i) / ray_iterations * 0.1; - p_step_function(0.7 + p, vformat(RTR("Integrating light probes %d%%"), percent), p_bake_userdata, false); + if (p_step_function(0.7 + p, vformat(RTR("Integrating light probes %d%%"), percent), p_bake_userdata, false)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + if (probe_positions.size() > 0) { + rd->free(light_probe_buffer); + } + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } } } @@ -1844,7 +1924,20 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d if (p_use_denoiser) { if (p_step_function) { - p_step_function(0.8, RTR("Denoising"), p_bake_userdata, true); + if (p_step_function(0.8, RTR("Denoising"), p_bake_userdata, true)) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + if (probe_positions.size() > 0) { + rd->free(light_probe_buffer); + } + memdelete(rd); + if (rcd != nullptr) { + memdelete(rcd); + } + return BAKE_ERROR_USER_ABORTED; + } } { diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs index ed78353f92..a8033914e7 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs @@ -781,8 +781,18 @@ namespace Godot.SourceGenerators return false; // Non-generic Dictionary, so there's no hint to add Debug.Assert(elementTypes.Length == 2); - var keyElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[0], typeCache)!.Value; - var keyElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(keyElementMarshalType)!.Value; + var keyElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[0], typeCache); + var valueElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[1], typeCache); + + if (keyElementMarshalType == null || valueElementMarshalType == null) + { + // To maintain compatibility with previous versions of Godot before 4.4, + // we must preserve the old behavior for generic dictionaries with non-marshallable + // generic type arguments. + return false; + } + + var keyElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(keyElementMarshalType.Value)!.Value; var keyIsPresetHint = false; var keyHintString = (string?)null; @@ -809,8 +819,7 @@ namespace Godot.SourceGenerators } } - var valueElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[1], typeCache)!.Value; - var valueElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(valueElementMarshalType)!.Value; + var valueElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(valueElementMarshalType.Value)!.Value; var valueIsPresetHint = false; var valueHintString = (string?)null; diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 467873ee7c..e300bd1c47 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -3244,6 +3244,10 @@ void DisplayServerWindows::process_events() { } _THREAD_SAFE_UNLOCK_ + if (tts) { + tts->process_events(); + } + if (!drop_events) { _process_key_events(); Input::get_singleton()->flush_buffered_events(); diff --git a/platform/windows/tts_windows.cpp b/platform/windows/tts_windows.cpp index 39a8f3e120..e9ef50d736 100644 --- a/platform/windows/tts_windows.cpp +++ b/platform/windows/tts_windows.cpp @@ -43,7 +43,7 @@ void __stdcall TTS_Windows::speech_event_callback(WPARAM wParam, LPARAM lParam) } else if (event.eEventId == SPEI_END_INPUT_STREAM) { DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_ENDED, tts->ids[stream_num].id); tts->ids.erase(stream_num); - tts->_update_tts(); + tts->update_requested = true; } else if (event.eEventId == SPEI_WORD_BOUNDARY) { const Char16String &string = tts->ids[stream_num].string; int pos = 0; @@ -60,8 +60,8 @@ void __stdcall TTS_Windows::speech_event_callback(WPARAM wParam, LPARAM lParam) } } -void TTS_Windows::_update_tts() { - if (!is_speaking() && !paused && queue.size() > 0) { +void TTS_Windows::process_events() { + if (update_requested && !paused && queue.size() > 0 && !is_speaking()) { DisplayServer::TTSUtterance &message = queue.front()->get(); String text; @@ -110,6 +110,8 @@ void TTS_Windows::_update_tts() { ids[(uint32_t)stream_number] = ut; queue.pop_front(); + + update_requested = false; } } @@ -207,7 +209,7 @@ void TTS_Windows::speak(const String &p_text, const String &p_voice, int p_volum if (is_paused()) { resume(); } else { - _update_tts(); + update_requested = true; } } diff --git a/platform/windows/tts_windows.h b/platform/windows/tts_windows.h index 33b597c612..657cb608d6 100644 --- a/platform/windows/tts_windows.h +++ b/platform/windows/tts_windows.h @@ -55,9 +55,9 @@ class TTS_Windows { int id; }; HashMap<uint32_t, UTData> ids; + bool update_requested = false; static void __stdcall speech_event_callback(WPARAM wParam, LPARAM lParam); - void _update_tts(); static TTS_Windows *singleton; @@ -73,6 +73,8 @@ public: void resume(); void stop(); + void process_events(); + TTS_Windows(); ~TTS_Windows(); }; diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index cdbd95d930..aa4445a7ba 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -1189,6 +1189,8 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa return BAKE_ERROR_MESHES_INVALID; } else if (bake_err == Lightmapper::BAKE_ERROR_ATLAS_TOO_SMALL) { return BAKE_ERROR_ATLAS_TOO_SMALL; + } else if (bake_err == Lightmapper::BAKE_ERROR_USER_ABORTED) { + return BAKE_ERROR_USER_ABORTED; } // POSTBAKE: Save Textures. diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h index 9aa8ef8ccb..1228c63edc 100644 --- a/scene/3d/lightmapper.h +++ b/scene/3d/lightmapper.h @@ -147,6 +147,7 @@ public: BAKE_ERROR_TEXTURE_EXCEEDS_MAX_SIZE, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES, BAKE_ERROR_ATLAS_TOO_SMALL, + BAKE_ERROR_USER_ABORTED, }; enum BakeQuality { diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index e172286d05..d0773fc83f 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -1003,6 +1003,14 @@ String AnimationNodeTimeSeek::get_caption() const { return "TimeSeek"; } +void AnimationNodeTimeSeek::set_explicit_elapse(bool p_enable) { + explicit_elapse = p_enable; +} + +bool AnimationNodeTimeSeek::is_explicit_elapse() const { + return explicit_elapse; +} + AnimationNode::NodeTimeInfo AnimationNodeTimeSeek::_process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) { double cur_seek_pos = get_parameter(seek_pos_request); @@ -1011,7 +1019,7 @@ AnimationNode::NodeTimeInfo AnimationNodeTimeSeek::_process(const AnimationMixer if (Animation::is_greater_or_equal_approx(cur_seek_pos, 0)) { pi.time = cur_seek_pos; pi.seeked = true; - pi.is_external_seeking = true; + pi.is_external_seeking = explicit_elapse; set_parameter(seek_pos_request, -1.0); // Reset. } @@ -1022,6 +1030,12 @@ AnimationNodeTimeSeek::AnimationNodeTimeSeek() { add_input("in"); } +void AnimationNodeTimeSeek::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_explicit_elapse", "enable"), &AnimationNodeTimeSeek::set_explicit_elapse); + ClassDB::bind_method(D_METHOD("is_explicit_elapse"), &AnimationNodeTimeSeek::is_explicit_elapse); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "explicit_elapse"), "set_explicit_elapse", "is_explicit_elapse"); +} + ///////////////////////////////////////////////// bool AnimationNodeTransition::_set(const StringName &p_path, const Variant &p_value) { diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 5c912f0095..c48d799eea 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -302,6 +302,10 @@ class AnimationNodeTimeSeek : public AnimationNode { GDCLASS(AnimationNodeTimeSeek, AnimationNode); StringName seek_pos_request = PNAME("seek_request"); + bool explicit_elapse = true; + +protected: + static void _bind_methods(); public: virtual void get_parameter_list(List<PropertyInfo> *r_list) const override; @@ -311,6 +315,9 @@ public: virtual NodeTimeInfo _process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only = false) override; + void set_explicit_elapse(bool p_enable); + bool is_explicit_elapse() const; + AnimationNodeTimeSeek(); }; diff --git a/scene/animation/animation_mixer.cpp b/scene/animation/animation_mixer.cpp index 3a2adead98..d4c8af4a4c 100644 --- a/scene/animation/animation_mixer.cpp +++ b/scene/animation/animation_mixer.cpp @@ -129,6 +129,9 @@ void AnimationMixer::_validate_property(PropertyInfo &p_property) const { p_property.usage |= PROPERTY_USAGE_READ_ONLY; } #endif // TOOLS_ENABLED + if (root_motion_track.is_empty() && p_property.name == "root_motion_local") { + p_property.usage = PROPERTY_USAGE_NONE; + } } /* -------------------------------------------- */ @@ -1212,6 +1215,10 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); if (track->root_motion && calc_root) { + int rot_track = -1; + if (root_motion_local) { + rot_track = a->find_track(a->track_get_path(i), Animation::TYPE_ROTATION_3D); + } double prev_time = time - delta; if (!backward) { if (Animation::is_less_approx(prev_time, start)) { @@ -1246,41 +1253,92 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } } } - Vector3 loc[2]; - if (!backward) { - if (Animation::is_greater_approx(prev_time, time)) { - Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); - if (err != OK) { - continue; + if (rot_track >= 0) { + Vector3 loc[2]; + Quaternion rot; + if (!backward) { + if (Animation::is_greater_approx(prev_time, time)) { + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, end, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + + a->try_rotation_track_interpolate(rot_track, end, &rot); + rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx); + + root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend; + prev_time = start; } - loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); - a->try_position_track_interpolate(i, end, &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); - root_motion_cache.loc += (loc[1] - loc[0]) * blend; - prev_time = start; + } else { + if (Animation::is_less_approx(prev_time, time)) { + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, start, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + + a->try_rotation_track_interpolate(rot_track, start, &rot); + rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx); + + root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend; + prev_time = end; + } + } + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, time, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + + a->try_rotation_track_interpolate(rot_track, time, &rot); + rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx); + + root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend; + prev_time = !backward ? start : end; } else { - if (Animation::is_less_approx(prev_time, time)) { - Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); - if (err != OK) { - continue; + Vector3 loc[2]; + if (!backward) { + if (Animation::is_greater_approx(prev_time, time)) { + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, end, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + root_motion_cache.loc += (loc[1] - loc[0]) * blend; + prev_time = start; + } + } else { + if (Animation::is_less_approx(prev_time, time)) { + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, start, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + root_motion_cache.loc += (loc[1] - loc[0]) * blend; + prev_time = end; } - loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); - a->try_position_track_interpolate(i, start, &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); - root_motion_cache.loc += (loc[1] - loc[0]) * blend; - prev_time = end; } + Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); + a->try_position_track_interpolate(i, time, &loc[1]); + loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); + root_motion_cache.loc += (loc[1] - loc[0]) * blend; + prev_time = !backward ? start : end; } - Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]); - if (err != OK) { - continue; - } - loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx); - a->try_position_track_interpolate(i, time, &loc[1]); - loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx); - root_motion_cache.loc += (loc[1] - loc[0]) * blend; - prev_time = !backward ? start : end; } { Vector3 loc; @@ -1355,6 +1413,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx); a->try_rotation_track_interpolate(i, start, &rot[1]); + rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx); root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = end; } @@ -1430,8 +1489,8 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx); a->try_scale_track_interpolate(i, end, &scale[1]); - root_motion_cache.scale += (scale[1] - scale[0]) * blend; scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx); + root_motion_cache.scale += (scale[1] - scale[0]) * blend; prev_time = start; } } else { @@ -2002,12 +2061,21 @@ void AnimationMixer::clear_caches() { void AnimationMixer::set_root_motion_track(const NodePath &p_track) { root_motion_track = p_track; + notify_property_list_changed(); } NodePath AnimationMixer::get_root_motion_track() const { return root_motion_track; } +void AnimationMixer::set_root_motion_local(bool p_enabled) { + root_motion_local = p_enabled; +} + +bool AnimationMixer::is_root_motion_local() const { + return root_motion_local; +} + Vector3 AnimationMixer::get_root_motion_position() const { return root_motion_position; } @@ -2353,6 +2421,8 @@ void AnimationMixer::_bind_methods() { /* ---- Root motion accumulator for Skeleton3D ---- */ ClassDB::bind_method(D_METHOD("set_root_motion_track", "path"), &AnimationMixer::set_root_motion_track); ClassDB::bind_method(D_METHOD("get_root_motion_track"), &AnimationMixer::get_root_motion_track); + ClassDB::bind_method(D_METHOD("set_root_motion_local", "enabled"), &AnimationMixer::set_root_motion_local); + ClassDB::bind_method(D_METHOD("is_root_motion_local"), &AnimationMixer::is_root_motion_local); ClassDB::bind_method(D_METHOD("get_root_motion_position"), &AnimationMixer::get_root_motion_position); ClassDB::bind_method(D_METHOD("get_root_motion_rotation"), &AnimationMixer::get_root_motion_rotation); @@ -2380,6 +2450,7 @@ void AnimationMixer::_bind_methods() { ADD_GROUP("Root Motion", "root_motion_"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_motion_track"), "set_root_motion_track", "get_root_motion_track"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "root_motion_local"), "set_root_motion_local", "is_root_motion_local"); ADD_GROUP("Audio", "audio_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "audio_max_polyphony", PROPERTY_HINT_RANGE, "1,127,1"), "set_audio_max_polyphony", "get_audio_max_polyphony"); diff --git a/scene/animation/animation_mixer.h b/scene/animation/animation_mixer.h index 822a7aef25..82deccaa95 100644 --- a/scene/animation/animation_mixer.h +++ b/scene/animation/animation_mixer.h @@ -334,6 +334,7 @@ protected: /* ---- Root motion accumulator for Skeleton3D ---- */ NodePath root_motion_track; + bool root_motion_local = false; Vector3 root_motion_position = Vector3(0, 0, 0); Quaternion root_motion_rotation = Quaternion(0, 0, 0, 1); Vector3 root_motion_scale = Vector3(0, 0, 0); @@ -447,6 +448,9 @@ public: void set_root_motion_track(const NodePath &p_track); NodePath get_root_motion_track() const; + void set_root_motion_local(bool p_enabled); + bool is_root_motion_local() const; + Vector3 get_root_motion_position() const; Quaternion get_root_motion_rotation() const; Vector3 get_root_motion_scale() const; diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index fd520dadd6..2c0222b3b8 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -94,7 +94,6 @@ void RootMotionView::_notification(int p_what) { if (has_node(path)) { Node *node = get_node(path); - AnimationMixer *mixer = Object::cast_to<AnimationMixer>(node); if (mixer && mixer->is_active() && mixer->get_root_motion_track() != NodePath()) { if (is_processing_internal() && mixer->get_callback_mode_process() == AnimationMixer::ANIMATION_CALLBACK_MODE_PROCESS_PHYSICS) { @@ -106,12 +105,12 @@ void RootMotionView::_notification(int p_what) { set_process_internal(true); set_physics_process_internal(false); } + transform.origin = mixer->get_root_motion_position(); transform.basis = mixer->get_root_motion_rotation(); // Scale is meaningless. - diff = mixer->get_root_motion_rotation_accumulator(); + diff = mixer->is_root_motion_local() ? Quaternion() : mixer->get_root_motion_rotation_accumulator(); } } - if (!first && transform == Transform3D()) { return; } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 997120ff25..06dff67172 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -217,14 +217,14 @@ void fragment() { circle_ok_color_shader->set_code(OK_COLOR_SHADER + R"( // ColorPicker ok color hsv circle shader. -uniform float v = 1.0; +uniform float ok_hsl_l = 1.0; void fragment() { float x = UV.x - 0.5; float y = UV.y - 0.5; float h = atan(y, x) / (2.0 * M_PI); float s = sqrt(x * x + y * y) * 2.0; - vec3 col = okhsl_to_srgb(vec3(h, s, v)); + vec3 col = okhsl_to_srgb(vec3(h, s, ok_hsl_l)); x += 0.001; y += 0.001; float b = float(sqrt(x * x + y * y) < 0.5); @@ -387,10 +387,21 @@ void ColorPicker::_slider_value_changed() { color = modes[current_mode]->get_color(); modes[current_mode]->_value_changed(); - if (current_mode == MODE_HSV || current_mode == MODE_OKHSL) { + if (current_mode == MODE_HSV) { h = sliders[0]->get_value() / 360.0; s = sliders[1]->get_value() / 100.0; v = sliders[2]->get_value() / 100.0; + ok_hsl_h = color.get_ok_hsl_h(); + ok_hsl_s = color.get_ok_hsl_s(); + ok_hsl_l = color.get_ok_hsl_l(); + last_color = color; + } else if (current_mode == MODE_OKHSL) { + ok_hsl_h = sliders[0]->get_value() / 360.0; + ok_hsl_s = sliders[1]->get_value() / 100.0; + ok_hsl_l = sliders[2]->get_value() / 100.0; + h = color.get_h(); + s = color.get_s(); + v = color.get_v(); last_color = color; } @@ -504,20 +515,17 @@ Vector<float> ColorPicker::get_active_slider_values() { } void ColorPicker::_copy_color_to_hsv() { - if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { - h = color.get_ok_hsl_h(); - s = color.get_ok_hsl_s(); - v = color.get_ok_hsl_l(); - } else { - h = color.get_h(); - s = color.get_s(); - v = color.get_v(); - } + ok_hsl_h = color.get_ok_hsl_h(); + ok_hsl_s = color.get_ok_hsl_s(); + ok_hsl_l = color.get_ok_hsl_l(); + h = color.get_h(); + s = color.get_s(); + v = color.get_v(); } void ColorPicker::_copy_hsv_to_color() { if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { - color.set_ok_hsl(h, s, v, color.a); + color.set_ok_hsl(ok_hsl_h, ok_hsl_s, ok_hsl_l, color.a); } else { color.set_hsv(h, s, v, color.a); } @@ -1201,8 +1209,8 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { int x; int y; if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { - x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_width() / 2); - y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_height() / 2); + x = center.x + (center.x * Math::cos((actual_shape == SHAPE_OKHSL_CIRCLE ? ok_hsl_h : h) * Math_TAU) * s) - (theme_cache.picker_cursor->get_width() / 2); + y = center.y + (center.y * Math::sin((actual_shape == SHAPE_OKHSL_CIRCLE ? ok_hsl_h : h) * Math_TAU) * s) - (theme_cache.picker_cursor->get_height() / 2); } else { real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; @@ -1238,11 +1246,11 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { Vector<Point2> points; Vector<Color> colors; Color col; - col.set_ok_hsl(h, s, 1); + col.set_ok_hsl(ok_hsl_h, ok_hsl_s, 1); Color col2; - col2.set_ok_hsl(h, s, 0.5); + col2.set_ok_hsl(ok_hsl_h, ok_hsl_s, 0.5); Color col3; - col3.set_ok_hsl(h, s, 0); + col3.set_ok_hsl(ok_hsl_h, ok_hsl_s, 0); points.resize(6); colors.resize(6); points.set(0, Vector2(c->get_size().x, 0)); @@ -1258,8 +1266,8 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { colors.set(4, col2); colors.set(5, col); c->draw_polygon(points, colors); - int y = c->get_size().y - c->get_size().y * CLAMP(v, 0, 1); - col.set_ok_hsl(h, 1, v); + int y = c->get_size().y - c->get_size().y * CLAMP(ok_hsl_l, 0, 1); + col.set_ok_hsl(ok_hsl_h, 1, ok_hsl_l); c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); } else if (actual_shape == SHAPE_VHS_CIRCLE) { Vector<Point2> points; @@ -1283,8 +1291,10 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { } } else if (p_which == 2) { c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1)); - if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { + if (actual_shape == SHAPE_VHS_CIRCLE) { circle_mat->set_shader_parameter("v", v); + } else if (actual_shape == SHAPE_OKHSL_CIRCLE) { + circle_mat->set_shader_parameter("ok_hsl_l", ok_hsl_l); } } } @@ -1308,6 +1318,8 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { real_t rad = center.angle_to_point(bev->get_position()); h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; s = CLAMP(dist / center.x, 0, 1); + ok_hsl_h = h; + ok_hsl_s = s; } else { return; } @@ -1375,6 +1387,8 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { real_t rad = center.angle_to_point(mev->get_position()); h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU; s = CLAMP(dist / center.x, 0, 1); + ok_hsl_h = h; + ok_hsl_s = s; } else { if (spinning) { real_t rad = center.angle_to_point(mev->get_position()); @@ -1412,6 +1426,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height); if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { v = 1.0 - (y / w_edit->get_size().height); + ok_hsl_l = v; } else { h = y / w_edit->get_size().height; } @@ -1440,6 +1455,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height); if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { v = 1.0 - (y / w_edit->get_size().height); + ok_hsl_l = v; } else { h = y / w_edit->get_size().height; } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 59540d9ace..aedf4aef16 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -211,6 +211,11 @@ private: float h = 0.0; float s = 0.0; float v = 0.0; + + float ok_hsl_h = 0.0; + float ok_hsl_s = 0.0; + float ok_hsl_l = 0.0; + Color last_color; struct ThemeCache { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index a349d50236..b0886a95d7 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1833,8 +1833,7 @@ void RichTextLabel::_notification(int p_what) { case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { - // If `text` is empty, it could mean that the tag stack is being used instead. Leave it be. - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } @@ -3109,6 +3108,10 @@ void RichTextLabel::add_text(const String &p_text) { } void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline) { + if (!internal_stack_editing) { + stack_externally_modified = true; + } + p_item->parent = current; p_item->E = current->subitems.push_back(p_item); p_item->index = current_idx++; @@ -3382,6 +3385,8 @@ bool RichTextLabel::remove_paragraph(int p_paragraph, bool p_no_invalidate) { return false; } + stack_externally_modified = true; + if (main->lines.size() == 1) { // Clear all. main->_clear_children(); @@ -4016,6 +4021,8 @@ void RichTextLabel::clear() { set_process_internal(false); MutexLock data_lock(data_mutex); + stack_externally_modified = false; + main->_clear_children(); current = main; current_frame = main; @@ -5818,11 +5825,19 @@ void RichTextLabel::set_text(const String &p_bbcode) { return; } + stack_externally_modified = false; + text = p_bbcode; _apply_translation(); } void RichTextLabel::_apply_translation() { + if (text.is_empty()) { + return; + } + + internal_stack_editing = true; + String xl_text = atr(text); if (use_bbcode) { parse_bbcode(xl_text); @@ -5830,6 +5845,8 @@ void RichTextLabel::_apply_translation() { clear(); add_text(xl_text); } + + internal_stack_editing = false; } String RichTextLabel::get_text() const { @@ -5843,8 +5860,7 @@ void RichTextLabel::set_use_bbcode(bool p_enable) { use_bbcode = p_enable; notify_property_list_changed(); - // If `text` is empty, it could mean that the tag stack is being used instead. Leave it be. - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } } @@ -5854,7 +5870,7 @@ bool RichTextLabel::is_using_bbcode() const { } String RichTextLabel::get_parsed_text() const { - String txt = ""; + String txt; Item *it = main; while (it) { if (it->type == ITEM_DROPCAP) { @@ -5881,7 +5897,7 @@ void RichTextLabel::set_text_direction(Control::TextDirection p_text_direction) if (text_direction != p_text_direction) { text_direction = p_text_direction; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5901,7 +5917,7 @@ void RichTextLabel::set_horizontal_alignment(HorizontalAlignment p_alignment) { if (default_alignment != p_alignment) { default_alignment = p_alignment; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5920,7 +5936,7 @@ void RichTextLabel::set_justification_flags(BitField<TextServer::JustificationFl if (default_jst_flags != p_flags) { default_jst_flags = p_flags; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5939,7 +5955,7 @@ void RichTextLabel::set_tab_stops(const PackedFloat32Array &p_tab_stops) { if (default_tab_stops != p_tab_stops) { default_tab_stops = p_tab_stops; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5958,7 +5974,7 @@ void RichTextLabel::set_structured_text_bidi_override(TextServer::StructuredText _stop_thread(); st_parser = p_parser; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -5992,7 +6008,7 @@ void RichTextLabel::set_language(const String &p_language) { _stop_thread(); language = p_language; - if (!text.is_empty()) { + if (!stack_externally_modified) { _apply_translation(); } else { main->first_invalid_line.store(0); // Invalidate all lines. @@ -6050,7 +6066,7 @@ float RichTextLabel::get_visible_ratio() const { void RichTextLabel::set_effects(Array p_effects) { custom_effects = p_effects; - if ((!text.is_empty()) && use_bbcode) { + if (!stack_externally_modified && use_bbcode) { parse_bbcode(atr(text)); } } @@ -6065,7 +6081,7 @@ void RichTextLabel::install_effect(const Variant effect) { ERR_FAIL_COND_MSG(rteffect.is_null(), "Invalid RichTextEffect resource."); custom_effects.push_back(effect); - if ((!text.is_empty()) && use_bbcode) { + if (!stack_externally_modified && use_bbcode) { parse_bbcode(atr(text)); } } diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index a01da02b27..ef4d17b8aa 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -626,6 +626,9 @@ private: String text; void _apply_translation(); + bool internal_stack_editing = false; + bool stack_externally_modified = false; + bool fit_content = false; struct ThemeCache { diff --git a/scene/resources/3d/primitive_meshes.cpp b/scene/resources/3d/primitive_meshes.cpp index ceeb73d0ef..4d04ae77b1 100644 --- a/scene/resources/3d/primitive_meshes.cpp +++ b/scene/resources/3d/primitive_meshes.cpp @@ -31,6 +31,7 @@ #include "primitive_meshes.h" #include "core/config/project_settings.h" +#include "core/math/math_funcs.h" #include "scene/resources/theme.h" #include "scene/theme/theme_db.h" #include "servers/rendering_server.h" @@ -261,6 +262,9 @@ void PrimitiveMesh::_bind_methods() { } void PrimitiveMesh::set_material(const Ref<Material> &p_material) { + if (p_material == material) { + return; + } material = p_material; if (!pending_request) { // just apply it, else it'll happen when _update is called. @@ -279,6 +283,9 @@ Array PrimitiveMesh::get_mesh_arrays() const { } void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) { + if (p_custom.is_equal_approx(custom_aabb)) { + return; + } custom_aabb = p_custom; RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); emit_changed(); @@ -289,6 +296,9 @@ AABB PrimitiveMesh::get_custom_aabb() const { } void PrimitiveMesh::set_flip_faces(bool p_enable) { + if (p_enable == flip_faces) { + return; + } flip_faces = p_enable; request_update(); } @@ -298,12 +308,18 @@ bool PrimitiveMesh::get_flip_faces() const { } void PrimitiveMesh::set_add_uv2(bool p_enable) { + if (p_enable == add_uv2) { + return; + } add_uv2 = p_enable; _update_lightmap_size(); request_update(); } void PrimitiveMesh::set_uv2_padding(float p_padding) { + if (Math::is_equal_approx(p_padding, uv2_padding)) { + return; + } uv2_padding = p_padding; _update_lightmap_size(); request_update(); @@ -578,6 +594,10 @@ void CapsuleMesh::_bind_methods() { } void CapsuleMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(radius, p_radius)) { + return; + } + radius = p_radius; if (radius > height * 0.5) { height = radius * 2.0; @@ -591,6 +611,10 @@ float CapsuleMesh::get_radius() const { } void CapsuleMesh::set_height(const float p_height) { + if (Math::is_equal_approx(height, p_height)) { + return; + } + height = p_height; if (radius > height * 0.5) { radius = height * 0.5; @@ -604,6 +628,10 @@ float CapsuleMesh::get_height() const { } void CapsuleMesh::set_radial_segments(const int p_segments) { + if (radial_segments == p_segments) { + return; + } + radial_segments = p_segments > 4 ? p_segments : 4; request_update(); } @@ -613,6 +641,10 @@ int CapsuleMesh::get_radial_segments() const { } void CapsuleMesh::set_rings(const int p_rings) { + if (rings == p_rings) { + return; + } + ERR_FAIL_COND(p_rings < 0); rings = p_rings; request_update(); @@ -908,6 +940,10 @@ void BoxMesh::_bind_methods() { } void BoxMesh::set_size(const Vector3 &p_size) { + if (p_size.is_equal_approx(size)) { + return; + } + size = p_size; _update_lightmap_size(); request_update(); @@ -918,6 +954,10 @@ Vector3 BoxMesh::get_size() const { } void BoxMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w) { + return; + } + subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -927,6 +967,10 @@ int BoxMesh::get_subdivide_width() const { } void BoxMesh::set_subdivide_height(const int p_divisions) { + if (p_divisions == subdivide_h) { + return; + } + subdivide_h = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -936,6 +980,10 @@ int BoxMesh::get_subdivide_height() const { } void BoxMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d) { + return; + } + subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1183,6 +1231,10 @@ void CylinderMesh::_bind_methods() { } void CylinderMesh::set_top_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, top_radius)) { + return; + } + top_radius = p_radius; _update_lightmap_size(); request_update(); @@ -1193,6 +1245,10 @@ float CylinderMesh::get_top_radius() const { } void CylinderMesh::set_bottom_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, bottom_radius)) { + return; + } + bottom_radius = p_radius; _update_lightmap_size(); request_update(); @@ -1203,6 +1259,10 @@ float CylinderMesh::get_bottom_radius() const { } void CylinderMesh::set_height(const float p_height) { + if (Math::is_equal_approx(p_height, height)) { + return; + } + height = p_height; _update_lightmap_size(); request_update(); @@ -1213,6 +1273,10 @@ float CylinderMesh::get_height() const { } void CylinderMesh::set_radial_segments(const int p_segments) { + if (p_segments == radial_segments) { + return; + } + radial_segments = p_segments > 4 ? p_segments : 4; request_update(); } @@ -1222,6 +1286,10 @@ int CylinderMesh::get_radial_segments() const { } void CylinderMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } + ERR_FAIL_COND(p_rings < 0); rings = p_rings; request_update(); @@ -1232,6 +1300,10 @@ int CylinderMesh::get_rings() const { } void CylinderMesh::set_cap_top(bool p_cap_top) { + if (p_cap_top == cap_top) { + return; + } + cap_top = p_cap_top; request_update(); } @@ -1241,6 +1313,10 @@ bool CylinderMesh::is_cap_top() const { } void CylinderMesh::set_cap_bottom(bool p_cap_bottom) { + if (p_cap_bottom == cap_bottom) { + return; + } + cap_bottom = p_cap_bottom; request_update(); } @@ -1375,6 +1451,9 @@ void PlaneMesh::_bind_methods() { } void PlaneMesh::set_size(const Size2 &p_size) { + if (p_size == size) { + return; + } size = p_size; _update_lightmap_size(); request_update(); @@ -1385,6 +1464,9 @@ Size2 PlaneMesh::get_size() const { } void PlaneMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w || (subdivide_w == 0 && p_divisions < 0)) { + return; + } subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1394,6 +1476,9 @@ int PlaneMesh::get_subdivide_width() const { } void PlaneMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d || (subdivide_d == 0 && p_divisions < 0)) { + return; + } subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1403,6 +1488,9 @@ int PlaneMesh::get_subdivide_depth() const { } void PlaneMesh::set_center_offset(const Vector3 p_offset) { + if (p_offset.is_equal_approx(center_offset)) { + return; + } center_offset = p_offset; request_update(); } @@ -1412,6 +1500,9 @@ Vector3 PlaneMesh::get_center_offset() const { } void PlaneMesh::set_orientation(const Orientation p_orientation) { + if (p_orientation == orientation) { + return; + } orientation = p_orientation; request_update(); } @@ -1719,6 +1810,9 @@ void PrismMesh::_bind_methods() { } void PrismMesh::set_left_to_right(const float p_left_to_right) { + if (Math::is_equal_approx(p_left_to_right, left_to_right)) { + return; + } left_to_right = p_left_to_right; request_update(); } @@ -1728,6 +1822,9 @@ float PrismMesh::get_left_to_right() const { } void PrismMesh::set_size(const Vector3 &p_size) { + if (p_size.is_equal_approx(size)) { + return; + } size = p_size; _update_lightmap_size(); request_update(); @@ -1738,6 +1835,9 @@ Vector3 PrismMesh::get_size() const { } void PrismMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w || (p_divisions < 0 && subdivide_w == 0)) { + return; + } subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1747,6 +1847,9 @@ int PrismMesh::get_subdivide_width() const { } void PrismMesh::set_subdivide_height(const int p_divisions) { + if (p_divisions == subdivide_h || (p_divisions < 0 && subdivide_h == 0)) { + return; + } subdivide_h = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1756,6 +1859,9 @@ int PrismMesh::get_subdivide_height() const { } void PrismMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d || (p_divisions < 0 && subdivide_d == 0)) { + return; + } subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1902,6 +2008,9 @@ void SphereMesh::_bind_methods() { } void SphereMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, radius)) { + return; + } radius = p_radius; _update_lightmap_size(); request_update(); @@ -1912,6 +2021,9 @@ float SphereMesh::get_radius() const { } void SphereMesh::set_height(const float p_height) { + if (Math::is_equal_approx(height, p_height)) { + return; + } height = p_height; _update_lightmap_size(); request_update(); @@ -1922,6 +2034,9 @@ float SphereMesh::get_height() const { } void SphereMesh::set_radial_segments(const int p_radial_segments) { + if (p_radial_segments == radial_segments || (radial_segments == 4 && p_radial_segments < 4)) { + return; + } radial_segments = p_radial_segments > 4 ? p_radial_segments : 4; request_update(); } @@ -1931,6 +2046,9 @@ int SphereMesh::get_radial_segments() const { } void SphereMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } ERR_FAIL_COND(p_rings < 1); rings = p_rings; request_update(); @@ -1941,6 +2059,9 @@ int SphereMesh::get_rings() const { } void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) { + if (p_is_hemisphere == is_hemisphere) { + return; + } is_hemisphere = p_is_hemisphere; _update_lightmap_size(); request_update(); @@ -2086,6 +2207,9 @@ void TorusMesh::_bind_methods() { } void TorusMesh::set_inner_radius(const float p_inner_radius) { + if (Math::is_equal_approx(p_inner_radius, inner_radius)) { + return; + } inner_radius = p_inner_radius; request_update(); } @@ -2095,6 +2219,9 @@ float TorusMesh::get_inner_radius() const { } void TorusMesh::set_outer_radius(const float p_outer_radius) { + if (Math::is_equal_approx(p_outer_radius, outer_radius)) { + return; + } outer_radius = p_outer_radius; request_update(); } @@ -2104,6 +2231,9 @@ float TorusMesh::get_outer_radius() const { } void TorusMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } ERR_FAIL_COND(p_rings < 3); rings = p_rings; request_update(); @@ -2114,6 +2244,9 @@ int TorusMesh::get_rings() const { } void TorusMesh::set_ring_segments(const int p_ring_segments) { + if (p_ring_segments == ring_segments) { + return; + } ERR_FAIL_COND(p_ring_segments < 3); ring_segments = p_ring_segments; request_update(); @@ -2143,6 +2276,9 @@ PointMesh::PointMesh() { // TUBE TRAIL void TubeTrailMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, radius)) { + return; + } radius = p_radius; request_update(); } @@ -2151,6 +2287,9 @@ float TubeTrailMesh::get_radius() const { } void TubeTrailMesh::set_radial_steps(const int p_radial_steps) { + if (p_radial_steps == radial_steps) { + return; + } ERR_FAIL_COND(p_radial_steps < 3 || p_radial_steps > 128); radial_steps = p_radial_steps; request_update(); @@ -2160,6 +2299,9 @@ int TubeTrailMesh::get_radial_steps() const { } void TubeTrailMesh::set_sections(const int p_sections) { + if (p_sections == sections) { + return; + } ERR_FAIL_COND(p_sections < 2 || p_sections > 128); sections = p_sections; request_update(); @@ -2169,6 +2311,9 @@ int TubeTrailMesh::get_sections() const { } void TubeTrailMesh::set_section_length(float p_section_length) { + if (p_section_length == section_length) { + return; + } section_length = p_section_length; request_update(); } @@ -2177,6 +2322,9 @@ float TubeTrailMesh::get_section_length() const { } void TubeTrailMesh::set_section_rings(const int p_section_rings) { + if (p_section_rings == section_rings) { + return; + } ERR_FAIL_COND(p_section_rings < 1 || p_section_rings > 1024); section_rings = p_section_rings; request_update(); @@ -2186,6 +2334,9 @@ int TubeTrailMesh::get_section_rings() const { } void TubeTrailMesh::set_cap_top(bool p_cap_top) { + if (p_cap_top == cap_top) { + return; + } cap_top = p_cap_top; request_update(); } @@ -2195,6 +2346,9 @@ bool TubeTrailMesh::is_cap_top() const { } void TubeTrailMesh::set_cap_bottom(bool p_cap_bottom) { + if (p_cap_bottom == cap_bottom) { + return; + } cap_bottom = p_cap_bottom; request_update(); } @@ -2501,6 +2655,9 @@ TubeTrailMesh::TubeTrailMesh() { // RIBBON TRAIL void RibbonTrailMesh::set_shape(Shape p_shape) { + if (p_shape == shape) { + return; + } shape = p_shape; request_update(); } @@ -2509,6 +2666,9 @@ RibbonTrailMesh::Shape RibbonTrailMesh::get_shape() const { } void RibbonTrailMesh::set_size(const float p_size) { + if (Math::is_equal_approx(p_size, size)) { + return; + } size = p_size; request_update(); } @@ -2517,6 +2677,9 @@ float RibbonTrailMesh::get_size() const { } void RibbonTrailMesh::set_sections(const int p_sections) { + if (p_sections == sections) { + return; + } ERR_FAIL_COND(p_sections < 2 || p_sections > 128); sections = p_sections; request_update(); @@ -2526,6 +2689,9 @@ int RibbonTrailMesh::get_sections() const { } void RibbonTrailMesh::set_section_length(float p_section_length) { + if (p_section_length == section_length) { + return; + } section_length = p_section_length; request_update(); } @@ -2534,6 +2700,9 @@ float RibbonTrailMesh::get_section_length() const { } void RibbonTrailMesh::set_section_segments(const int p_section_segments) { + if (p_section_segments == section_segments) { + return; + } ERR_FAIL_COND(p_section_segments < 1 || p_section_segments > 1024); section_segments = p_section_segments; request_update(); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 0dcdb90948..165168cb29 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -666,6 +666,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * light_count, &state.light_uniforms[0]); } + bool use_linear_colors = texture_storage->render_target_is_using_hdr(p_to_render_target); + { //update canvas state uniform buffer State::Buffer state_buffer; @@ -684,7 +686,6 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p normal_transform.columns[2] = Vector2(); _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform); - bool use_linear_colors = texture_storage->render_target_is_using_hdr(p_to_render_target); Color modulate = p_modulate; if (use_linear_colors) { modulate = p_modulate.srgb_to_linear(); @@ -722,6 +723,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p //print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale)); state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5); + state_buffer.flags = use_linear_colors ? CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR : 0; + RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer); } @@ -752,8 +755,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RenderTarget to_render_target; to_render_target.render_target = p_to_render_target; - bool use_linear_colors = texture_storage->render_target_is_using_hdr(p_to_render_target); - to_render_target.base_flags = use_linear_colors ? FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR : 0; + to_render_target.use_linear_colors = use_linear_colors; while (ci) { if (ci->copy_back_buffer && canvas_group_owner == nullptr) { @@ -2244,7 +2246,7 @@ RendererCanvasRenderRD::InstanceData *RendererCanvasRenderRD::new_instance_data( instance_data->world[i] = p_world[i]; } - instance_data->flags = p_base_flags | p_info->flags; // Reset on each command for safety, keep canvas texture binding config. + instance_data->flags = p_base_flags; // Reset on each command for safety. instance_data->color_texture_pixel_size[0] = p_info->texpixel_size.width; instance_data->color_texture_pixel_size[1] = p_info->texpixel_size.height; @@ -2265,8 +2267,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar _update_transform_2d_to_mat2x3(base_transform, world); Color base_color = p_item->final_modulate; - bool use_linear_colors = bool(p_render_target.base_flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR); - uint32_t base_flags = p_render_target.base_flags; + bool use_linear_colors = p_render_target.use_linear_colors; + uint32_t base_flags = 0; bool reclip = false; @@ -2276,6 +2278,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar uint32_t lights[4] = { 0, 0, 0, 0 }; uint16_t light_count = 0; + uint16_t shadow_mask = 0; { Light *light = p_lights; @@ -2285,6 +2288,10 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar uint32_t light_index = light->render_index_cache; lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); + if (p_item->light_mask & light->item_shadow_mask) { + shadow_mask |= 1 << light_count; + } + light_count++; if (light_count == MAX_LIGHTS_PER_ITEM - 1) { @@ -2294,7 +2301,8 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar light = light->next_ptr; } - base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; + base_flags |= light_count << INSTANCE_FLAGS_LIGHT_COUNT_SHIFT; + base_flags |= shadow_mask << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT; } bool use_lighting = (light_count > 0 || using_directional_lights); @@ -2323,6 +2331,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar // default variant r_current_batch->shader_variant = SHADER_VARIANT_QUAD; r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; + r_current_batch->flags = 0; } RenderingServer::CanvasItemTextureRepeat rect_repeat = texture_repeat; @@ -2378,20 +2387,18 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar if (rect->flags & CANVAS_RECT_FLIP_H) { src_rect.size.x *= -1; - instance_data->flags |= FLAGS_FLIP_H; } if (rect->flags & CANVAS_RECT_FLIP_V) { src_rect.size.y *= -1; - instance_data->flags |= FLAGS_FLIP_V; } if (rect->flags & CANVAS_RECT_TRANSPOSE) { - instance_data->flags |= FLAGS_TRANSPOSE_RECT; + instance_data->flags |= INSTANCE_FLAGS_TRANSPOSE_RECT; } if (rect->flags & CANVAS_RECT_CLIP_UV) { - instance_data->flags |= FLAGS_CLIP_RECT_UV; + instance_data->flags |= INSTANCE_FLAGS_CLIP_RECT_UV; } } else { @@ -2410,13 +2417,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar } if (has_msdf) { - instance_data->flags |= FLAGS_USE_MSDF; + instance_data->flags |= INSTANCE_FLAGS_USE_MSDF; instance_data->msdf[0] = rect->px_range; // Pixel range. instance_data->msdf[1] = rect->outline; // Outline size. instance_data->msdf[2] = 0.f; // Reserved. instance_data->msdf[3] = 0.f; // Reserved. } else if (rect->flags & CANVAS_RECT_LCD) { - instance_data->flags |= FLAGS_USE_LCD; + instance_data->flags |= INSTANCE_FLAGS_USE_LCD; } instance_data->modulation[0] = modulated.r; @@ -2447,6 +2454,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->has_blend = false; r_current_batch->shader_variant = SHADER_VARIANT_NINEPATCH; r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; + r_current_batch->flags = 0; } TextureState tex_state(np->texture, texture_filter, texture_repeat, false, use_linear_colors); @@ -2498,11 +2506,11 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar instance_data->dst_rect[2] = dst_rect.size.width; instance_data->dst_rect[3] = dst_rect.size.height; - instance_data->flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT; - instance_data->flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT; + instance_data->flags |= int(np->axis_x) << INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT; + instance_data->flags |= int(np->axis_y) << INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT; if (np->draw_center) { - instance_data->flags |= FLAGS_NINEPACH_DRAW_CENTER; + instance_data->flags |= INSTANCE_FLAGS_NINEPACH_DRAW_CENTER; } instance_data->ninepatch_margins[0] = np->margin[SIDE_LEFT]; @@ -2522,6 +2530,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->command_type = Item::Command::TYPE_POLYGON; r_current_batch->has_blend = false; r_current_batch->command = c; + r_current_batch->flags = 0; TextureState tex_state(polygon->texture, texture_filter, texture_repeat, false, use_linear_colors); TextureInfo *tex_info = texture_info_map.getptr(tex_state); @@ -2566,6 +2575,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->has_blend = false; r_current_batch->command = c; r_current_batch->primitive_points = primitive->point_count; + r_current_batch->flags = 0; ERR_CONTINUE(primitive->point_count == 0 || primitive->point_count > 4); @@ -2648,6 +2658,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->command = c; r_current_batch->command_type = c->type; r_current_batch->has_blend = false; + r_current_batch->flags = 0; InstanceData *instance_data = nullptr; @@ -2690,13 +2701,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->tex_info = tex_info; instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); - instance_data->flags |= 1; // multimesh, trails disabled + r_current_batch->flags |= 1; // multimesh, trails disabled if (mesh_storage->multimesh_uses_colors(mm->multimesh)) { - instance_data->flags |= FLAGS_INSTANCING_HAS_COLORS; + r_current_batch->flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS; } if (mesh_storage->multimesh_uses_custom_data(mm->multimesh)) { - instance_data->flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + r_current_batch->flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA; } } else if (c->type == Item::Command::TYPE_PARTICLES) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); @@ -2714,13 +2725,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar uint32_t divisor = 1; r_current_batch->mesh_instance_count = particles_storage->particles_get_amount(pt->particles, divisor); - instance_data->flags |= (divisor & FLAGS_INSTANCING_MASK); + r_current_batch->flags |= (divisor & BATCH_FLAGS_INSTANCING_MASK); r_current_batch->mesh_instance_count /= divisor; RID particles = pt->particles; - instance_data->flags |= FLAGS_INSTANCING_HAS_COLORS; - instance_data->flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + r_current_batch->flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS; + r_current_batch->flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA; if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target.render_target)) { // Pass collision information. @@ -2806,6 +2817,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar // default variant r_current_batch->shader_variant = SHADER_VARIANT_QUAD; r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; + r_current_batch->flags = 0; } // 2: If the current batch has lighting, start a new batch. @@ -2920,6 +2932,7 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha PushConstant push_constant; push_constant.base_instance_index = p_batch->start; push_constant.specular_shininess = p_batch->tex_info->specular_shininess; + push_constant.batch_flags = p_batch->tex_info->flags | p_batch->flags; RID pipeline; PipelineKey pipeline_key; @@ -3168,11 +3181,11 @@ void RendererCanvasRenderRD::_prepare_batch_texture_info(RID p_texture, TextureS // cache values to be copied to instance data if (info.specular_color.a < 0.999) { - p_info->flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + p_info->flags |= BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED; } if (info.use_normal) { - p_info->flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + p_info->flags |= BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED; } uint8_t a = uint8_t(CLAMP(info.specular_color.a * 255.0, 0.0, 255.0)); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 1bdc5076c5..e4f1779b09 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -65,31 +65,31 @@ class RendererCanvasRenderRD : public RendererCanvasRender { }; enum { + INSTANCE_FLAGS_LIGHT_COUNT_SHIFT = 0, // 4 bits for light count. - FLAGS_INSTANCING_MASK = 0x7F, - FLAGS_INSTANCING_HAS_COLORS = (1 << 7), - FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), + INSTANCE_FLAGS_CLIP_RECT_UV = (1 << 4), + INSTANCE_FLAGS_TRANSPOSE_RECT = (1 << 5), + INSTANCE_FLAGS_USE_MSDF = (1 << 6), + INSTANCE_FLAGS_USE_LCD = (1 << 7), - FLAGS_CLIP_RECT_UV = (1 << 9), - FLAGS_TRANSPOSE_RECT = (1 << 10), + INSTANCE_FLAGS_NINEPACH_DRAW_CENTER = (1 << 8), + INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT = 9, + INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT = 11, - FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR = (1 << 11), - - FLAGS_NINEPACH_DRAW_CENTER = (1 << 12), - - FLAGS_USE_SKELETON = (1 << 15), - FLAGS_NINEPATCH_H_MODE_SHIFT = 16, - FLAGS_NINEPATCH_V_MODE_SHIFT = 18, - FLAGS_LIGHT_COUNT_SHIFT = 20, + INSTANCE_FLAGS_SHADOW_MASKED_SHIFT = 13, // 16 bits. + }; - FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 24), - FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 25), + enum { + BATCH_FLAGS_INSTANCING_MASK = 0x7F, + BATCH_FLAGS_INSTANCING_HAS_COLORS = (1 << 7), + BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), - FLAGS_USE_MSDF = (1 << 26), - FLAGS_USE_LCD = (1 << 27), + BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 9), + BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 10), + }; - FLAGS_FLIP_H = (1 << 28), - FLAGS_FLIP_V = (1 << 29), + enum { + CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR = (1 << 0), }; enum { @@ -370,7 +370,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t base_instance_index; ShaderSpecialization shader_specialization; uint32_t specular_shininess; - uint32_t pad; + uint32_t batch_flags; }; // TextureState is used to determine when a new batch is required due to a change of texture state. @@ -508,6 +508,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t mesh_instance_count; }; bool has_blend = false; + uint32_t flags = 0; }; HashMap<TextureState, TextureInfo, HashableHasher<TextureState>> texture_info_map; @@ -535,7 +536,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t directional_light_count; float tex_to_sdf; - uint32_t pad1; + uint32_t flags; uint32_t pad2; }; @@ -596,9 +597,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct RenderTarget { // Current render target for the canvas. RID render_target; - // The base flags for each InstanceData, derived from the render target. - // Either FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR or 0 - uint32_t base_flags = 0; + bool use_linear_colors = false; }; inline RID _get_pipeline_specialization_or_ubershader(CanvasShaderData *p_shader_data, PipelineKey &r_pipeline_key, PushConstant &r_push_constant, RID p_mesh_instance = RID(), void *p_surface = nullptr, uint32_t p_surface_index = 0, RID *r_vertex_array = nullptr); diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index f665bc24a4..b66aa71f6b 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -101,7 +101,7 @@ void main() { vec2 vertex = vertex_attrib; vec4 color = color_attrib; - if (bool(draw_data.flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR)) { + if (bool(canvas_data.flags & CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR)) { color.rgb = srgb_to_linear(color.rgb); } color *= draw_data.modulation; @@ -122,7 +122,7 @@ void main() { vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); vec2 vertex_base = vertex_base_arr[gl_VertexIndex]; - vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy); + vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & INSTANCE_FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy); vec4 color = draw_data.modulation; vec2 vertex = draw_data.dst_rect.xy + abs(draw_data.dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data.src_rect.zw, vec2(0.0, 0.0))); uvec4 bones = uvec4(0, 0, 0, 0); @@ -133,7 +133,7 @@ void main() { #ifdef USE_ATTRIBUTES - uint instancing = draw_data.flags & FLAGS_INSTANCING_MASK; + uint instancing = params.batch_flags & BATCH_FLAGS_INSTANCING_MASK; if (instancing > 1) { // trails @@ -172,19 +172,19 @@ void main() { vertex = new_vertex; color *= pcolor; } else if (instancing == 1) { - uint stride = 2 + bitfieldExtract(draw_data.flags, FLAGS_INSTANCING_HAS_COLORS_SHIFT, 1) + bitfieldExtract(draw_data.flags, FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT, 1); + uint stride = 2 + bitfieldExtract(params.batch_flags, BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT, 1) + bitfieldExtract(params.batch_flags, BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT, 1); uint offset = stride * gl_InstanceIndex; mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); offset += 2; - if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) { + if (bool(params.batch_flags & BATCH_FLAGS_INSTANCING_HAS_COLORS)) { color *= transforms.data[offset]; offset += 1; } - if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { + if (bool(params.batch_flags & BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { instance_custom = transforms.data[offset]; } @@ -331,7 +331,7 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo } else if (pixel >= draw_size - margin_end) { return (tex_size - (draw_size - pixel)) * tex_pixel_size; } else { - draw_center -= 1 - int(bitfieldExtract(draw_data.flags, FLAGS_NINEPACH_DRAW_CENTER_SHIFT, 1)); + draw_center -= 1 - int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER_SHIFT, 1)); // np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum. if (np_repeat == 0) { // Stretch. @@ -472,8 +472,8 @@ void main() { int draw_center = 2; uv = vec2( - map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(bitfieldExtract(draw_data.flags, FLAGS_NINEPATCH_H_MODE_SHIFT, 2)), draw_center), - map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(bitfieldExtract(draw_data.flags, FLAGS_NINEPATCH_V_MODE_SHIFT, 2)), draw_center)); + map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT, 2)), draw_center), + map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT, 2)), draw_center)); if (draw_center == 0) { color.a = 0.0; @@ -482,7 +482,7 @@ void main() { uv = uv * draw_data.src_rect.zw + draw_data.src_rect.xy; //apply region if needed #endif - if (bool(draw_data.flags & FLAGS_CLIP_RECT_UV)) { + if (bool(draw_data.flags & INSTANCE_FLAGS_CLIP_RECT_UV)) { vec2 half_texpixel = draw_data.color_texture_pixel_size * 0.5; uv = clamp(uv, draw_data.src_rect.xy + half_texpixel, draw_data.src_rect.xy + abs(draw_data.src_rect.zw) - half_texpixel); } @@ -490,7 +490,7 @@ void main() { #endif #ifndef USE_PRIMITIVE - if (bool(draw_data.flags & FLAGS_USE_MSDF)) { + if (bool(draw_data.flags & INSTANCE_FLAGS_USE_MSDF)) { float px_range = draw_data.ninepatch_margins.x; float outline_thickness = draw_data.ninepatch_margins.y; //float reserved1 = draw_data.ninepatch_margins.z; @@ -510,7 +510,7 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - } else if (bool(draw_data.flags & FLAGS_USE_LCD)) { + } else if (bool(draw_data.flags & INSTANCE_FLAGS_USE_LCD)) { vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv); if (lcd_sample.a == 1.0) { color.rgb = lcd_sample.rgb * color.a; @@ -524,7 +524,7 @@ void main() { color *= texture(sampler2D(color_texture, texture_sampler), uv); } - uint light_count = bitfieldExtract(draw_data.flags, FLAGS_LIGHT_COUNT_SHIFT, 4); //max 15 lights + uint light_count = draw_data.flags & 15u; //max 15 lights bool using_light = (light_count + canvas_data.directional_light_count) > 0; vec3 normal; @@ -535,17 +535,15 @@ void main() { bool normal_used = false; #endif - if (normal_used || (using_light && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { + if (normal_used || (using_light && bool(params.batch_flags & BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED))) { normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); - if (bool(draw_data.flags & FLAGS_TRANSPOSE_RECT)) { + +#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) + if (bool(draw_data.flags & INSTANCE_FLAGS_TRANSPOSE_RECT)) { normal.xy = normal.yx; } - if (bool(draw_data.flags & FLAGS_FLIP_H)) { - normal.x = -normal.x; - } - if (bool(draw_data.flags & FLAGS_FLIP_V)) { - normal.y = -normal.y; - } + normal.xy *= sign(draw_data.src_rect.zw); +#endif normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy, normal.xy))); normal_used = true; } else { @@ -561,7 +559,7 @@ void main() { bool specular_shininess_used = false; #endif - if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { + if (specular_shininess_used || (using_light && normal_used && bool(params.batch_flags & BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED))) { specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv); specular_shininess *= unpackUnorm4x8(params.specular_shininess); specular_shininess_used = true; @@ -632,7 +630,7 @@ void main() { } #endif - if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(draw_data.flags & (INSTANCE_FLAGS_SHADOW_MASKED << i))) { vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. vec4 shadow_uv = vec4(shadow_pos.x, light_array.data[light_base].shadow_y_ofs, shadow_pos.y * light_array.data[light_base].shadow_zfar_inv, 1.0); @@ -692,7 +690,7 @@ void main() { } #endif - if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(draw_data.flags & (INSTANCE_FLAGS_SHADOW_MASKED << i))) { vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. vec2 pos_norm = normalize(shadow_pos); diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 84017a1fe1..2186b08e89 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -5,32 +5,19 @@ #define SDF_MAX_LENGTH 16384.0 -//1 means enabled, 2+ means trails in use -#define FLAGS_INSTANCING_MASK 0x7F -#define FLAGS_INSTANCING_HAS_COLORS_SHIFT 7 -#define FLAGS_INSTANCING_HAS_COLORS (1 << FLAGS_INSTANCING_HAS_COLORS_SHIFT) -#define FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8 -#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT) - -#define FLAGS_CLIP_RECT_UV (1 << 9) -#define FLAGS_TRANSPOSE_RECT (1 << 10) -#define FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR (1 << 11) -#define FLAGS_NINEPACH_DRAW_CENTER_SHIFT 12 -#define FLAGS_NINEPACH_DRAW_CENTER (1 << FLAGS_NINEPACH_DRAW_CENTER_SHIFT) - -#define FLAGS_NINEPATCH_H_MODE_SHIFT 16 -#define FLAGS_NINEPATCH_V_MODE_SHIFT 18 +#define INSTANCE_FLAGS_LIGHT_COUNT_SHIFT 0 // 4 bits. -#define FLAGS_LIGHT_COUNT_SHIFT 20 +#define INSTANCE_FLAGS_CLIP_RECT_UV (1 << 4) +#define INSTANCE_FLAGS_TRANSPOSE_RECT (1 << 5) +#define INSTANCE_FLAGS_USE_MSDF (1 << 6) +#define INSTANCE_FLAGS_USE_LCD (1 << 7) -#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 24) -#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 25) +#define INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER_SHIFT 8 +#define INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT 9 +#define INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT 11 -#define FLAGS_USE_MSDF (1 << 26) -#define FLAGS_USE_LCD (1 << 27) - -#define FLAGS_FLIP_H (1 << 28) -#define FLAGS_FLIP_V (1 << 29) +#define INSTANCE_FLAGS_SHADOW_MASKED_SHIFT 13 // 16 bits. +#define INSTANCE_FLAGS_SHADOW_MASKED (1 << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT) struct InstanceData { vec2 world_x; @@ -54,11 +41,21 @@ struct InstanceData { uint lights[4]; }; +//1 means enabled, 2+ means trails in use +#define BATCH_FLAGS_INSTANCING_MASK 0x7F +#define BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT 7 +#define BATCH_FLAGS_INSTANCING_HAS_COLORS (1 << BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT) +#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8 +#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT) + +#define BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 9) +#define BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 10) + layout(push_constant, std430) uniform Params { uint base_instance_index; // base index to instance data uint sc_packed_0; uint specular_shininess; - uint pad; + uint batch_flags; } params; @@ -94,6 +91,8 @@ bool sc_use_lighting() { /* SET0: Globals */ +#define CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR (1 << 0) + // The values passed per draw primitives are cached within it layout(set = 0, binding = 1, std140) uniform CanvasData { @@ -111,7 +110,7 @@ layout(set = 0, binding = 1, std140) uniform CanvasData { uint directional_light_count; float tex_to_sdf; - uint pad1; + uint flags; uint pad2; } canvas_data; diff --git a/tests/core/io/test_file_access.h b/tests/core/io/test_file_access.h index a4d3fd1d70..00d33eaf30 100644 --- a/tests/core/io/test_file_access.h +++ b/tests/core/io/test_file_access.h @@ -39,7 +39,7 @@ namespace TestFileAccess { TEST_CASE("[FileAccess] CSV read") { Ref<FileAccess> f = FileAccess::open(TestUtils::get_data_path("testdata.csv"), FileAccess::READ); - REQUIRE(!f.is_null()); + REQUIRE(f.is_valid()); Vector<String> header = f->get_csv_line(); // Default delimiter: ",". REQUIRE(header.size() == 4); @@ -107,6 +107,98 @@ TEST_CASE("[FileAccess] Get as UTF-8 String") { CHECK(s_cr == "Hello darkness\rMy old friend\rI've come to talk\rWith you again\r"); CHECK(s_cr_nocr == "Hello darknessMy old friendI've come to talkWith you again"); } + +TEST_CASE("[FileAccess] Get/Store floating point values") { + // BigEndian Hex: 0x40490E56 + // LittleEndian Hex: 0x560E4940 + float value = 3.1415f; + + SUBCASE("Little Endian") { + const String file_path = TestUtils::get_data_path("floating_point_little_endian.bin"); + const String file_path_new = TestUtils::get_data_path("floating_point_little_endian_new.bin"); + + Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ); + REQUIRE(f.is_valid()); + CHECK_EQ(f->get_float(), value); + + Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE); + REQUIRE(fw.is_valid()); + fw->store_float(value); + fw->close(); + + CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path)); + + DirAccess::remove_file_or_error(file_path_new); + } + + SUBCASE("Big Endian") { + const String file_path = TestUtils::get_data_path("floating_point_big_endian.bin"); + const String file_path_new = TestUtils::get_data_path("floating_point_big_endian_new.bin"); + + Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ); + REQUIRE(f.is_valid()); + f->set_big_endian(true); + CHECK_EQ(f->get_float(), value); + + Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE); + REQUIRE(fw.is_valid()); + fw->set_big_endian(true); + fw->store_float(value); + fw->close(); + + CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path)); + + DirAccess::remove_file_or_error(file_path_new); + } +} + +TEST_CASE("[FileAccess] Get/Store floating point half precision values") { + // IEEE 754 half-precision binary floating-point format: + // sign exponent (5 bits) fraction (10 bits) + // 0 01101 0101010101 + // BigEndian Hex: 0x3555 + // LittleEndian Hex: 0x5535 + float value = 0.33325195f; + + SUBCASE("Little Endian") { + const String file_path = TestUtils::get_data_path("half_precision_floating_point_little_endian.bin"); + const String file_path_new = TestUtils::get_data_path("half_precision_floating_point_little_endian_new.bin"); + + Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ); + REQUIRE(f.is_valid()); + CHECK_EQ(f->get_half(), value); + + Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE); + REQUIRE(fw.is_valid()); + fw->store_half(value); + fw->close(); + + CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path)); + + DirAccess::remove_file_or_error(file_path_new); + } + + SUBCASE("Big Endian") { + const String file_path = TestUtils::get_data_path("half_precision_floating_point_big_endian.bin"); + const String file_path_new = TestUtils::get_data_path("half_precision_floating_point_big_endian_new.bin"); + + Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ); + REQUIRE(f.is_valid()); + f->set_big_endian(true); + CHECK_EQ(f->get_half(), value); + + Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE); + REQUIRE(fw.is_valid()); + fw->set_big_endian(true); + fw->store_half(value); + fw->close(); + + CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path)); + + DirAccess::remove_file_or_error(file_path_new); + } +} + } // namespace TestFileAccess #endif // TEST_FILE_ACCESS_H diff --git a/tests/core/io/test_marshalls.h b/tests/core/io/test_marshalls.h index 6716984681..eb92c3f752 100644 --- a/tests/core/io/test_marshalls.h +++ b/tests/core/io/test_marshalls.h @@ -90,6 +90,20 @@ TEST_CASE("[Marshalls] Unsigned 64 bit integer decoding") { CHECK(decode_uint64(arr) == 0x0f123456789abcdef); } +TEST_CASE("[Marshalls] Floating point half precision encoding") { + uint8_t arr[2]; + + // Decimal: 0.33325195 + // IEEE 754 half-precision binary floating-point format: + // sign exponent (5 bits) fraction (10 bits) + // 0 01101 0101010101 + // Hexadecimal: 0x3555 + unsigned int actual_size = encode_half(0.33325195f, arr); + CHECK(actual_size == sizeof(uint16_t)); + CHECK(arr[0] == 0x55); + CHECK(arr[1] == 0x35); +} + TEST_CASE("[Marshalls] Floating point single precision encoding") { uint8_t arr[4]; @@ -126,6 +140,13 @@ TEST_CASE("[Marshalls] Floating point double precision encoding") { CHECK(arr[7] == 0x3f); } +TEST_CASE("[Marshalls] Floating point half precision decoding") { + uint8_t arr[] = { 0x55, 0x35 }; + + // See floating point half precision encoding test case for details behind expected values. + CHECK(decode_half(arr) == 0.33325195f); +} + TEST_CASE("[Marshalls] Floating point single precision decoding") { uint8_t arr[] = { 0x00, 0x00, 0x20, 0x3e }; diff --git a/tests/core/io/test_stream_peer.h b/tests/core/io/test_stream_peer.h index 31bd69edd0..961b4ac070 100644 --- a/tests/core/io/test_stream_peer.h +++ b/tests/core/io/test_stream_peer.h @@ -127,6 +127,17 @@ TEST_CASE("[StreamPeer] Get and sets through StreamPeerBuffer") { CHECK_EQ(spb->get_u64(), value); } + SUBCASE("A half-precision float value") { + float value = 3.1415927f; + float expected = 3.14062f; + + spb->clear(); + spb->put_half(value); + spb->seek(0); + + CHECK(spb->get_half() == doctest::Approx(expected)); + } + SUBCASE("A float value") { float value = 42.0f; @@ -255,6 +266,17 @@ TEST_CASE("[StreamPeer] Get and sets big endian through StreamPeerBuffer") { CHECK_EQ(spb->get_float(), value); } + SUBCASE("A half-precision float value") { + float value = 3.1415927f; + float expected = 3.14062f; + + spb->clear(); + spb->put_half(value); + spb->seek(0); + + CHECK(spb->get_half() == doctest::Approx(expected)); + } + SUBCASE("A double value") { double value = 42.0; diff --git a/tests/data/floating_point_big_endian.bin b/tests/data/floating_point_big_endian.bin new file mode 100644 index 0000000000..9534605ce1 --- /dev/null +++ b/tests/data/floating_point_big_endian.bin @@ -0,0 +1 @@ +@IV
\ No newline at end of file diff --git a/tests/data/floating_point_little_endian.bin b/tests/data/floating_point_little_endian.bin new file mode 100644 index 0000000000..8cd66219d8 --- /dev/null +++ b/tests/data/floating_point_little_endian.bin @@ -0,0 +1 @@ +VI@
\ No newline at end of file diff --git a/tests/data/half_precision_floating_point_big_endian.bin b/tests/data/half_precision_floating_point_big_endian.bin new file mode 100644 index 0000000000..6519f7500a --- /dev/null +++ b/tests/data/half_precision_floating_point_big_endian.bin @@ -0,0 +1 @@ +5U
\ No newline at end of file diff --git a/tests/data/half_precision_floating_point_little_endian.bin b/tests/data/half_precision_floating_point_little_endian.bin new file mode 100644 index 0000000000..4f748ab1e9 --- /dev/null +++ b/tests/data/half_precision_floating_point_little_endian.bin @@ -0,0 +1 @@ +U5
\ No newline at end of file |