Merge pull request #57217 from akien-mga/3.4-cherrypicks
This commit is contained in:
commit
4a83366185
|
@ -2988,6 +2988,7 @@ void Image::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_GENERIC);
|
||||
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_SRGB);
|
||||
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_NORMAL);
|
||||
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_LAYERED);
|
||||
}
|
||||
|
||||
void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, CompressSource)) {
|
||||
|
|
|
@ -11,17 +11,6 @@
|
|||
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_mix_mode" qualifiers="const">
|
||||
<return type="int" enum="AnimationNodeOneShot.MixMode" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_mix_mode">
|
||||
<return type="void" />
|
||||
<argument index="0" name="mode" type="int" enum="AnimationNodeOneShot.MixMode" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="autorestart" type="bool" setter="set_autorestart" getter="has_autorestart" default="false">
|
||||
|
@ -37,6 +26,8 @@
|
|||
</member>
|
||||
<member name="fadeout_time" type="float" setter="set_fadeout_time" getter="get_fadeout_time" default="0.1">
|
||||
</member>
|
||||
<member name="mix_mode" type="int" setter="set_mix_mode" getter="get_mix_mode" enum="AnimationNodeOneShot.MixMode" default="0">
|
||||
</member>
|
||||
<member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
|
||||
</member>
|
||||
</members>
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
When enabled, an octree containing the scene's lighting information will be computed. This octree will then be used to light dynamic objects in the scene.
|
||||
</member>
|
||||
<member name="capture_propagation" type="float" setter="set_capture_propagation" getter="get_capture_propagation" default="1.0">
|
||||
Bias value to reduce the amount of light proagation in the captured octree.
|
||||
Bias value to reduce the amount of light propagation in the captured octree.
|
||||
</member>
|
||||
<member name="capture_quality" type="int" setter="set_capture_quality" getter="get_capture_quality" enum="BakedLightmap.BakeQuality" default="1">
|
||||
Bake quality of the capture data.
|
||||
|
|
|
@ -182,7 +182,7 @@
|
|||
If [code]true[/code], the [CollisionObject] will continue to receive input events as the mouse is dragged across its shapes.
|
||||
</member>
|
||||
<member name="input_ray_pickable" type="bool" setter="set_ray_pickable" getter="is_ray_pickable" default="true">
|
||||
If [code]true[/code], the [CollisionObject]'s shapes will respond to [RayCast]s.
|
||||
If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [member collision_layer] bit to be set.
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
|
|
|
@ -207,7 +207,7 @@
|
|||
[b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
|
||||
</member>
|
||||
<member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable" default="true">
|
||||
If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [code]collision_layer[/code] bit to be set.
|
||||
If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [member collision_layer] bit to be set.
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
|
|
|
@ -9,7 +9,11 @@
|
|||
- Glow
|
||||
- Tonemap (Auto Exposure)
|
||||
- Adjustments
|
||||
These effects will only apply when the [Viewport]'s intended usage is "3D" or "3D Without Effects". This can be configured for the root Viewport with [member ProjectSettings.rendering/quality/intended_usage/framebuffer_allocation], or for specific Viewports via the [member Viewport.usage] property.
|
||||
If the target [Viewport] is set to "2D Without Sampling", all post-processing effects will be unavailable. With "3D Without Effects", the following options will be unavailable:
|
||||
- Ssao
|
||||
- Ss Reflections
|
||||
This can be configured for the root Viewport with [member ProjectSettings.rendering/quality/intended_usage/framebuffer_allocation], or for specific Viewports via the [member Viewport.usage] property.
|
||||
Note that [member ProjectSettings.rendering/quality/intended_usage/framebuffer_allocation] has a mobile platform override to use "3D Without Effects" by default. It improves the performance on mobile devices, but at the same time affects the screen display on mobile devices.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Environment and post-processing">https://docs.godotengine.org/en/3.4/tutorials/3d/environment_and_post_processing.html</link>
|
||||
|
|
|
@ -603,5 +603,8 @@
|
|||
<constant name="COMPRESS_SOURCE_NORMAL" value="2" enum="CompressSource">
|
||||
Source texture (before compression) is a normal texture (e.g. it can be compressed into two channels).
|
||||
</constant>
|
||||
<constant name="COMPRESS_SOURCE_LAYERED" value="3" enum="CompressSource">
|
||||
Source texture (before compression) is a [TextureLayered].
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<description>
|
||||
Converts a [Variant] var to JSON text and returns the result. Useful for serializing data to store or send over the network.
|
||||
[b]Note:[/b] The JSON specification does not define integer or float types, but only a [i]number[/i] type. Therefore, converting a Variant to JSON text will convert all numerical values to [float] types.
|
||||
Use [code]indent[/code] parameter to pretty print the output.
|
||||
The [code]indent[/code] parameter controls if and how something is indented, the string used for this parameter will be used where there should be an indent in the output, even spaces like [code]" "[/code] will work. [code]\t[/code] and [code]\n[/code] can also be used for a tab indent, or to make a newline for each indent respectively.
|
||||
[b]Example output:[/b]
|
||||
[codeblock]
|
||||
## JSON.print(my_dictionary)
|
||||
|
@ -45,6 +45,22 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
|
||||
## JSON.print(my_dictionary, "...")
|
||||
{
|
||||
..."name": "my_dictionary",
|
||||
..."version": "1.0.0",
|
||||
..."entities": [
|
||||
......{
|
||||
........."name": "entity_0",
|
||||
........."value": "value_0"
|
||||
......},
|
||||
......{
|
||||
........."name": "entity_1",
|
||||
........."value": "value_1"
|
||||
......}
|
||||
...]
|
||||
}
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
|
|
|
@ -106,6 +106,9 @@
|
|||
OS.execute("CMD.exe", ["/C", "cd %TEMP% && dir"], true, output)
|
||||
[/codeblock]
|
||||
[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
|
||||
[b]Note:[/b] To execute a Windows command interpreter built-in command, specify [code]cmd.exe[/code] in [code]path[/code], [code]/c[/code] as the first argument, and the desired command as the second argument.
|
||||
[b]Note:[/b] To execute a PowerShell built-in command, specify [code]powershell.exe[/code] in [code]path[/code], [code]-Command[/code] as the first argument, and the desired command as the second argument.
|
||||
[b]Note:[/b] To execute a Unix shell built-in command, specify shell executable name in [code]path[/code], [code]-c[/code] as the first argument, and the desired command as the second argument.
|
||||
</description>
|
||||
</method>
|
||||
<method name="find_scancode_from_string" qualifiers="const">
|
||||
|
|
|
@ -243,7 +243,7 @@
|
|||
</member>
|
||||
<member name="bbcode_text" type="String" setter="set_bbcode" getter="get_bbcode" default="""">
|
||||
The label's text in BBCode format. Is not representative of manual modifications to the internal tag stack. Erases changes made by other methods when edited.
|
||||
[b]Note:[/b] It is unadvised to use the [code]+=[/code] operator with [code]bbcode_text[/code] (e.g. [code]bbcode_text += "some string"[/code]) as it replaces the whole text and can cause slowdowns. Use [method append_bbcode] for adding text instead, unless you absolutely need to close a tag that was opened in an earlier method call.
|
||||
[b]Note:[/b] It is unadvised to use the [code]+=[/code] operator with [code]bbcode_text[/code] (e.g. [code]bbcode_text += "some string"[/code]) as it replaces the whole text and can cause slowdowns. It will also erase all BBCode that was added to stack using [code]push_*[/code] methods. Use [method append_bbcode] for adding text instead, unless you absolutely need to close a tag that was opened in an earlier method call.
|
||||
</member>
|
||||
<member name="custom_effects" type="Array" setter="set_effects" getter="get_effects" default="[ ]">
|
||||
The currently installed custom effects. This is an array of [RichTextEffect]s.
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
</brief_description>
|
||||
<description>
|
||||
A deformable physics body. Used to create elastic or deformable objects such as cloth, rubber, or other flexible materials.
|
||||
[b]Note:[/b] There are many known bugs in [SoftBody]. Therefore, it's not recommended to use them for things that can affect gameplay (such as a player character made entirely out of soft bodies).
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/physics/soft_body.html</link>
|
||||
|
|
|
@ -57,13 +57,15 @@
|
|||
If [code]true[/code], texture is flipped vertically.
|
||||
</member>
|
||||
<member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color( 1, 1, 1, 1 )">
|
||||
A color value that gets multiplied on, could be used for mood-coloring or to simulate the color of light.
|
||||
A color value used to [i]multiply[/i] the texture's colors. Can be used for mood-coloring or to simulate the color of light.
|
||||
[b]Note:[/b] If a [member GeometryInstance.material_override] is defined on the [SpriteBase3D], the material override must be configured to take vertex colors into account for albedo. Otherwise, the color defined in [member modulate] will be ignored. For a [SpatialMaterial], [member SpatialMaterial.vertex_color_use_as_albedo] must be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/color] must be inserted in the shader's [code]fragment()[/code] function.
|
||||
</member>
|
||||
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2( 0, 0 )">
|
||||
The texture's drawing offset.
|
||||
</member>
|
||||
<member name="opacity" type="float" setter="set_opacity" getter="get_opacity" default="1.0">
|
||||
The objects' visibility on a scale from [code]0[/code] fully invisible to [code]1[/code] fully visible.
|
||||
The texture's visibility on a scale from [code]0[/code] (fully invisible) to [code]1[/code] (fully visible). [member opacity] is a multiplier for the [member modulate] color's alpha channel.
|
||||
[b]Note:[/b] If a [member GeometryInstance.material_override] is defined on the [SpriteBase3D], the material override must be configured to take vertex colors into account for albedo. Otherwise, the opacity defined in [member opacity] will be ignored. For a [SpatialMaterial], [member SpatialMaterial.vertex_color_use_as_albedo] must be [code]true[/code]. For a [ShaderMaterial], [code]ALPHA *= COLOR.a;[/color] must be inserted in the shader's [code]fragment()[/code] function.
|
||||
</member>
|
||||
<member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01">
|
||||
The size of one pixel's width on the sprite to scale it in 3D.
|
||||
|
|
|
@ -750,13 +750,24 @@
|
|||
<method name="to_float">
|
||||
<return type="float" />
|
||||
<description>
|
||||
Converts a string containing a decimal number into a [code]float[/code].
|
||||
Converts a string containing a decimal number into a [code]float[/code]. The method will stop on the first non-number character except the first [code].[/code] (decimal point), and [code]e[/code] which is used for exponential.
|
||||
[codeblock]
|
||||
print("12.3".to_float()) # 12.3
|
||||
print("1.2.3".to_float()) # 1.2
|
||||
print("12ab3".to_float()) # 12
|
||||
print("1e3".to_float()) # 1000
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="to_int">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Converts a string containing an integer number into an [code]int[/code].
|
||||
Converts a string containing an integer number into an [code]int[/code]. The method will remove any non-number character and stop if it encounters a [code].[/code].
|
||||
[codeblock]
|
||||
print("123".to_int()) # 123
|
||||
print("a1b2c3".to_int()) # 123
|
||||
print("1.2.3".to_int()) # 1
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="to_lower">
|
||||
|
|
|
@ -427,6 +427,7 @@
|
|||
<argument index="1" name="color" type="Color" />
|
||||
<description>
|
||||
Sets the tile's modulation color.
|
||||
[b]Note:[/b] Modulation is performed by setting the tile's vertex color. To access this in a shader, use [code]COLOR[/code] rather than [code]MODULATE[/code] (which instead accesses the [TileMap]'s [member CanvasItem.modulate] property).
|
||||
</description>
|
||||
</method>
|
||||
<method name="tile_set_name">
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<argument index="0" name="parent" type="Object" default="null" />
|
||||
<argument index="1" name="idx" type="int" default="-1" />
|
||||
<description>
|
||||
Creates an item in the tree and adds it as a child of [code]parent[/code].
|
||||
Creates an item in the tree and adds it as a child of [code]parent[/code], which can be either a valid [TreeItem] or [code]null[/code].
|
||||
If [code]parent[/code] is [code]null[/code], the root item will be the parent, or the new item will be the root itself if the tree is empty.
|
||||
The new item will be the [code]idx[/code]th child of parent, or it will be the last child if there are not enough siblings.
|
||||
</description>
|
||||
|
@ -117,7 +117,7 @@
|
|||
<argument index="0" name="item" type="Object" />
|
||||
<argument index="1" name="column" type="int" default="-1" />
|
||||
<description>
|
||||
Returns the rectangle area for the specified item. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
|
||||
Returns the rectangle area for the specified [TreeItem]. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_item_at_position" qualifiers="const">
|
||||
|
@ -131,7 +131,7 @@
|
|||
<return type="TreeItem" />
|
||||
<argument index="0" name="from" type="Object" />
|
||||
<description>
|
||||
Returns the next selected item after the given one, or [code]null[/code] if the end is reached.
|
||||
Returns the next selected [TreeItem] after the given one, or [code]null[/code] if the end is reached.
|
||||
If [code]from[/code] is [code]null[/code], this returns the first selected item.
|
||||
</description>
|
||||
</method>
|
||||
|
@ -173,7 +173,7 @@
|
|||
<return type="void" />
|
||||
<argument index="0" name="item" type="Object" />
|
||||
<description>
|
||||
Causes the [Tree] to jump to the specified item.
|
||||
Causes the [Tree] to jump to the specified [TreeItem].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_column_expand">
|
||||
|
|
|
@ -321,7 +321,7 @@ def main(): # type: () -> None
|
|||
|
||||
for path in args.path:
|
||||
# Cut off trailing slashes so os.path.basename doesn't choke.
|
||||
if path.endswith(os.sep):
|
||||
if path.endswith("/") or path.endswith("\\"):
|
||||
path = path[:-1]
|
||||
|
||||
if os.path.basename(path) == "modules":
|
||||
|
|
|
@ -77,7 +77,6 @@ void ResourceFormatDummyTexture::get_recognized_extensions(List<String> *p_exten
|
|||
p_extensions->push_back("png");
|
||||
p_extensions->push_back("pvr");
|
||||
p_extensions->push_back("svg");
|
||||
p_extensions->push_back("svgz");
|
||||
p_extensions->push_back("tga");
|
||||
p_extensions->push_back("webp");
|
||||
}
|
||||
|
@ -99,7 +98,6 @@ String ResourceFormatDummyTexture::get_resource_type(const String &p_path) const
|
|||
extension == "png" ||
|
||||
extension == "pvr" ||
|
||||
extension == "svg" ||
|
||||
extension == "svgz" ||
|
||||
extension == "tga" ||
|
||||
extension == "webp") {
|
||||
return "ImageTexture";
|
||||
|
|
|
@ -204,7 +204,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, in
|
|||
float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));
|
||||
|
||||
float sigma2 = roughness * roughness; // TODO: this needs checking
|
||||
vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13));
|
||||
vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse / (sigma2 + 0.13));
|
||||
float B = 0.45 * sigma2 / (sigma2 + 0.09);
|
||||
|
||||
diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI);
|
||||
|
|
|
@ -186,8 +186,7 @@ void main() {
|
|||
}
|
||||
|
||||
vec2 final_pos;
|
||||
float grad;
|
||||
grad = steps_taken / float(num_steps);
|
||||
float grad = (steps_taken + 1.0) / float(num_steps);
|
||||
float initial_fade = curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), curve_fade_in);
|
||||
float fade = pow(clamp(1.0 - grad, 0.0, 1.0), distance_fade) * initial_fade;
|
||||
final_pos = pos;
|
||||
|
|
|
@ -140,7 +140,6 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
|
|||
extension_guess["jpeg"] = tree->get_icon("ImageTexture", "EditorIcons");
|
||||
extension_guess["png"] = tree->get_icon("ImageTexture", "EditorIcons");
|
||||
extension_guess["svg"] = tree->get_icon("ImageTexture", "EditorIcons");
|
||||
extension_guess["svgz"] = tree->get_icon("ImageTexture", "EditorIcons");
|
||||
extension_guess["tga"] = tree->get_icon("ImageTexture", "EditorIcons");
|
||||
extension_guess["webp"] = tree->get_icon("ImageTexture", "EditorIcons");
|
||||
|
||||
|
|
|
@ -1498,6 +1498,10 @@ void EditorFileSystem::update_file(const String &p_file) {
|
|||
_queue_update_script_classes();
|
||||
}
|
||||
|
||||
Set<String> EditorFileSystem::get_valid_extensions() const {
|
||||
return valid_extensions;
|
||||
}
|
||||
|
||||
Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector<String> &p_files) {
|
||||
String importer_name;
|
||||
|
||||
|
|
|
@ -262,6 +262,7 @@ public:
|
|||
void scan_changes();
|
||||
void get_changed_sources(List<String> *r_changed);
|
||||
void update_file(const String &p_file);
|
||||
Set<String> get_valid_extensions() const;
|
||||
|
||||
EditorFileSystemDirectory *get_filesystem_path(const String &p_path);
|
||||
String get_file_type(const String &p_file) const;
|
||||
|
|
|
@ -1436,12 +1436,18 @@ void FileSystemDock::_folder_removed(String p_folder) {
|
|||
|
||||
void FileSystemDock::_rename_operation_confirm() {
|
||||
String new_name = rename_dialog_text->get_text().strip_edges();
|
||||
String old_name = tree->get_selected()->get_text(0);
|
||||
if (new_name.length() == 0) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
|
||||
return;
|
||||
} else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
|
||||
return;
|
||||
} else if (to_rename.is_file && old_name.get_extension() != new_name.get_extension()) {
|
||||
if (!EditorFileSystem::get_singleton()->get_valid_extensions().find(new_name.get_extension())) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("This file extension is not recognized by the editor.\nIf you want to rename it anyway, use your operating system's file manager.\nAfter renaming to an unknown extension, the file won't be shown in the editor anymore."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String old_path = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1) : to_rename.path;
|
||||
|
|
|
@ -103,7 +103,7 @@ void AnimationNodeBlendTreeEditor::_property_changed(const StringName &p_propert
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_update_graph() {
|
||||
if (updating) {
|
||||
if (updating || blend_tree.is_null()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -915,6 +915,9 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node) {
|
||||
if (le == nullptr) {
|
||||
return; // The text_submitted signal triggered the graph update and freed the LineEdit.
|
||||
}
|
||||
_node_renamed(le->call("get_text"), p_node);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,9 +136,11 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
|
|||
continue;
|
||||
}
|
||||
|
||||
//Transform shape_transform = sb->shape_owner_get_transform(E->get());
|
||||
|
||||
//shape_transform.set_origin(shape_transform.get_origin() - phys_offset);
|
||||
Transform shape_transform;
|
||||
if (p_apply_xforms) {
|
||||
shape_transform = mi->get_transform();
|
||||
}
|
||||
shape_transform *= sb->get_transform() * sb->shape_owner_get_transform(E->get());
|
||||
|
||||
for (int k = 0; k < sb->shape_owner_get_shape_count(E->get()); k++) {
|
||||
Ref<Shape> collision = sb->shape_owner_get_shape(E->get(), k);
|
||||
|
@ -147,7 +149,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
|
|||
}
|
||||
MeshLibrary::ShapeData shape_data;
|
||||
shape_data.shape = collision;
|
||||
shape_data.local_transform = sb->get_transform() * sb->shape_owner_get_transform(E->get());
|
||||
shape_data.local_transform = shape_transform;
|
||||
collisions.push_back(shape_data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -258,7 +258,7 @@ void ProjectSettingsEditor::_device_input_add() {
|
|||
int idx = edit_idx;
|
||||
Dictionary old_val = ProjectSettings::get_singleton()->get(name);
|
||||
Dictionary action = old_val.duplicate();
|
||||
Array events = action["events"];
|
||||
Array events = action["events"].duplicate();
|
||||
|
||||
switch (add_type) {
|
||||
case INPUT_MOUSE_BUTTON: {
|
||||
|
@ -383,7 +383,7 @@ void ProjectSettingsEditor::_press_a_key_confirm() {
|
|||
|
||||
Dictionary old_val = ProjectSettings::get_singleton()->get(name);
|
||||
Dictionary action = old_val.duplicate();
|
||||
Array events = action["events"];
|
||||
Array events = action["events"].duplicate();
|
||||
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
Ref<InputEventKey> aie = events[i];
|
||||
|
@ -654,7 +654,7 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column,
|
|||
Dictionary action = old_val.duplicate();
|
||||
int idx = ti->get_metadata(0);
|
||||
|
||||
Array events = action["events"];
|
||||
Array events = action["events"].duplicate();
|
||||
ERR_FAIL_INDEX(idx, events.size());
|
||||
events.remove(idx);
|
||||
action["events"] = events;
|
||||
|
|
|
@ -284,6 +284,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
|
|||
vbc->add_child(lbl_preview_title);
|
||||
|
||||
lbl_preview = memnew(Label);
|
||||
lbl_preview->set_autowrap(true);
|
||||
vbc->add_child(lbl_preview);
|
||||
|
||||
// ---- Dialog related
|
||||
|
|
|
@ -1413,7 +1413,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
|||
GLOBAL_DEF("application/config/icon", String());
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/config/icon",
|
||||
PropertyInfo(Variant::STRING, "application/config/icon",
|
||||
PROPERTY_HINT_FILE, "*.png,*.webp,*.svg,*.svgz"));
|
||||
PROPERTY_HINT_FILE, "*.png,*.webp,*.svg"));
|
||||
|
||||
GLOBAL_DEF("application/config/macos_native_icon", String());
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("application/config/macos_native_icon", PropertyInfo(Variant::STRING, "application/config/macos_native_icon", PROPERTY_HINT_FILE, "*.icns"));
|
||||
|
|
|
@ -1757,7 +1757,7 @@ CSGBrush *CSGPolygon::_build_brush() {
|
|||
}
|
||||
int shape_sides = shape_polygon.size();
|
||||
Vector<int> shape_faces = Geometry::triangulate_polygon(shape_polygon);
|
||||
ERR_FAIL_COND_V_MSG(shape_faces.size() < 3, brush, "Failed to triangulate CSGPolygon");
|
||||
ERR_FAIL_COND_V_MSG(shape_faces.size() < 3, brush, "Failed to triangulate CSGPolygon. Make sure the polygon doesn't have any intersecting edges.");
|
||||
|
||||
// Get polygon enclosing Rect2.
|
||||
Rect2 shape_rect(shape_polygon[0], Vector2());
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
A CSG Mesh shape that uses a mesh resource.
|
||||
</brief_description>
|
||||
<description>
|
||||
This CSG node allows you to use any mesh resource as a CSG shape, provided it is closed, does not self-intersect, does not contain internal faces and has no edges that connect to more then two faces.
|
||||
This CSG node allows you to use any mesh resource as a CSG shape, provided it is closed, does not self-intersect, does not contain internal faces and has no edges that connect to more than two faces. See also [CSGPolygon] for drawing 2D extruded polygons to be used as CSG nodes.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
Extrudes a 2D polygon shape to create a 3D mesh.
|
||||
</brief_description>
|
||||
<description>
|
||||
An array of 2D points is extruded to quickly and easily create a variety of 3D meshes.
|
||||
An array of 2D points is extruded to quickly and easily create a variety of 3D meshes. See also [CSGMesh] for using 3D meshes as CSG nodes.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
@ -48,7 +48,8 @@
|
|||
When [member mode] is [constant MODE_PATH], this is the distance along the path, in meters, the texture coordinates will tile. When set to 0, texture coordinates will match geometry exactly with no tiling.
|
||||
</member>
|
||||
<member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon" default="PoolVector2Array( 0, 0, 0, 1, 1, 1, 1, 0 )">
|
||||
The point array that defines the 2D polygon that is extruded.
|
||||
The point array that defines the 2D polygon that is extruded. This can be a convex or concave polygon with 3 or more points. The polygon must [i]not[/i] have any intersecting edges. Otherwise, triangulation will fail and no mesh will be generated.
|
||||
[b]Note:[/b] If only 1 or 2 points are defined in [member polygon], no mesh will be generated.
|
||||
</member>
|
||||
<member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces" default="false">
|
||||
If [code]true[/code], applies smooth shading to the extrusions.
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
A GDNative library can implement [NativeScript]s, global functions to call with the [GDNative] class, or low-level engine extensions through interfaces such as [ARVRInterfaceGDNative]. The library must be compiled for each platform and architecture that the project will run on.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/scripting/gdnative/gdnative-c-example.html</link>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/scripting/gdnative/gdnative-cpp-example.html</link>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/scripting/gdnative/gdnative_c_example.html</link>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/scripting/gdnative/gdnative_cpp_example.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_current_dependencies" qualifiers="const">
|
||||
|
|
|
@ -473,7 +473,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||
err_text = "Left operand of 'is' was already freed.";
|
||||
OPCODE_BREAK;
|
||||
}
|
||||
if (b->is_invalid_object()) {
|
||||
if (b->get_type() != Variant::OBJECT || b->is_invalid_object()) {
|
||||
err_text = "Right operand of 'is' is not a class.";
|
||||
OPCODE_BREAK;
|
||||
}
|
||||
|
|
|
@ -318,6 +318,9 @@ namespace Godot.Collections
|
|||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void godot_icall_Dictionary_KeyValuePairAt_Generic(IntPtr ptr, int index, out object key, out object value, int valueTypeEncoding, IntPtr valueTypeClass);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value);
|
||||
|
||||
|
@ -484,7 +487,7 @@ namespace Godot.Collections
|
|||
|
||||
private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
|
||||
{
|
||||
Dictionary.godot_icall_Dictionary_KeyValuePairAt(GetPtr(), index, out object key, out object value);
|
||||
Dictionary.godot_icall_Dictionary_KeyValuePairAt_Generic(GetPtr(), index, out object key, out object value, valTypeEncoding, valTypeClass);
|
||||
return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
|
||||
}
|
||||
|
||||
|
|
|
@ -240,6 +240,12 @@ void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, MonoObjec
|
|||
*value = GDMonoMarshal::variant_to_mono_object(ptr->get_value_at_index(index));
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_KeyValuePairAt_Generic(Dictionary *ptr, int index, MonoObject **key, MonoObject **value, uint32_t value_type_encoding, GDMonoClass *value_type_class) {
|
||||
ManagedType type(value_type_encoding, value_type_class);
|
||||
*key = GDMonoMarshal::variant_to_mono_object(ptr->get_key_at_index(index));
|
||||
*value = GDMonoMarshal::variant_to_mono_object(ptr->get_value_at_index(index), type);
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
||||
Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
|
||||
Variant *ret = ptr->getptr(varKey);
|
||||
|
@ -350,6 +356,7 @@ void godot_register_collections_icalls() {
|
|||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", godot_icall_Dictionary_Count);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairs", godot_icall_Dictionary_KeyValuePairs);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt", godot_icall_Dictionary_KeyValuePairAt);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt_Generic", godot_icall_Dictionary_KeyValuePairAt_Generic);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", godot_icall_Dictionary_Add);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", godot_icall_Dictionary_Clear);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", godot_icall_Dictionary_Contains);
|
||||
|
|
|
@ -132,14 +132,31 @@ void gd_mono_debug_init() {
|
|||
CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8();
|
||||
|
||||
if (da_args.length()) {
|
||||
// Clear to avoid passing it to child processes
|
||||
OS::get_singleton()->set_environment("GODOT_MONO_DEBUGGER_AGENT", String());
|
||||
} else {
|
||||
// Try with command line arguments. This is useful on platforms where it's difficult to pass
|
||||
// environment variables. The command line arguments can be specified in the export options.
|
||||
|
||||
String da_cmdline_arg;
|
||||
List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
|
||||
|
||||
for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) {
|
||||
const String &arg = E->get();
|
||||
|
||||
if (arg.begins_with("--mono-debugger-agent=")) {
|
||||
da_cmdline_arg = arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (da_cmdline_arg.length()) {
|
||||
da_cmdline_arg.replace_first("--mono-debugger-agent=", "--debugger-agent=");
|
||||
da_args = da_cmdline_arg.utf8();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685);
|
||||
bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false);
|
||||
int da_timeout = GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000);
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint() ||
|
||||
ProjectSettings::get_singleton()->get_resource_path().empty() ||
|
||||
Main::is_project_manager()) {
|
||||
|
@ -148,6 +165,12 @@ void gd_mono_debug_init() {
|
|||
}
|
||||
|
||||
if (da_args.length() == 0) {
|
||||
// Use project settings defaults for the editor player
|
||||
|
||||
int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685);
|
||||
bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false);
|
||||
int da_timeout = GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000);
|
||||
|
||||
da_args = String("--debugger-agent=transport=dt_socket,address=127.0.0.1:" + itos(da_port) +
|
||||
",embedding=1,server=y,suspend=" + (da_suspend ? "y,timeout=" + itos(da_timeout) : "n"))
|
||||
.utf8();
|
||||
|
|
|
@ -246,6 +246,8 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end)
|
|||
|
||||
if (res < 0) {
|
||||
pcre2_match_data_free_16(match);
|
||||
pcre2_match_context_free_16(mctx);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,7 +152,6 @@ Error ImageLoaderSVG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
|
|||
|
||||
void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const {
|
||||
p_extensions->push_back("svg");
|
||||
p_extensions->push_back("svgz");
|
||||
}
|
||||
|
||||
ImageLoaderSVG::ImageLoaderSVG() {
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#include "core/io/image_loader.h"
|
||||
#include "core/io/json.h"
|
||||
#include "core/io/stream_peer_ssl.h"
|
||||
|
@ -658,9 +660,9 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op
|
|||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/offline_page", PROPERTY_HINT_FILE, "*.html"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "progressive_web_app/display", PROPERTY_HINT_ENUM, "Fullscreen,Standalone,Minimal Ui,Browser"), 1));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "progressive_web_app/orientation", PROPERTY_HINT_ENUM, "Any,Landscape,Portrait"), 0));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_144x144", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg,*.svgz"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_180x180", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg,*.svgz"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_512x512", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg,*.svgz"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_144x144", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_180x180", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_512x512", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg"), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::COLOR, "progressive_web_app/background_color", PROPERTY_HINT_COLOR_NO_ALPHA), Color()));
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#include "core/os/file_access.h"
|
||||
#include "core/os/os.h"
|
||||
#include "editor/editor_export.h"
|
||||
|
|
|
@ -3822,7 +3822,7 @@ Error OS_X11::move_to_trash(const String &p_path) {
|
|||
|
||||
// Create needed directories for decided trash can location.
|
||||
{
|
||||
DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
Error err = dir_access->make_dir_recursive(trash_path);
|
||||
|
||||
// Issue an error if trash can is not created proprely.
|
||||
|
@ -3831,7 +3831,6 @@ Error OS_X11::move_to_trash(const String &p_path) {
|
|||
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files");
|
||||
err = dir_access->make_dir_recursive(trash_path + "/info");
|
||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info");
|
||||
memdelete(dir_access);
|
||||
}
|
||||
|
||||
// The trash can is successfully created, now we check that we don't exceed our file name length limit.
|
||||
|
@ -3871,16 +3870,15 @@ Error OS_X11::move_to_trash(const String &p_path) {
|
|||
String trash_info = "[Trash Info]\nPath=" + p_path.http_escape() + "\nDeletionDate=" + timestamp + "\n";
|
||||
{
|
||||
Error err;
|
||||
FileAccess *file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
|
||||
FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo");
|
||||
file->store_string(trash_info);
|
||||
file->close();
|
||||
|
||||
// Rename our resource before moving it to the trash can.
|
||||
DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\"");
|
||||
memdelete(dir_access);
|
||||
}
|
||||
|
||||
// Move the given resource to the trash can.
|
||||
|
|
|
@ -1278,7 +1278,7 @@ void CPUParticles2D::_bind_methods() {
|
|||
|
||||
ADD_GROUP("Emission Shape", "emission_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "emission_rect_extents"), "set_emission_rect_extents", "get_emission_rect_extents");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
|
||||
|
@ -1314,7 +1314,7 @@ void CPUParticles2D::_bind_methods() {
|
|||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL);
|
||||
ADD_GROUP("Damping", "");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param", "get_param", PARAM_DAMPING);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING);
|
||||
ADD_GROUP("Angle", "");
|
||||
|
|
|
@ -389,7 +389,7 @@ void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound>
|
|||
|
||||
GeometryInstance *gi = Object::cast_to<GeometryInstance>(p_at_node);
|
||||
if (gi) {
|
||||
all_override = mi->get_material_override();
|
||||
all_override = gi->get_material_override();
|
||||
}
|
||||
|
||||
for (int i = 0; i < bmeshes.size(); i += 2) {
|
||||
|
@ -414,8 +414,8 @@ void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound>
|
|||
mf.mesh = mesh;
|
||||
|
||||
if (gi) {
|
||||
mf.cast_shadows = mi->get_cast_shadows_setting() != GeometryInstance::SHADOW_CASTING_SETTING_OFF;
|
||||
mf.generate_lightmap = mi->get_generate_lightmap();
|
||||
mf.cast_shadows = gi->get_cast_shadows_setting() != GeometryInstance::SHADOW_CASTING_SETTING_OFF;
|
||||
mf.generate_lightmap = gi->get_generate_lightmap();
|
||||
} else {
|
||||
mf.cast_shadows = true;
|
||||
mf.generate_lightmap = true;
|
||||
|
|
|
@ -1410,7 +1410,7 @@ void CPUParticles::_bind_methods() {
|
|||
|
||||
ADD_GROUP("Emission Shape", "emission_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points, Ring", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
|
||||
|
@ -1454,7 +1454,7 @@ void CPUParticles::_bind_methods() {
|
|||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL);
|
||||
ADD_GROUP("Damping", "");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param", "get_param", PARAM_DAMPING);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING);
|
||||
ADD_GROUP("Angle", "");
|
||||
|
|
|
@ -319,6 +319,8 @@ void AnimationNodeOneShot::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync);
|
||||
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_mode", PROPERTY_HINT_ENUM, "Blend,Add"), "set_mix_mode", "get_mix_mode");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadein_time", "get_fadein_time");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "fadeout_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadeout_time", "get_fadeout_time");
|
||||
|
||||
|
|
|
@ -684,8 +684,8 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const {
|
|||
|
||||
void LineEdit::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint() && !get_tree()->is_node_being_edited(this)) {
|
||||
cursor_set_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false));
|
||||
cursor_set_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65));
|
||||
|
@ -694,8 +694,15 @@ void LineEdit::_notification(int p_what) {
|
|||
EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
update_cached_width();
|
||||
update_placeholder_width();
|
||||
} break;
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
update_cached_width();
|
||||
update_placeholder_width();
|
||||
update();
|
||||
} break;
|
||||
case NOTIFICATION_RESIZED: {
|
||||
scroll_offset = 0;
|
||||
set_cursor_position(get_cursor_position());
|
||||
|
|
|
@ -387,7 +387,6 @@ void TextureProgress::draw_nine_patch_stretched(const Ref<Texture> &p_texture, F
|
|||
}
|
||||
|
||||
void TextureProgress::_notification(int p_what) {
|
||||
const float corners[12] = { -0.125, -0.375, -0.625, -0.875, 0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875 };
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
if (nine_patch_stretch && (mode == FILL_LEFT_TO_RIGHT || mode == FILL_RIGHT_TO_LEFT || mode == FILL_TOP_TO_BOTTOM || mode == FILL_BOTTOM_TO_TOP || mode == FILL_BILINEAR_LEFT_AND_RIGHT || mode == FILL_BILINEAR_TOP_AND_BOTTOM)) {
|
||||
|
@ -452,7 +451,7 @@ void TextureProgress::_notification(int p_what) {
|
|||
float val = get_as_ratio() * rad_max_degrees / 360;
|
||||
if (val == 1) {
|
||||
Rect2 region = Rect2(progress_offset, s);
|
||||
Rect2 source = Rect2(Point2(), s);
|
||||
Rect2 source = Rect2(Point2(), progress->get_size());
|
||||
draw_texture_rect_region(progress, region, source, tint_progress);
|
||||
} else if (val != 0) {
|
||||
Array pts;
|
||||
|
@ -466,16 +465,14 @@ void TextureProgress::_notification(int p_what) {
|
|||
}
|
||||
|
||||
float end = start + direction * val;
|
||||
pts.append(start);
|
||||
pts.append(end);
|
||||
float from = MIN(start, end);
|
||||
float to = MAX(start, end);
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (corners[i] > from && corners[i] < to) {
|
||||
pts.append(corners[i]);
|
||||
pts.append(from);
|
||||
for (float corner = Math::floor(from * 4 + 0.5) * 0.25 + 0.125; corner < to; corner += 0.25) {
|
||||
pts.append(corner);
|
||||
}
|
||||
}
|
||||
pts.sort();
|
||||
pts.append(to);
|
||||
|
||||
Vector<Point2> uvs;
|
||||
Vector<Point2> points;
|
||||
uvs.push_back(get_relative_center());
|
||||
|
@ -492,6 +489,8 @@ void TextureProgress::_notification(int p_what) {
|
|||
colors.push_back(tint_progress);
|
||||
draw_polygon(points, colors, uvs, progress);
|
||||
}
|
||||
|
||||
// Draw a reference cross.
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
Point2 p;
|
||||
|
||||
|
|
|
@ -1928,6 +1928,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
|
|||
#endif
|
||||
node = res->instance(ges);
|
||||
ERR_FAIL_COND_V(!node, nullptr);
|
||||
node->set_scene_instance_load_placeholder(get_scene_instance_load_placeholder());
|
||||
|
||||
instanced = true;
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "mesh_library.h"
|
||||
|
||||
#include "box_shape.h"
|
||||
|
||||
bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
|
||||
String name = p_name;
|
||||
if (name.begins_with("item/")) {
|
||||
|
@ -254,12 +256,35 @@ int MeshLibrary::get_last_unused_item_id() const {
|
|||
}
|
||||
|
||||
void MeshLibrary::_set_item_shapes(int p_item, const Array &p_shapes) {
|
||||
ERR_FAIL_COND(p_shapes.size() & 1);
|
||||
Array arr_shapes = p_shapes;
|
||||
int size = p_shapes.size();
|
||||
if (size & 1) {
|
||||
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
||||
int prev_size = item_map[p_item].shapes.size() * 2;
|
||||
|
||||
if (prev_size < size) {
|
||||
// Check if last element is a shape.
|
||||
Ref<Shape> shape = arr_shapes[size - 1];
|
||||
if (shape.is_null()) {
|
||||
Ref<BoxShape> box_shape;
|
||||
box_shape.instance();
|
||||
arr_shapes[size - 1] = box_shape;
|
||||
}
|
||||
|
||||
// Make sure the added element is a Transform.
|
||||
arr_shapes.push_back(Transform());
|
||||
size++;
|
||||
} else {
|
||||
size--;
|
||||
arr_shapes.resize(size);
|
||||
}
|
||||
}
|
||||
|
||||
Vector<ShapeData> shapes;
|
||||
for (int i = 0; i < p_shapes.size(); i += 2) {
|
||||
for (int i = 0; i < size; i += 2) {
|
||||
ShapeData sd;
|
||||
sd.shape = p_shapes[i + 0];
|
||||
sd.local_transform = p_shapes[i + 1];
|
||||
sd.shape = arr_shapes[i + 0];
|
||||
sd.local_transform = arr_shapes[i + 1];
|
||||
|
||||
if (sd.shape.is_valid()) {
|
||||
shapes.push_back(sd);
|
||||
|
|
|
@ -74,6 +74,95 @@ bool PortalGameplayMonitor::_source_rooms_changed(const int *p_source_room_ids,
|
|||
return source_rooms_changed;
|
||||
}
|
||||
|
||||
void PortalGameplayMonitor::unload(PortalRenderer &p_portal_renderer) {
|
||||
// First : send gameplay exit signals for any objects still in gameplay
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// lock output
|
||||
VisualServerCallbacks *callbacks = VSG::scene->get_callbacks();
|
||||
callbacks->lock();
|
||||
|
||||
// Remove any movings
|
||||
for (int n = 0; n < _active_moving_pool_ids_prev->size(); n++) {
|
||||
int pool_id = (*_active_moving_pool_ids_prev)[n];
|
||||
PortalRenderer::Moving &moving = p_portal_renderer.get_pool_moving(pool_id);
|
||||
moving.last_gameplay_tick_hit = 0;
|
||||
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = VSG::scene->_instance_get_object_ID(moving.instance);
|
||||
msg.type = _exit_callback_type;
|
||||
callbacks->push_message(msg);
|
||||
}
|
||||
|
||||
// Remove any roaming ghosts
|
||||
for (int n = 0; n < _active_rghost_pool_ids_prev->size(); n++) {
|
||||
int pool_id = (*_active_rghost_pool_ids_prev)[n];
|
||||
PortalRenderer::RGhost &moving = p_portal_renderer.get_pool_rghost(pool_id);
|
||||
moving.last_gameplay_tick_hit = 0;
|
||||
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = moving.object_id;
|
||||
msg.type = VisualServerCallbacks::CALLBACK_NOTIFICATION_EXIT_GAMEPLAY;
|
||||
callbacks->push_message(msg);
|
||||
}
|
||||
|
||||
// Rooms
|
||||
for (int n = 0; n < _active_room_ids_prev->size(); n++) {
|
||||
int room_id = (*_active_room_ids_prev)[n];
|
||||
VSRoom &room = p_portal_renderer.get_room(room_id);
|
||||
room.last_gameplay_tick_hit = 0;
|
||||
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = room._godot_instance_ID;
|
||||
msg.type = _exit_callback_type;
|
||||
callbacks->push_message(msg);
|
||||
}
|
||||
|
||||
// RoomGroups
|
||||
for (int n = 0; n < _active_roomgroup_ids_prev->size(); n++) {
|
||||
int roomgroup_id = (*_active_roomgroup_ids_prev)[n];
|
||||
VSRoomGroup &roomgroup = p_portal_renderer.get_roomgroup(roomgroup_id);
|
||||
roomgroup.last_gameplay_tick_hit = 0;
|
||||
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = roomgroup._godot_instance_ID;
|
||||
msg.type = _exit_callback_type;
|
||||
callbacks->push_message(msg);
|
||||
}
|
||||
|
||||
// Static Ghosts
|
||||
for (int n = 0; n < _active_sghost_ids_prev->size(); n++) {
|
||||
int id = (*_active_sghost_ids_prev)[n];
|
||||
VSStaticGhost &ghost = p_portal_renderer.get_static_ghost(id);
|
||||
ghost.last_gameplay_tick_hit = 0;
|
||||
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = ghost.object_id;
|
||||
msg.type = VisualServerCallbacks::CALLBACK_NOTIFICATION_EXIT_GAMEPLAY;
|
||||
callbacks->push_message(msg);
|
||||
}
|
||||
|
||||
// unlock
|
||||
callbacks->unlock();
|
||||
|
||||
// Clear all remaining data
|
||||
for (int n = 0; n < 2; n++) {
|
||||
_active_moving_pool_ids[n].clear();
|
||||
_active_rghost_pool_ids[n].clear();
|
||||
_active_room_ids[n].clear();
|
||||
_active_roomgroup_ids[n].clear();
|
||||
_active_sghost_ids[n].clear();
|
||||
}
|
||||
|
||||
_source_rooms_prev.clear();
|
||||
|
||||
// Lets not reset this just in case because it may be possible to have a moving outside the room system
|
||||
// which is preserved between levels, and has a stored gameplay tick. And with uint32_t this should take
|
||||
// a *long* time to rollover... (828 days?). And I don't think a rollover would actually cause a problem in practice.
|
||||
// But can revisit this in the case of e.g. servers running continuously.
|
||||
// We could alternatively go through all movings (not just active) etc and reset the last_gameplay_tick_hit to 0.
|
||||
// _gameplay_tick = 1;
|
||||
}
|
||||
|
||||
void PortalGameplayMonitor::set_params(bool p_use_secondary_pvs, bool p_use_signals) {
|
||||
_use_secondary_pvs = p_use_secondary_pvs;
|
||||
_use_signals = p_use_signals;
|
||||
|
|
|
@ -43,6 +43,8 @@ class PortalGameplayMonitor {
|
|||
public:
|
||||
PortalGameplayMonitor();
|
||||
|
||||
void unload(PortalRenderer &p_portal_renderer);
|
||||
|
||||
// entering and exiting gameplay notifications (requires PVS)
|
||||
void update_gameplay(PortalRenderer &p_portal_renderer, const int *p_source_room_ids, int p_num_source_rooms);
|
||||
void set_params(bool p_use_secondary_pvs, bool p_use_signals);
|
||||
|
|
|
@ -996,6 +996,7 @@ void PortalRenderer::sprawl_roaming(uint32_t p_mover_pool_id, MovingBase &r_movi
|
|||
void PortalRenderer::_ensure_unloaded(String p_reason) {
|
||||
if (_loaded) {
|
||||
_loaded = false;
|
||||
_gameplay_monitor.unload(*this);
|
||||
|
||||
String str;
|
||||
if (p_reason != String()) {
|
||||
|
@ -1014,6 +1015,17 @@ void PortalRenderer::_ensure_unloaded(String p_reason) {
|
|||
|
||||
void PortalRenderer::rooms_and_portals_clear() {
|
||||
_loaded = false;
|
||||
|
||||
// N.B. We want to make sure all the tick counters on movings rooms etc to zero,
|
||||
// so that on loading the next level gameplay entered signals etc will be
|
||||
// correctly sent and everything is fresh.
|
||||
// This is mostly done by the gameplay_monitor, but rooms_and_portals_clear()
|
||||
// will also clear tick counters where possible
|
||||
// (there is no TrackedList for the RoomGroup pool for example).
|
||||
// This could be made neater by moving everything to TrackedPooledLists, but this
|
||||
// may be overkill.
|
||||
_gameplay_monitor.unload(*this);
|
||||
|
||||
_statics.clear();
|
||||
_static_ghosts.clear();
|
||||
|
||||
|
|
|
@ -87,6 +87,9 @@ public:
|
|||
void destroy() {
|
||||
_rooms.clear();
|
||||
room_id = -1;
|
||||
|
||||
last_tick_hit = 0;
|
||||
last_gameplay_tick_hit = 0;
|
||||
}
|
||||
|
||||
// the expanded aabb allows objects to move on most frames
|
||||
|
|
|
@ -257,6 +257,7 @@ struct VSRoom {
|
|||
_secondary_pvs_size = 0;
|
||||
_priority = 0;
|
||||
_contains_internal_rooms = false;
|
||||
last_gameplay_tick_hit = 0;
|
||||
}
|
||||
|
||||
void cleanup_after_conversion() {
|
||||
|
|
|
@ -1141,7 +1141,7 @@ void VisualServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p
|
|||
ERR_FAIL_COND(!occluder);
|
||||
|
||||
if (occluder->polygon.is_valid()) {
|
||||
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
|
||||
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon);
|
||||
if (occluder_poly) {
|
||||
occluder_poly->owners.erase(occluder);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue