Merge pull request #56002 from akien-mga/3.4-cherrypicks
This commit is contained in:
commit
67f8c5c4e8
@ -3113,6 +3113,27 @@ CharType String::ord_at(int p_idx) const {
|
||||
return operator[](p_idx);
|
||||
}
|
||||
|
||||
String String::indent(const String &p_prefix) const {
|
||||
String new_string;
|
||||
int line_start = 0;
|
||||
|
||||
for (int i = 0; i < length(); i++) {
|
||||
const char32_t c = operator[](i);
|
||||
if (c == '\n') {
|
||||
if (i == line_start) {
|
||||
new_string += c; // Leave empty lines empty.
|
||||
} else {
|
||||
new_string += p_prefix + substr(line_start, i - line_start + 1);
|
||||
}
|
||||
line_start = i + 1;
|
||||
}
|
||||
}
|
||||
if (line_start != length()) {
|
||||
new_string += p_prefix + substr(line_start);
|
||||
}
|
||||
return new_string;
|
||||
}
|
||||
|
||||
String String::dedent() const {
|
||||
String new_string;
|
||||
String indent;
|
||||
|
@ -282,6 +282,7 @@ public:
|
||||
|
||||
String left(int p_pos) const;
|
||||
String right(int p_pos) const;
|
||||
String indent(const String &p_prefix) const;
|
||||
String dedent() const;
|
||||
String strip_edges(bool left = true, bool right = true) const;
|
||||
String strip_escapes() const;
|
||||
|
@ -271,6 +271,7 @@ struct _VariantCall {
|
||||
VCALL_LOCALMEM0R(String, to_lower);
|
||||
VCALL_LOCALMEM1R(String, left);
|
||||
VCALL_LOCALMEM1R(String, right);
|
||||
VCALL_LOCALMEM1R(String, indent);
|
||||
VCALL_LOCALMEM0R(String, dedent);
|
||||
VCALL_LOCALMEM2R(String, strip_edges);
|
||||
VCALL_LOCALMEM0R(String, strip_escapes);
|
||||
@ -1675,6 +1676,7 @@ void register_variant_methods() {
|
||||
ADDFUNC0R(STRING, STRING, String, get_basename, varray());
|
||||
ADDFUNC1R(STRING, STRING, String, plus_file, STRING, "file", varray());
|
||||
ADDFUNC1R(STRING, INT, String, ord_at, INT, "at", varray());
|
||||
ADDFUNC1R(STRING, STRING, String, indent, STRING, "prefix", varray());
|
||||
ADDFUNC0R(STRING, STRING, String, dedent, varray());
|
||||
ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray());
|
||||
ADDFUNC0R(STRING, INT, String, hash, varray());
|
||||
|
@ -1486,7 +1486,7 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
|
||||
v->set_hsv(v->get_h(), p_value._data._int, v->get_v(), v->a);
|
||||
valid = true;
|
||||
} else if (p_index == CoreStringNames::singleton->v) {
|
||||
v->set_hsv(v->get_h(), v->get_v(), p_value._data._int, v->a);
|
||||
v->set_hsv(v->get_h(), v->get_s(), p_value._data._int, v->a);
|
||||
valid = true;
|
||||
}
|
||||
} else if (p_value.type == Variant::REAL) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
</brief_description>
|
||||
<description>
|
||||
Base resource for [AnimationTree] nodes. In general, it's not used directly, but you can create custom ones with custom blending formulas.
|
||||
Inherit this when creating nodes mainly for use in [AnimationNodeBlendTree], otherwise [AnimationRootNode] should be used instead.
|
||||
Inherit this when creating nodes mainly for use in [AnimationNodeBlendTree], otherwise [AnimationRootNode] should be used instead.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/animation/animation_tree.html</link>
|
||||
|
@ -150,7 +150,8 @@
|
||||
[b]Note:[/b] To detect whether the script is run from an editor [i]build[/i] (e.g. when pressing [code]F5[/code]), use [method OS.has_feature] with the [code]"editor"[/code] argument instead. [code]OS.has_feature("editor")[/code] will evaluate to [code]true[/code] both when the code is running in the editor and when running the project from the editor, but it will evaluate to [code]false[/code] when the code is run from an exported project.
|
||||
</member>
|
||||
<member name="iterations_per_second" type="int" setter="set_iterations_per_second" getter="get_iterations_per_second" default="60">
|
||||
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. This value should generally always be set to [code]60[/code] or above, as Godot doesn't interpolate the physics step. As a result, values lower than [code]60[/code] will look stuttery. This value can be increased to make input more reactive or work around tunneling issues, but keep in mind doing so will increase CPU usage.
|
||||
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. This value should generally always be set to [code]60[/code] or above, as Godot doesn't interpolate the physics step. As a result, values lower than [code]60[/code] will look stuttery. This value can be increased to make input more reactive or work around collision tunneling issues, but keep in mind doing so will increase CPU usage. See also [member target_fps] and [member ProjectSettings.physics/common/physics_fps].
|
||||
[b]Note:[/b] Only 8 physics ticks may be simulated per rendered frame at most. If more than 8 physics ticks have to be simulated per rendered frame to keep up with rendering, the game will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended not to increase [member Engine.iterations_per_second] above 240. Otherwise, the game will slow down when the rendering framerate goes below 30 FPS.
|
||||
</member>
|
||||
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
|
||||
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of the in-game clock and real clock but smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
|
||||
|
@ -5,49 +5,49 @@
|
||||
</brief_description>
|
||||
<description>
|
||||
The HMACContext class is useful for advanced HMAC use cases, such as streaming the message as it supports creating the message over time rather than providing it all at once.
|
||||
[codeblock]
|
||||
extends Node
|
||||
var ctx = HMACContext.new()
|
||||
[codeblock]
|
||||
extends Node
|
||||
var ctx = HMACContext.new()
|
||||
|
||||
func _ready():
|
||||
var key = "supersecret".to_utf8()
|
||||
var err = ctx.start(HashingContext.HASH_SHA256, key)
|
||||
assert(err == OK)
|
||||
var msg1 = "this is ".to_utf8()
|
||||
var msg2 = "vewy vewy secret".to_utf8()
|
||||
err = ctx.update(msg1)
|
||||
assert(err == OK)
|
||||
err = ctx.update(msg2)
|
||||
assert(err == OK)
|
||||
var hmac = ctx.finish()
|
||||
print(hmac.hex_encode())
|
||||
[/codeblock]
|
||||
func _ready():
|
||||
var key = "supersecret".to_utf8()
|
||||
var err = ctx.start(HashingContext.HASH_SHA256, key)
|
||||
assert(err == OK)
|
||||
var msg1 = "this is ".to_utf8()
|
||||
var msg2 = "vewy vewy secret".to_utf8()
|
||||
err = ctx.update(msg1)
|
||||
assert(err == OK)
|
||||
err = ctx.update(msg2)
|
||||
assert(err == OK)
|
||||
var hmac = ctx.finish()
|
||||
print(hmac.hex_encode())
|
||||
[/codeblock]
|
||||
And in C# we can use the following.
|
||||
[codeblock]
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
[codeblock]
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
public class CryptoNode : Node
|
||||
{
|
||||
private HMACContext ctx = new HMACContext();
|
||||
public override void _Ready()
|
||||
{
|
||||
PoolByteArray key = String("supersecret").to_utf8();
|
||||
Error err = ctx.Start(HashingContext.HASH_SHA256, key);
|
||||
GD.Assert(err == OK);
|
||||
PoolByteArray msg1 = String("this is ").to_utf8();
|
||||
PoolByteArray msg2 = String("vewy vew secret").to_utf8();
|
||||
err = ctx.Update(msg1);
|
||||
GD.Assert(err == OK);
|
||||
err = ctx.Update(msg2);
|
||||
GD.Assert(err == OK);
|
||||
PoolByteArray hmac = ctx.Finish();
|
||||
GD.Print(hmac.HexEncode());
|
||||
}
|
||||
}
|
||||
[/codeblock]
|
||||
[b]Note:[/b] Not available in HTML5 exports.
|
||||
public class CryptoNode : Node
|
||||
{
|
||||
private HMACContext ctx = new HMACContext();
|
||||
public override void _Ready()
|
||||
{
|
||||
PoolByteArray key = String("supersecret").to_utf8();
|
||||
Error err = ctx.Start(HashingContext.HASH_SHA256, key);
|
||||
GD.Assert(err == OK);
|
||||
PoolByteArray msg1 = String("this is ").to_utf8();
|
||||
PoolByteArray msg2 = String("vewy vew secret").to_utf8();
|
||||
err = ctx.Update(msg1);
|
||||
GD.Assert(err == OK);
|
||||
err = ctx.Update(msg2);
|
||||
GD.Assert(err == OK);
|
||||
PoolByteArray hmac = ctx.Finish();
|
||||
GD.Print(hmac.HexEncode());
|
||||
}
|
||||
}
|
||||
[/codeblock]
|
||||
[b]Note:[/b] Not available in HTML5 exports.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
@ -162,7 +162,7 @@
|
||||
<argument index="1" name="recursive" type="bool" default="true" />
|
||||
<argument index="2" name="owned" type="bool" default="true" />
|
||||
<description>
|
||||
Finds a descendant of this node whose name matches [code]mask[/code] as in [method String.match] (i.e. case-sensitive, but [code]"*"[/code] matches zero or more characters and [code]"?"[/code] matches any single character except [code]"."[/code]).
|
||||
Finds a descendant of this node whose name matches [code]mask[/code] as in [method String.match] (i.e. case-sensitive, but [code]"*"[/code] matches zero or more characters and [code]"?"[/code] matches any single character except [code]"."[/code]). Returns [code]null[/code] if no matching [Node] is found.
|
||||
[b]Note:[/b] It does not match against the full path, just against individual node names.
|
||||
If [code]owned[/code] is [code]true[/code], this method only finds nodes whose owner is this node. This is especially important for scenes instantiated through a script, because those scenes don't have an owner.
|
||||
[b]Note:[/b] As this method walks through all the descendants of the node, it is the slowest way to get a reference to another node. Whenever possible, consider using [method get_node] instead. To avoid using [method find_node] too often, consider caching the node reference into a variable.
|
||||
|
@ -325,7 +325,6 @@
|
||||
<argument index="0" name="body" type="RID" />
|
||||
<description>
|
||||
Returns the physics layer or layers a body can collide with.
|
||||
-
|
||||
</description>
|
||||
</method>
|
||||
<method name="body_get_direct_state">
|
||||
|
@ -398,9 +398,10 @@
|
||||
Message to be displayed before the backtrace when the engine crashes.
|
||||
</member>
|
||||
<member name="debug/settings/fps/force_fps" type="int" setter="" getter="" default="0">
|
||||
Maximum number of frames per second allowed. The actual number of frames per second may still be below this value if the game is lagging.
|
||||
Maximum number of frames per second allowed. The actual number of frames per second may still be below this value if the game is lagging. See also [member physics/common/physics_fps].
|
||||
If [member display/window/vsync/use_vsync] is enabled, it takes precedence and the forced FPS number cannot exceed the monitor's refresh rate.
|
||||
This setting is therefore mostly relevant for lowering the maximum FPS below VSync, e.g. to perform non-real-time rendering of static frames, or test the project under lag conditions.
|
||||
[b]Note:[/b] This property is only read when the project starts. To change the rendering FPS cap at runtime, set [member Engine.target_fps] instead.
|
||||
</member>
|
||||
<member name="debug/settings/gdscript/max_call_stack" type="int" setter="" getter="" default="1024">
|
||||
Maximum call stack allowed for debugging GDScript.
|
||||
@ -1122,8 +1123,9 @@
|
||||
If disabled, the legacy behavior is used, which consists in queuing the picking input events during pause (so nodes won't get them) and flushing that queue on resume, against the state of the 2D/3D world at that point.
|
||||
</member>
|
||||
<member name="physics/common/physics_fps" type="int" setter="" getter="" default="60">
|
||||
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run.
|
||||
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. See also [member debug/settings/fps/force_fps].
|
||||
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.iterations_per_second] instead.
|
||||
[b]Note:[/b] Only 8 physics ticks may be simulated per rendered frame at most. If more than 8 physics ticks have to be simulated per rendered frame to keep up with rendering, the game will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended not to increase [member physics/common/physics_fps] above 240. Otherwise, the game will slow down when the rendering framerate goes below 30 FPS.
|
||||
</member>
|
||||
<member name="physics/common/physics_jitter_fix" type="float" setter="" getter="" default="0.5">
|
||||
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
|
||||
|
@ -1,12 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="ReflectionProbe" inherits="VisualInstance" version="3.4">
|
||||
<brief_description>
|
||||
Captures its surroundings to create reflections.
|
||||
Captures its surroundings to create fast, accurate reflections from a given point.
|
||||
</brief_description>
|
||||
<description>
|
||||
Capture its surroundings as a dual paraboloid image, and stores versions of it with increasing levels of blur to simulate different material roughnesses.
|
||||
The [ReflectionProbe] is used to create high-quality reflections at the cost of performance. It can be combined with [GIProbe]s and Screen Space Reflections to achieve high quality reflections. [ReflectionProbe]s render all objects within their [member cull_mask], so updating them can be quite expensive. It is best to update them once with the important static objects and then leave them.
|
||||
[b]Note:[/b] By default Godot will only render 16 reflection probes. If you need more, increase the number of atlas subdivisions. This setting can be found in [member ProjectSettings.rendering/quality/reflections/atlas_subdiv].
|
||||
The [ReflectionProbe] is used to create high-quality reflections at a low performance cost (when [member update_mode] is [constant UPDATE_ONCE]). [ReflectionProbe]s can be blended together and with the rest of the scene smoothly. [ReflectionProbe]s can also be combined with [GIProbe] and screen-space reflections ([member Environment.ss_reflections_enabled]) to get more accurate reflections in specific areas. [ReflectionProbe]s render all objects within their [member cull_mask], so updating them can be quite expensive. It is best to update them once with the important static objects and then leave them as-is.
|
||||
[b]Note:[/b] Unlike [GIProbe], [ReflectionProbe]s only source their environment from a [WorldEnvironment] node. If you specify an [Environment] resource within a [Camera] node, it will be ignored by the [ReflectionProbe]. This can lead to incorrect lighting within the [ReflectionProbe].
|
||||
[b]Note:[/b] By default, Godot will only render 16 reflection probes. If you need more, increase the number of atlas subdivisions. This setting can be found in [member ProjectSettings.rendering/quality/reflections/atlas_subdiv].
|
||||
[b]Note:[/b] The GLES2 backend will only display two reflection probes at the same time for a single mesh. If possible, split up large meshes that span over multiple reflection probes into smaller ones.
|
||||
</description>
|
||||
<tutorials>
|
||||
@ -17,15 +18,17 @@
|
||||
<members>
|
||||
<member name="box_projection" type="bool" setter="set_enable_box_projection" getter="is_box_projection_enabled" default="false">
|
||||
If [code]true[/code], enables box projection. This makes reflections look more correct in rectangle-shaped rooms by offsetting the reflection center depending on the camera's location.
|
||||
[b]Note:[/b] To better fit rectangle-shaped rooms that are not aligned to the grid, you can rotate the [ReflectionProbe] node.
|
||||
</member>
|
||||
<member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="1048575">
|
||||
Sets the cull mask which determines what objects are drawn by this probe. Every [VisualInstance] with a layer included in this cull mask will be rendered by the probe. It is best to only include large objects which are likely to take up a lot of space in the reflection in order to save on rendering cost.
|
||||
Sets the cull mask which determines what objects are drawn by this probe. Every [VisualInstance] with a layer included in this cull mask will be rendered by the probe. To improve performance, it is best to only include large objects which are likely to take up a lot of space in the reflection.
|
||||
</member>
|
||||
<member name="enable_shadows" type="bool" setter="set_enable_shadows" getter="are_shadows_enabled" default="false">
|
||||
If [code]true[/code], computes shadows in the reflection probe. This makes the reflection probe slower to render; you may want to disable this if using the [constant UPDATE_ALWAYS] [member update_mode].
|
||||
</member>
|
||||
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3( 1, 1, 1 )">
|
||||
The size of the reflection probe. The larger the extents the more space covered by the probe which will lower the perceived resolution. It is best to keep the extents only as large as you need them.
|
||||
[b]Note:[/b] To better fit areas that are not aligned to the grid, you can rotate the [ReflectionProbe] node.
|
||||
</member>
|
||||
<member name="intensity" type="float" setter="set_intensity" getter="get_intensity" default="1.0">
|
||||
Defines the reflection intensity. Intensity modulates the strength of the reflection.
|
||||
@ -43,21 +46,21 @@
|
||||
If [code]true[/code], reflections will ignore sky contribution. Ambient lighting is then controlled by the [code]interior_ambient_*[/code] properties.
|
||||
</member>
|
||||
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="0.0">
|
||||
Sets the max distance away from the probe an object can be before it is culled.
|
||||
The maximum distance away from the [ReflectionProbe] an object can be before it is culled. Decrease this to improve performance, especially when using the [constant UPDATE_ALWAYS] [member update_mode].
|
||||
</member>
|
||||
<member name="origin_offset" type="Vector3" setter="set_origin_offset" getter="get_origin_offset" default="Vector3( 0, 0, 0 )">
|
||||
Sets the origin offset to be used when this reflection probe is in box project mode.
|
||||
Sets the origin offset to be used when this [ReflectionProbe] is in [member box_projection] mode. This can be set to a non-zero value to ensure a reflection fits a rectangle-shaped room, while reducing the amount of objects that "get in the way" of the reflection.
|
||||
</member>
|
||||
<member name="update_mode" type="int" setter="set_update_mode" getter="get_update_mode" enum="ReflectionProbe.UpdateMode" default="0">
|
||||
Sets how frequently the probe is updated. Can be [constant UPDATE_ONCE] or [constant UPDATE_ALWAYS].
|
||||
Sets how frequently the [ReflectionProbe] is updated. Can be [constant UPDATE_ONCE] or [constant UPDATE_ALWAYS].
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="UPDATE_ONCE" value="0" enum="UpdateMode">
|
||||
Update the probe once on the next frame.
|
||||
Update the probe once on the next frame (recommended for most objects). The corresponding radiance map will be generated over the following six frames. This takes more time to update than [constant UPDATE_ALWAYS], but it has a lower performance cost and can result in higher-quality reflections. The ReflectionProbe is updated when its transform changes, but not when nearby geometry changes. You can force a [ReflectionProbe] update by moving the [ReflectionProbe] slightly in any direction.
|
||||
</constant>
|
||||
<constant name="UPDATE_ALWAYS" value="1" enum="UpdateMode">
|
||||
Update the probe every frame. This is needed when you want to capture dynamic objects. However, it results in an increased render time. Use [constant UPDATE_ONCE] whenever possible.
|
||||
Update the probe every frame. This provides better results for fast-moving dynamic objects (such as cars). However, it has a significant performance cost. Due to the cost, it's recommended to only use one ReflectionProbe with [constant UPDATE_ALWAYS] at most per scene. For all other use cases, use [constant UPDATE_ONCE].
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
@ -241,7 +241,7 @@
|
||||
<method name="dedent">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns a copy of the string with indentation (leading tabs and spaces) removed.
|
||||
Returns a copy of the string with indentation (leading tabs and spaces) removed. See also [method indent] to add indentation.
|
||||
</description>
|
||||
</method>
|
||||
<method name="empty">
|
||||
@ -380,6 +380,15 @@
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="indent">
|
||||
<return type="String" />
|
||||
<argument index="0" name="prefix" type="String" />
|
||||
<description>
|
||||
Returns a copy of the string with lines indented with [code]prefix[/code].
|
||||
For example, the string can be indented with two tabs using [code]"\t\t"[/code], or four spaces using [code]" "[/code]. The prefix can be any string so it can also be used to comment out strings with e.g. [code]"# "[/code]. See also [method dedent] to remove indentation.
|
||||
[b]Note:[/b] Empty lines are kept empty.
|
||||
</description>
|
||||
</method>
|
||||
<method name="insert">
|
||||
<return type="String" />
|
||||
<argument index="0" name="position" type="int" />
|
||||
|
@ -4,7 +4,8 @@
|
||||
Texture with 3 dimensions.
|
||||
</brief_description>
|
||||
<description>
|
||||
Texture3D is a 3-dimensional texture that has a width, height, and depth.
|
||||
Texture3D is a 3-dimensional [Texture] that has a width, height, and depth. See also [TextureArray].
|
||||
[b]Note:[/b] [Texture3D]s can only be sampled in shaders in the GLES3 backend. In GLES2, their data can be accessed via scripting, but there is no way to render them in a hardware-accelerated manner.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
@ -4,8 +4,8 @@
|
||||
Array of textures stored in a single primitive.
|
||||
</brief_description>
|
||||
<description>
|
||||
[TextureArray]s store an array of [Image]s in a single [Texture] primitive. Each layer of the texture array has its own mipmap chain. This makes it is a good alternative to texture atlases.
|
||||
[TextureArray]s must be displayed using shaders. After importing your file as a [TextureArray] and setting the appropriate Horizontal and Vertical Slices, display it by setting it as a uniform to a shader, for example:
|
||||
[TextureArray]s store an array of [Image]s in a single [Texture] primitive. Each layer of the texture array has its own mipmap chain. This makes it is a good alternative to texture atlases. See also [Texture3D].
|
||||
[TextureArray]s must be displayed using shaders. After importing your file as a [TextureArray] and setting the appropriate Horizontal and Vertical Slices, display it by setting it as a uniform to a shader, for example (2D):
|
||||
[codeblock]
|
||||
shader_type canvas_item;
|
||||
|
||||
@ -17,6 +17,18 @@
|
||||
}
|
||||
[/codeblock]
|
||||
Set the integer uniform "index" to show a particular part of the texture as defined by the Horizontal and Vertical Slices in the importer.
|
||||
[b]Note:[/b] When sampling an albedo texture from a texture array in 3D, the sRGB -> linear conversion hint ([code]hint_albedo[/code]) should be used to prevent colors from looking washed out:
|
||||
[codeblock]
|
||||
shader_type spatial;
|
||||
|
||||
uniform sampler2DArray tex : hint_albedo;
|
||||
uniform int index;
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = texture(tex, vec3(UV.x, UV.y, float(index)));
|
||||
}
|
||||
[/codeblock]
|
||||
[b]Note:[/b] [TextureArray]s can only be sampled in shaders in the GLES3 backend. In GLES2, their data can be accessed via scripting, but there is no way to render them in a hardware-accelerated manner.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
@ -39,7 +39,7 @@ void main() {
|
||||
|
||||
#if 1
|
||||
//more precise and expensive, but less jittery
|
||||
ivec2 next_pos = ivec2(gl_FragCoord.xy + ivec2(1)) * source_render_size / target_size;
|
||||
ivec2 next_pos = (ivec2(gl_FragCoord.xy) + ivec2(1)) * source_render_size / target_size;
|
||||
next_pos = max(next_pos, src_pos + ivec2(1)); //so it at least reads one pixel
|
||||
highp vec3 source_color = vec3(0.0);
|
||||
for (int i = src_pos.x; i < next_pos.x; i++) {
|
||||
|
@ -37,9 +37,39 @@
|
||||
#include "core/os/dir_access.h"
|
||||
#include "core/project_settings.h"
|
||||
#include "core/script_language.h"
|
||||
#include "core/translation.h"
|
||||
#include "core/version.h"
|
||||
#include "scene/resources/theme.h"
|
||||
|
||||
static String _get_indent(const String &p_text) {
|
||||
String indent;
|
||||
bool has_text = false;
|
||||
int line_start = 0;
|
||||
|
||||
for (int i = 0; i < p_text.length(); i++) {
|
||||
const char32_t c = p_text[i];
|
||||
if (c == '\n') {
|
||||
line_start = i + 1;
|
||||
} else if (c > 32) {
|
||||
has_text = true;
|
||||
indent = p_text.substr(line_start, i - line_start);
|
||||
break; // Indentation of the first line that has text.
|
||||
}
|
||||
}
|
||||
if (!has_text) {
|
||||
return p_text;
|
||||
}
|
||||
return indent;
|
||||
}
|
||||
|
||||
static String _translate_doc_string(const String &p_text) {
|
||||
const String indent = _get_indent(p_text);
|
||||
const String message = p_text.dedent().strip_edges();
|
||||
const String translated = TranslationServer::get_singleton()->doc_translate(message);
|
||||
// No need to restore stripped edges because they'll be stripped again later.
|
||||
return translated.indent(indent);
|
||||
}
|
||||
|
||||
void DocData::merge_from(const DocData &p_data) {
|
||||
for (Map<String, ClassDoc>::Element *E = class_list.front(); E; E = E->next()) {
|
||||
ClassDoc &c = E->get();
|
||||
@ -1051,11 +1081,11 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
|
||||
_write_string(f, 0, header);
|
||||
|
||||
_write_string(f, 1, "<brief_description>");
|
||||
_write_string(f, 2, c.brief_description.strip_edges().xml_escape());
|
||||
_write_string(f, 2, _translate_doc_string(c.brief_description).strip_edges().xml_escape());
|
||||
_write_string(f, 1, "</brief_description>");
|
||||
|
||||
_write_string(f, 1, "<description>");
|
||||
_write_string(f, 2, c.description.strip_edges().xml_escape());
|
||||
_write_string(f, 2, _translate_doc_string(c.description).strip_edges().xml_escape());
|
||||
_write_string(f, 1, "</description>");
|
||||
|
||||
_write_string(f, 1, "<tutorials>");
|
||||
@ -1104,7 +1134,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
|
||||
}
|
||||
|
||||
_write_string(f, 3, "<description>");
|
||||
_write_string(f, 4, m.description.strip_edges().xml_escape());
|
||||
_write_string(f, 4, _translate_doc_string(m.description).strip_edges().xml_escape());
|
||||
_write_string(f, 3, "</description>");
|
||||
|
||||
_write_string(f, 2, "</method>");
|
||||
@ -1132,7 +1162,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
|
||||
_write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\" override=\"true\"" + additional_attributes + " />");
|
||||
} else {
|
||||
_write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\"" + additional_attributes + ">");
|
||||
_write_string(f, 3, p.description.strip_edges().xml_escape());
|
||||
_write_string(f, 3, _translate_doc_string(p.description).strip_edges().xml_escape());
|
||||
_write_string(f, 2, "</member>");
|
||||
}
|
||||
}
|
||||
@ -1152,7 +1182,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
|
||||
}
|
||||
|
||||
_write_string(f, 3, "<description>");
|
||||
_write_string(f, 4, m.description.strip_edges().xml_escape());
|
||||
_write_string(f, 4, _translate_doc_string(m.description).strip_edges().xml_escape());
|
||||
_write_string(f, 3, "</description>");
|
||||
|
||||
_write_string(f, 2, "</signal>");
|
||||
@ -1178,7 +1208,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
|
||||
_write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"platform-dependent\">");
|
||||
}
|
||||
}
|
||||
_write_string(f, 3, k.description.strip_edges().xml_escape());
|
||||
_write_string(f, 3, _translate_doc_string(k.description).strip_edges().xml_escape());
|
||||
_write_string(f, 2, "</constant>");
|
||||
}
|
||||
|
||||
@ -1197,7 +1227,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
|
||||
_write_string(f, 2, "<theme_item name=\"" + ti.name + "\" data_type=\"" + ti.data_type + "\" type=\"" + ti.type + "\">");
|
||||
}
|
||||
|
||||
_write_string(f, 3, ti.description.strip_edges().xml_escape());
|
||||
_write_string(f, 3, _translate_doc_string(ti.description).strip_edges().xml_escape());
|
||||
|
||||
_write_string(f, 2, "</theme_item>");
|
||||
}
|
||||
|
@ -31,22 +31,18 @@
|
||||
#include "editor_settings.h"
|
||||
|
||||
#include "core/io/certs_compressed.gen.h"
|
||||
#include "core/io/compression.h"
|
||||
#include "core/io/config_file.h"
|
||||
#include "core/io/file_access_memory.h"
|
||||
#include "core/io/ip.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/io/translation_loader_po.h"
|
||||
#include "core/os/dir_access.h"
|
||||
#include "core/os/file_access.h"
|
||||
#include "core/os/keyboard.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/project_settings.h"
|
||||
#include "core/version.h"
|
||||
#include "editor/doc_translations.gen.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_translations.gen.h"
|
||||
#include "editor/editor_translation.h"
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/viewport.h"
|
||||
@ -268,17 +264,14 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
||||
const Vector<String> locales_to_skip = String("ar,bn,fa,he,hi,ml,si,ta,te,ur").split(",");
|
||||
|
||||
String best;
|
||||
|
||||
EditorTranslationList *etl = _editor_translations;
|
||||
|
||||
while (etl->data) {
|
||||
const String &locale = etl->lang;
|
||||
const Vector<String> &locales = get_editor_locales();
|
||||
for (int i = 0; i < locales.size(); i++) {
|
||||
const String &locale = locales[i];
|
||||
|
||||
// Skip locales which we can't render properly (see above comment).
|
||||
// Test against language code without regional variants (e.g. ur_PK).
|
||||
String lang_code = locale.get_slice("_", 0);
|
||||
if (locales_to_skip.find(lang_code) != -1) {
|
||||
etl++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -292,8 +285,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
||||
if (best == String() && host_lang.begins_with(locale)) {
|
||||
best = locale;
|
||||
}
|
||||
|
||||
etl++;
|
||||
}
|
||||
|
||||
if (best == String()) {
|
||||
@ -1009,50 +1000,10 @@ void EditorSettings::setup_language() {
|
||||
}
|
||||
|
||||
// Load editor translation for configured/detected locale.
|
||||
EditorTranslationList *etl = _editor_translations;
|
||||
while (etl->data) {
|
||||
if (etl->lang == lang) {
|
||||
Vector<uint8_t> data;
|
||||
data.resize(etl->uncomp_size);
|
||||
Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
|
||||
|
||||
FileAccessMemory *fa = memnew(FileAccessMemory);
|
||||
fa->open_custom(data.ptr(), data.size());
|
||||
|
||||
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(etl->lang);
|
||||
TranslationServer::get_singleton()->set_tool_translation(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
etl++;
|
||||
}
|
||||
load_editor_translations(lang);
|
||||
|
||||
// Load class reference translation.
|
||||
DocTranslationList *dtl = _doc_translations;
|
||||
while (dtl->data) {
|
||||
if (dtl->lang == lang) {
|
||||
Vector<uint8_t> data;
|
||||
data.resize(dtl->uncomp_size);
|
||||
Compression::decompress(data.ptrw(), dtl->uncomp_size, dtl->data, dtl->comp_size, Compression::MODE_DEFLATE);
|
||||
|
||||
FileAccessMemory *fa = memnew(FileAccessMemory);
|
||||
fa->open_custom(data.ptr(), data.size());
|
||||
|
||||
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(dtl->lang);
|
||||
TranslationServer::get_singleton()->set_doc_translation(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dtl++;
|
||||
}
|
||||
load_doc_translations(lang);
|
||||
}
|
||||
|
||||
void EditorSettings::setup_network() {
|
||||
|
99
editor/editor_translation.cpp
Normal file
99
editor/editor_translation.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*************************************************************************/
|
||||
/* editor_translation.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "editor/editor_translation.h"
|
||||
|
||||
#include "core/io/compression.h"
|
||||
#include "core/io/file_access_memory.h"
|
||||
#include "core/io/translation_loader_po.h"
|
||||
#include "editor/doc_translations.gen.h"
|
||||
#include "editor/editor_translations.gen.h"
|
||||
|
||||
Vector<String> get_editor_locales() {
|
||||
Vector<String> locales;
|
||||
|
||||
EditorTranslationList *etl = _editor_translations;
|
||||
while (etl->data) {
|
||||
const String &locale = etl->lang;
|
||||
locales.push_back(locale);
|
||||
|
||||
etl++;
|
||||
}
|
||||
|
||||
return locales;
|
||||
}
|
||||
|
||||
void load_editor_translations(const String &p_locale) {
|
||||
EditorTranslationList *etl = _editor_translations;
|
||||
while (etl->data) {
|
||||
if (etl->lang == p_locale) {
|
||||
Vector<uint8_t> data;
|
||||
data.resize(etl->uncomp_size);
|
||||
Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
|
||||
|
||||
FileAccessMemory *fa = memnew(FileAccessMemory);
|
||||
fa->open_custom(data.ptr(), data.size());
|
||||
|
||||
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(etl->lang);
|
||||
TranslationServer::get_singleton()->set_tool_translation(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
etl++;
|
||||
}
|
||||
}
|
||||
|
||||
void load_doc_translations(const String &p_locale) {
|
||||
DocTranslationList *dtl = _doc_translations;
|
||||
while (dtl->data) {
|
||||
if (dtl->lang == p_locale) {
|
||||
Vector<uint8_t> data;
|
||||
data.resize(dtl->uncomp_size);
|
||||
Compression::decompress(data.ptrw(), dtl->uncomp_size, dtl->data, dtl->comp_size, Compression::MODE_DEFLATE);
|
||||
|
||||
FileAccessMemory *fa = memnew(FileAccessMemory);
|
||||
fa->open_custom(data.ptr(), data.size());
|
||||
|
||||
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(dtl->lang);
|
||||
TranslationServer::get_singleton()->set_doc_translation(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dtl++;
|
||||
}
|
||||
}
|
41
editor/editor_translation.h
Normal file
41
editor/editor_translation.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*************************************************************************/
|
||||
/* editor_translation.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef EDITOR_TRANSLATION_H
|
||||
#define EDITOR_TRANSLATION_H
|
||||
|
||||
#include "core/ustring.h"
|
||||
#include "core/vector.h"
|
||||
|
||||
Vector<String> get_editor_locales();
|
||||
void load_editor_translations(const String &p_locale);
|
||||
void load_doc_translations(const String &p_locale);
|
||||
|
||||
#endif // EDITOR_TRANSLATION_H
|
@ -811,7 +811,10 @@ void InputDefault::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) {
|
||||
|
||||
Joypad &joy = joy_names[p_device];
|
||||
|
||||
if (joy.last_axis[p_axis] == p_value.value) {
|
||||
// Make sure that we don't generate events for up to 5% jitter
|
||||
// This is needed for Nintendo Switch Pro controllers, which jitter at rest
|
||||
const float MIN_AXIS_CHANGE = 0.05f;
|
||||
if (fabs(joy.last_axis[p_axis] - p_value.value) < MIN_AXIS_CHANGE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@
|
||||
#include "editor/doc/doc_data_class_path.gen.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_settings.h"
|
||||
#include "editor/editor_translation.h"
|
||||
#include "editor/progress_dialog.h"
|
||||
#include "editor/project_manager.h"
|
||||
#ifndef NO_EDITOR_SPLASH
|
||||
@ -1498,7 +1499,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||
VisualServer::get_singleton()->callbacks_register(visual_server_callbacks);
|
||||
|
||||
_start_success = true;
|
||||
locale = String();
|
||||
|
||||
ClassDB::set_current_api(ClassDB::API_NONE); //no more api is registered at this point
|
||||
|
||||
@ -1606,6 +1606,11 @@ bool Main::start() {
|
||||
if (doc_tool_path != "") {
|
||||
Engine::get_singleton()->set_editor_hint(true); // Needed to instance editor-only classes for their default values
|
||||
|
||||
// Translate the class reference only when `-l LOCALE` parameter is given.
|
||||
if (!locale.empty() && locale != "en") {
|
||||
load_doc_translations(locale);
|
||||
}
|
||||
|
||||
{
|
||||
DirAccessRef da = DirAccess::open(doc_tool_path);
|
||||
ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a valid directory path.");
|
||||
|
@ -154,6 +154,10 @@ void WebRTCMultiplayer::_find_next_peer() {
|
||||
}
|
||||
// After last.
|
||||
while (E) {
|
||||
if (!E->get()->connected) {
|
||||
E = E->next();
|
||||
continue;
|
||||
}
|
||||
for (List<Ref<WebRTCDataChannel>>::Element *F = E->get()->channels.front(); F; F = F->next()) {
|
||||
if (F->get()->get_available_packet_count()) {
|
||||
next_packet_peer = E->key();
|
||||
@ -165,6 +169,10 @@ void WebRTCMultiplayer::_find_next_peer() {
|
||||
E = peer_map.front();
|
||||
// Before last
|
||||
while (E) {
|
||||
if (!E->get()->connected) {
|
||||
E = E->next();
|
||||
continue;
|
||||
}
|
||||
for (List<Ref<WebRTCDataChannel>>::Element *F = E->get()->channels.front(); F; F = F->next()) {
|
||||
if (F->get()->get_available_packet_count()) {
|
||||
next_packet_peer = E->key();
|
||||
@ -357,6 +365,9 @@ int WebRTCMultiplayer::get_available_packet_count() const {
|
||||
}
|
||||
int size = 0;
|
||||
for (Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.front(); E; E = E->next()) {
|
||||
if (!E->get()->connected) {
|
||||
continue;
|
||||
}
|
||||
for (List<Ref<WebRTCDataChannel>>::Element *F = E->get()->channels.front(); F; F = F->next()) {
|
||||
size += F->get()->get_available_packet_count();
|
||||
}
|
||||
|
@ -54,11 +54,14 @@ Error EMWSPeer::read_msg(const uint8_t *p_data, uint32_t p_size, bool p_is_strin
|
||||
}
|
||||
|
||||
Error EMWSPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
|
||||
ERR_FAIL_COND_V(_out_buf_size && ((uint64_t)godot_js_websocket_buffered_amount(peer_sock) >= (1ULL << _out_buf_size)), ERR_OUT_OF_MEMORY);
|
||||
ERR_FAIL_COND_V(_out_buf_size && ((uint64_t)godot_js_websocket_buffered_amount(peer_sock) + p_buffer_size >= (1ULL << _out_buf_size)), ERR_OUT_OF_MEMORY);
|
||||
|
||||
int is_bin = write_mode == WebSocketPeer::WRITE_MODE_BINARY ? 1 : 0;
|
||||
|
||||
godot_js_websocket_send(peer_sock, p_buffer, p_buffer_size, is_bin);
|
||||
if (godot_js_websocket_send(peer_sock, p_buffer, p_buffer_size, is_bin) != 0) {
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
|
@ -242,15 +242,14 @@ void WSLPeer::poll() {
|
||||
Error WSLPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
|
||||
ERR_FAIL_COND_V(!is_connected_to_host(), FAILED);
|
||||
ERR_FAIL_COND_V(_out_pkt_size && (wslay_event_get_queued_msg_count(_data->ctx) >= (1ULL << _out_pkt_size)), ERR_OUT_OF_MEMORY);
|
||||
ERR_FAIL_COND_V(_out_buf_size && (wslay_event_get_queued_msg_length(_data->ctx) >= (1ULL << _out_buf_size)), ERR_OUT_OF_MEMORY);
|
||||
ERR_FAIL_COND_V(_out_buf_size && (wslay_event_get_queued_msg_length(_data->ctx) + p_buffer_size >= (1ULL << _out_buf_size)), ERR_OUT_OF_MEMORY);
|
||||
|
||||
struct wslay_event_msg msg; // Should I use fragmented?
|
||||
struct wslay_event_msg msg;
|
||||
msg.opcode = write_mode == WRITE_MODE_TEXT ? WSLAY_TEXT_FRAME : WSLAY_BINARY_FRAME;
|
||||
msg.msg = p_buffer;
|
||||
msg.msg_length = p_buffer_size;
|
||||
|
||||
wslay_event_queue_msg(_data->ctx, &msg);
|
||||
if (wslay_event_send(_data->ctx) < 0) {
|
||||
if (wslay_event_queue_msg(_data->ctx, &msg) != 0 || wslay_event_send(_data->ctx) != 0) {
|
||||
close_now();
|
||||
return FAILED;
|
||||
}
|
||||
|
@ -2229,11 +2229,25 @@ bool OS_Windows::is_window_focused() const {
|
||||
return window_focused;
|
||||
}
|
||||
|
||||
bool OS_Windows::_is_win11_terminal() const {
|
||||
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD dwMode = 0;
|
||||
if (GetConsoleMode(hStdOut, &dwMode)) {
|
||||
return ((dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OS_Windows::set_console_visible(bool p_enabled) {
|
||||
if (console_visible == p_enabled)
|
||||
return;
|
||||
ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE);
|
||||
console_visible = p_enabled;
|
||||
|
||||
if (!_is_win11_terminal()) {
|
||||
// GetConsoleWindow is not supported by the Windows Terminal.
|
||||
ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE);
|
||||
console_visible = p_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
bool OS_Windows::is_console_visible() const {
|
||||
@ -2840,7 +2854,8 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
|
||||
}
|
||||
|
||||
DWORD creation_flags = NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW;
|
||||
if (p_path == get_executable_path() && GetConsoleWindow() != NULL) {
|
||||
if (p_path == get_executable_path() && GetConsoleWindow() != NULL && _is_win11_terminal()) {
|
||||
// Open a new terminal as a workaround for Windows Terminal bug.
|
||||
creation_flags |= CREATE_NEW_CONSOLE;
|
||||
}
|
||||
|
||||
|
@ -371,6 +371,8 @@ class OS_Windows : public OS {
|
||||
|
||||
CrashHandler crash_handler;
|
||||
|
||||
bool _is_win11_terminal() const;
|
||||
|
||||
void _drag_event(float p_x, float p_y, int idx);
|
||||
void _touch_event(bool p_pressed, float p_x, float p_y, int idx);
|
||||
|
||||
|
@ -5996,6 +5996,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||
|
||||
} else {
|
||||
_set_error("Expected valid type hint after ':'.");
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
|
||||
|
Loading…
Reference in New Issue
Block a user