summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/config/project_settings.cpp1
-rw-r--r--core/extension/extension_api_dump.cpp210
-rw-r--r--doc/classes/CanvasItem.xml7
-rw-r--r--doc/classes/CanvasLayer.xml6
-rw-r--r--doc/classes/Control.xml3
-rw-r--r--doc/classes/LinkButton.xml18
-rw-r--r--doc/classes/MeshLibrary.xml12
-rw-r--r--doc/classes/NavigationAgent2D.xml18
-rw-r--r--doc/classes/NavigationAgent3D.xml18
-rw-r--r--doc/classes/NavigationLink2D.xml4
-rw-r--r--doc/classes/NavigationLink3D.xml4
-rw-r--r--doc/classes/NavigationMesh.xml10
-rw-r--r--doc/classes/NavigationMeshGenerator.xml10
-rw-r--r--doc/classes/NavigationObstacle2D.xml2
-rw-r--r--doc/classes/NavigationObstacle3D.xml2
-rw-r--r--doc/classes/NavigationPathQueryParameters2D.xml6
-rw-r--r--doc/classes/NavigationPathQueryParameters3D.xml6
-rw-r--r--doc/classes/NavigationPathQueryResult2D.xml2
-rw-r--r--doc/classes/NavigationPathQueryResult3D.xml2
-rw-r--r--doc/classes/NavigationPolygon.xml14
-rw-r--r--doc/classes/NavigationRegion2D.xml10
-rw-r--r--doc/classes/NavigationRegion3D.xml10
-rw-r--r--doc/classes/NavigationServer2D.xml8
-rw-r--r--doc/classes/NavigationServer3D.xml14
-rw-r--r--doc/classes/Node2D.xml6
-rw-r--r--doc/classes/Node3D.xml6
-rw-r--r--doc/classes/ProjectSettings.xml9
-rw-r--r--doc/classes/RenderingServer.xml1
-rw-r--r--doc/classes/TextServer.xml1
-rw-r--r--editor/editor_node.cpp15
-rw-r--r--editor/editor_node.h4
-rw-r--r--editor/editor_property_name_processor.cpp1
-rw-r--r--editor/fbx_importer_manager.cpp158
-rw-r--r--editor/fbx_importer_manager.h66
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp280
-rw-r--r--editor/plugins/audio_stream_editor_plugin.h93
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp16
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp17
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp1
-rw-r--r--editor/register_editor_types.cpp2
-rw-r--r--editor/scene_tree_dock.cpp38
-rw-r--r--modules/gdscript/gdscript.cpp26
-rw-r--r--modules/gdscript/gdscript.h2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp54
-rw-r--r--modules/gdscript/gdscript_codegen.h2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp5
-rw-r--r--modules/gdscript/language_server/godot_lsp.h2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment_external.notest.gd2
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.cpp27
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.h11
-rw-r--r--modules/gltf/gltf_document.cpp316
-rw-r--r--modules/gltf/register_types.cpp17
-rw-r--r--modules/gridmap/grid_map.cpp68
-rw-r--r--modules/gridmap/grid_map.h6
-rw-r--r--modules/mono/csharp_script.cpp2
-rw-r--r--modules/navigation/godot_navigation_server.cpp14
-rw-r--r--modules/navigation/godot_navigation_server.h4
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp102
-rw-r--r--modules/navigation/navigation_mesh_generator.h8
-rw-r--r--modules/text_server_adv/text_server_adv.cpp4
-rw-r--r--modules/text_server_fb/text_server_fb.cpp4
-rw-r--r--platform/ios/display_server_ios.mm32
-rw-r--r--platform/windows/export/export_plugin.cpp2
-rw-r--r--scene/2d/navigation_agent_2d.cpp24
-rw-r--r--scene/2d/navigation_agent_2d.h8
-rw-r--r--scene/2d/navigation_region_2d.cpp369
-rw-r--r--scene/2d/navigation_region_2d.h66
-rw-r--r--scene/2d/node_2d.cpp22
-rw-r--r--scene/2d/node_2d.h4
-rw-r--r--scene/2d/tile_map.cpp53
-rw-r--r--scene/3d/navigation_agent_3d.cpp24
-rw-r--r--scene/3d/navigation_agent_3d.h8
-rw-r--r--scene/3d/navigation_region_3d.cpp44
-rw-r--r--scene/3d/navigation_region_3d.h6
-rw-r--r--scene/3d/node_3d.cpp30
-rw-r--r--scene/3d/node_3d.h4
-rw-r--r--scene/gui/control.cpp11
-rw-r--r--scene/gui/control.h2
-rw-r--r--scene/gui/link_button.cpp19
-rw-r--r--scene/gui/link_button.h4
-rw-r--r--scene/main/canvas_item.cpp12
-rw-r--r--scene/main/canvas_item.h2
-rw-r--r--scene/main/canvas_layer.cpp13
-rw-r--r--scene/main/canvas_layer.h1
-rw-r--r--scene/main/scene_tree.cpp2
-rw-r--r--scene/main/viewport.cpp2
-rw-r--r--scene/register_scene_types.cpp2
-rw-r--r--scene/resources/mesh_library.cpp44
-rw-r--r--scene/resources/mesh_library.h14
-rw-r--r--scene/resources/navigation_mesh.cpp22
-rw-r--r--scene/resources/navigation_mesh.h12
-rw-r--r--scene/resources/navigation_polygon.cpp354
-rw-r--r--scene/resources/navigation_polygon.h94
-rw-r--r--scene/resources/texture.cpp25
-rw-r--r--scene/resources/tile_set.cpp56
-rw-r--r--scene/resources/tile_set.h2
-rw-r--r--servers/audio_server.cpp8
-rw-r--r--servers/navigation_server_2d.cpp8
-rw-r--r--servers/navigation_server_2d.h4
-rw-r--r--servers/navigation_server_3d.cpp6
-rw-r--r--servers/navigation_server_3d.h4
-rw-r--r--servers/physics_2d/godot_body_pair_2d.cpp8
-rw-r--r--servers/physics_3d/godot_body_pair_3d.cpp10
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp4
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/rendering_server_default.h2
-rw-r--r--servers/rendering/storage/environment_storage.cpp2
-rw-r--r--servers/rendering_server.cpp2
-rw-r--r--servers/rendering_server.h2
114 files changed, 2113 insertions, 1150 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index d0de39a79d..310df46085 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -1277,7 +1277,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("physics/2d/run_on_separate_thread", false);
GLOBAL_DEF("physics/3d/run_on_separate_thread", false);
- GLOBAL_DEF("debug/disable_touch", false);
GLOBAL_DEF("debug/settings/profiler/max_functions", 16384);
custom_prop_info["debug/settings/profiler/max_functions"] = PropertyInfo(Variant::INT, "debug/settings/profiler/max_functions", PROPERTY_HINT_RANGE, "128,65535,1");
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 5812a24c4f..a0e3778dcc 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -252,63 +252,140 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
}
{
- // Member offsets sizes.
+ // Member offsets, meta types and sizes.
+
+#define REAL_MEMBER_OFFSET(type, member) \
+ { \
+ type, \
+ member, \
+ "float", \
+ sizeof(float), \
+ "float", \
+ sizeof(float), \
+ "double", \
+ sizeof(double), \
+ "double", \
+ sizeof(double), \
+ }
+
+#define INT32_MEMBER_OFFSET(type, member) \
+ { \
+ type, \
+ member, \
+ "int32", \
+ sizeof(int32_t), \
+ "int32", \
+ sizeof(int32_t), \
+ "int32", \
+ sizeof(int32_t), \
+ "int32", \
+ sizeof(int32_t), \
+ }
+
+#define INT32_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
+ { \
+ type, \
+ member, \
+ member_type, \
+ sizeof(int32_t) * member_elems, \
+ member_type, \
+ sizeof(int32_t) * member_elems, \
+ member_type, \
+ sizeof(int32_t) * member_elems, \
+ member_type, \
+ sizeof(int32_t) * member_elems, \
+ }
+
+#define REAL_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
+ { \
+ type, \
+ member, \
+ member_type, \
+ sizeof(float) * member_elems, \
+ member_type, \
+ sizeof(float) * member_elems, \
+ member_type, \
+ sizeof(double) * member_elems, \
+ member_type, \
+ sizeof(double) * member_elems, \
+ }
+
struct {
Variant::Type type;
const char *member;
- uint32_t offset_32_bits_real_float;
- uint32_t offset_64_bits_real_float;
- uint32_t offset_32_bits_real_double;
- uint32_t offset_64_bits_real_double;
+ const char *member_meta_32_bits_real_float;
+ const uint32_t member_size_32_bits_real_float;
+ const char *member_meta_64_bits_real_float;
+ const uint32_t member_size_64_bits_real_float;
+ const char *member_meta_32_bits_real_double;
+ const uint32_t member_size_32_bits_real_double;
+ const char *member_meta_64_bits_real_double;
+ const uint32_t member_size_64_bits_real_double;
} member_offset_array[] = {
- { Variant::VECTOR2, "x", 0, 0, 0, 0 },
- { Variant::VECTOR2, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
- { Variant::VECTOR2I, "x", 0, 0, 0, 0 },
- { Variant::VECTOR2I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
- { Variant::RECT2, "position", 0, 0, 0, 0 },
- { Variant::RECT2, "size", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
- { Variant::RECT2I, "position", 0, 0, 0, 0 },
- { Variant::RECT2I, "size", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
- { Variant::VECTOR3, "x", 0, 0, 0, 0 },
- { Variant::VECTOR3, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
- { Variant::VECTOR3, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
- { Variant::VECTOR3I, "x", 0, 0, 0, 0 },
- { Variant::VECTOR3I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
- { Variant::VECTOR3I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
- { Variant::TRANSFORM2D, "x", 0, 0, 0, 0 },
- { Variant::TRANSFORM2D, "y", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
- { Variant::TRANSFORM2D, "origin", 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
- { Variant::VECTOR4, "x", 0, 0, 0, 0 },
- { Variant::VECTOR4, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
- { Variant::VECTOR4, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
- { Variant::VECTOR4, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) },
- { Variant::VECTOR4I, "x", 0, 0, 0, 0 },
- { Variant::VECTOR4I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) },
- { Variant::VECTOR4I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
- { Variant::VECTOR4I, "w", 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) },
- { Variant::PLANE, "normal", 0, 0, 0, 0 },
- { Variant::PLANE, "d", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
- { Variant::QUATERNION, "x", 0, 0, 0, 0 },
- { Variant::QUATERNION, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) },
- { Variant::QUATERNION, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
- { Variant::QUATERNION, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) },
- { Variant::AABB, "position", 0, 0, 0, 0 },
- { Variant::AABB, "size", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
- // Remember that basis vectors are flipped!
- { Variant::BASIS, "x", 0, 0, 0, 0 },
- { Variant::BASIS, "y", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
- { Variant::BASIS, "z", vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(double), vec3_elems * 2 * sizeof(double) },
- { Variant::TRANSFORM3D, "basis", 0, 0, 0, 0 },
- { Variant::TRANSFORM3D, "origin", (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) },
- { Variant::PROJECTION, "x", 0, 0, 0, 0 },
- { Variant::PROJECTION, "y", vec4_elems * sizeof(float), vec4_elems * sizeof(float), vec4_elems * sizeof(double), vec4_elems * sizeof(double) },
- { Variant::PROJECTION, "z", vec4_elems * 2 * sizeof(float), vec4_elems * 2 * sizeof(float), vec4_elems * 2 * sizeof(double), vec4_elems * 2 * sizeof(double) },
- { Variant::PROJECTION, "w", vec4_elems * 3 * sizeof(float), vec4_elems * 3 * sizeof(float), vec4_elems * 3 * sizeof(double), vec4_elems * 3 * sizeof(double) },
- { Variant::COLOR, "r", 0, 0, 0, 0 },
- { Variant::COLOR, "g", sizeof(float), sizeof(float), sizeof(float), sizeof(float) },
- { Variant::COLOR, "b", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float) },
- { Variant::COLOR, "a", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float) },
- { Variant::NIL, nullptr, 0, 0, 0, 0 },
+ // Vector2
+ REAL_MEMBER_OFFSET(Variant::VECTOR2, "x"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR2, "y"),
+ // Vector2i
+ INT32_MEMBER_OFFSET(Variant::VECTOR2I, "x"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR2I, "y"),
+ // Rect2
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2, "position", "Vector2", 2),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2, "size", "Vector2", 2),
+ // Rect2i
+ INT32_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2I, "position", "Vector2i", 2),
+ INT32_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2I, "size", "Vector2i", 2),
+ // Vector3
+ REAL_MEMBER_OFFSET(Variant::VECTOR3, "x"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR3, "y"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR3, "z"),
+ // Vector3i
+ INT32_MEMBER_OFFSET(Variant::VECTOR3I, "x"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR3I, "y"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR3I, "z"),
+ // Transform2D
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "x", "Vector2", 2),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "y", "Vector2", 2),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "origin", "Vector2", 2),
+ // Vector4
+ REAL_MEMBER_OFFSET(Variant::VECTOR4, "x"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR4, "y"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR4, "z"),
+ REAL_MEMBER_OFFSET(Variant::VECTOR4, "w"),
+ // Vector4i
+ INT32_MEMBER_OFFSET(Variant::VECTOR4I, "x"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR4I, "y"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR4I, "z"),
+ INT32_MEMBER_OFFSET(Variant::VECTOR4I, "w"),
+ // Plane
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PLANE, "normal", "Vector3", vec3_elems),
+ REAL_MEMBER_OFFSET(Variant::PLANE, "d"),
+ // Quaternion
+ REAL_MEMBER_OFFSET(Variant::QUATERNION, "x"),
+ REAL_MEMBER_OFFSET(Variant::QUATERNION, "y"),
+ REAL_MEMBER_OFFSET(Variant::QUATERNION, "z"),
+ REAL_MEMBER_OFFSET(Variant::QUATERNION, "w"),
+ // AABB
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::AABB, "position", "Vector3", vec3_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::AABB, "size", "Vector3", vec3_elems),
+ // Basis (remember that basis vectors are flipped!)
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "x", "Vector3", vec3_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "y", "Vector3", vec3_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "z", "Vector3", vec3_elems),
+ // Transform3D
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM3D, "basis", "Basis", vec3_elems * 3),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM3D, "origin", "Vector3", vec3_elems),
+ // Projection
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "x", "Vector4", vec4_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "y", "Vector4", vec4_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "z", "Vector4", vec4_elems),
+ REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "w", "Vector4", vec4_elems),
+ // Color (always composed of 4bytes floats)
+ { Variant::COLOR, "r", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) },
+ { Variant::COLOR, "g", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) },
+ { Variant::COLOR, "b", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) },
+ { Variant::COLOR, "a", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) },
+ // End marker, must stay last
+ { Variant::NIL, nullptr, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0 },
};
Array core_type_member_offsets;
@@ -319,15 +396,16 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
Array type_offsets;
uint32_t idx = 0;
- Variant::Type last_type = Variant::NIL;
+ Variant::Type previous_type = Variant::NIL;
Dictionary d2;
Array members;
+ uint32_t offset = 0;
while (true) {
Variant::Type t = member_offset_array[idx].type;
- if (t != last_type) {
- if (last_type != Variant::NIL) {
+ if (t != previous_type) {
+ if (previous_type != Variant::NIL) {
d2["members"] = members;
type_offsets.push_back(d2);
}
@@ -338,27 +416,35 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
d2 = Dictionary();
members = Array();
+ offset = 0;
d2["name"] = name;
- last_type = t;
+ previous_type = t;
}
Dictionary d3;
- uint32_t offset = 0;
+ const char *member_meta = nullptr;
+ uint32_t member_size = 0;
switch (i) {
case 0:
- offset = member_offset_array[idx].offset_32_bits_real_float;
+ member_meta = member_offset_array[idx].member_meta_32_bits_real_float;
+ member_size = member_offset_array[idx].member_size_32_bits_real_float;
break;
case 1:
- offset = member_offset_array[idx].offset_64_bits_real_float;
+ member_meta = member_offset_array[idx].member_meta_64_bits_real_float;
+ member_size = member_offset_array[idx].member_size_64_bits_real_float;
break;
case 2:
- offset = member_offset_array[idx].offset_32_bits_real_double;
+ member_meta = member_offset_array[idx].member_meta_32_bits_real_double;
+ member_size = member_offset_array[idx].member_size_32_bits_real_double;
break;
case 3:
- offset = member_offset_array[idx].offset_64_bits_real_double;
+ member_meta = member_offset_array[idx].member_meta_64_bits_real_double;
+ member_size = member_offset_array[idx].member_size_64_bits_real_double;
break;
}
d3["member"] = member_offset_array[idx].member;
d3["offset"] = offset;
+ d3["meta"] = member_meta;
+ offset += member_size;
members.push_back(d3);
idx++;
}
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 499d53e63c..5171e0acbe 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -153,6 +153,7 @@
<param index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<param index="4" name="outline" type="float" default="0.0" />
<param index="5" name="pixel_range" type="float" default="4.0" />
+ <param index="6" name="scale" type="float" default="1.0" />
<description>
Draws a textured rectangle region of the multi-channel signed distance field texture at a given position, optionally modulated by a color. See [member FontFile.multichannel_signed_distance_field] for more information and caveats about MSDF font rendering.
If [param outline] is positive, each alpha channel value of pixel in region is set to maximum value of true distance in the [param outline] radius.
@@ -404,7 +405,7 @@
<method name="get_canvas_transform" qualifiers="const">
<return type="Transform2D" />
<description>
- Returns the transform matrix of this item's canvas.
+ Returns the transform from the coordinate system of the canvas, this item is in, to the [Viewport]s coordinate system.
</description>
</method>
<method name="get_global_mouse_position" qualifiers="const">
@@ -422,7 +423,7 @@
<method name="get_global_transform_with_canvas" qualifiers="const">
<return type="Transform2D" />
<description>
- Returns the global transform matrix of this item in relation to the canvas.
+ Returns the transform from the local coordinate system of this [CanvasItem] to the [Viewport]s coordinate system.
</description>
</method>
<method name="get_local_mouse_position" qualifiers="const">
@@ -453,7 +454,7 @@
<method name="get_viewport_transform" qualifiers="const">
<return type="Transform2D" />
<description>
- Returns this item's transform in relation to the viewport.
+ Returns the transform from the coordinate system of the canvas, this item is in, to the [Viewport]s embedders coordinate system.
</description>
</method>
<method name="get_visibility_layer_bit" qualifiers="const">
diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml
index 7c1b19b961..ce999c06d3 100644
--- a/doc/classes/CanvasLayer.xml
+++ b/doc/classes/CanvasLayer.xml
@@ -19,6 +19,12 @@
Returns the RID of the canvas used by this layer.
</description>
</method>
+ <method name="get_final_transform" qualifiers="const">
+ <return type="Transform2D" />
+ <description>
+ Returns the transform from the [CanvasLayer]s coordinate system to the [Viewport]s coordinate system.
+ </description>
+ </method>
<method name="hide">
<return type="void" />
<description>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index fd6aab6a49..b0351559ee 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1050,6 +1050,9 @@
<member name="rotation" type="float" setter="set_rotation" getter="get_rotation" default="0.0">
The node's rotation around its pivot, in radians. See [member pivot_offset] to change the pivot's position.
</member>
+ <member name="rotation_degrees" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees">
+ Helper property to access [member rotation] in degrees instead of radians.
+ </member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The node's scale, relative to its [member size]. Change this property to scale the node around its [member pivot_offset]. The Control's [member tooltip_text] will also scale according to this value.
[b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually.
diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml
index d7701ea184..184ba1ba7a 100644
--- a/doc/classes/LinkButton.xml
+++ b/doc/classes/LinkButton.xml
@@ -28,7 +28,23 @@
Base text writing direction.
</member>
<member name="underline" type="int" setter="set_underline_mode" getter="get_underline_mode" enum="LinkButton.UnderlineMode" default="0">
- Determines when to show the underline. See [enum UnderlineMode] for options.
+ The underline mode to use for the text. See [enum LinkButton.UnderlineMode] for the available modes.
+ </member>
+ <member name="uri" type="String" setter="set_uri" getter="get_uri" default="&quot;&quot;">
+ The [url=https://en.wikipedia.org/wiki/Uniform_Resource_Identifier]URI[/url] for this [LinkButton]. If set to a valid URI, pressing the button opens the URI using the operating system's default program for the protocol (via [method OS.shell_open]). HTTP and HTTPS URLs open the default web browser.
+ [b]Examples:[/b]
+ [codeblocks]
+ [gdscript]
+ uri = "https://godotengine.org" # Opens the URL in the default web browser.
+ uri = "C:\SomeFolder" # Opens the file explorer at the given path.
+ uri = "C:\SomeImage.png" # Opens the given image in the default viewing app.
+ [/gdscript]
+ [csharp]
+ Uri = "https://godotengine.org"; // Opens the URL in the default web browser.
+ Uri = "C:\SomeFolder"; // Opens the file explorer at the given path.
+ Uri = "C:\SomeImage.png"; // Opens the given image in the default viewing app.
+ [/csharp]
+ [/codeblocks]
</member>
</members>
<constants>
diff --git a/doc/classes/MeshLibrary.xml b/doc/classes/MeshLibrary.xml
index 85e57dd0f3..ab217abb23 100644
--- a/doc/classes/MeshLibrary.xml
+++ b/doc/classes/MeshLibrary.xml
@@ -59,14 +59,14 @@
Returns the item's name.
</description>
</method>
- <method name="get_item_navmesh" qualifiers="const">
+ <method name="get_item_navigation_mesh" qualifiers="const">
<return type="NavigationMesh" />
<param index="0" name="id" type="int" />
<description>
Returns the item's navigation mesh.
</description>
</method>
- <method name="get_item_navmesh_transform" qualifiers="const">
+ <method name="get_item_navigation_mesh_transform" qualifiers="const">
<return type="Transform3D" />
<param index="0" name="id" type="int" />
<description>
@@ -126,18 +126,18 @@
This name is shown in the editor. It can also be used to look up the item later using [method find_item_by_name].
</description>
</method>
- <method name="set_item_navmesh">
+ <method name="set_item_navigation_mesh">
<return type="void" />
<param index="0" name="id" type="int" />
- <param index="1" name="navmesh" type="NavigationMesh" />
+ <param index="1" name="navigation_mesh" type="NavigationMesh" />
<description>
Sets the item's navigation mesh.
</description>
</method>
- <method name="set_item_navmesh_transform">
+ <method name="set_item_navigation_mesh_transform">
<return type="void" />
<param index="0" name="id" type="int" />
- <param index="1" name="navmesh" type="Transform3D" />
+ <param index="1" name="navigation_mesh" type="Transform3D" />
<description>
Sets the transform to apply to the item's navigation mesh.
</description>
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml
index 8cf7824ff7..770a5dc5b0 100644
--- a/doc/classes/NavigationAgent2D.xml
+++ b/doc/classes/NavigationAgent2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationAgent2D" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationAgent2D" inherits="Node" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
2D Agent used in navigation for collision avoidance.
</brief_description>
@@ -16,24 +16,24 @@
Returns the distance to the target location, using the agent's global position. The user must set [member target_location] in order for this to be accurate.
</description>
</method>
- <method name="get_final_location">
- <return type="Vector2" />
- <description>
- Returns the reachable final location in global coordinates. This can change if the navigation path is altered in any way. Because of this, it would be best to check this each frame.
- </description>
- </method>
- <method name="get_nav_path" qualifiers="const">
+ <method name="get_current_navigation_path" qualifiers="const">
<return type="PackedVector2Array" />
<description>
Returns this agent's current path from start to finish in global coordinates. The path only updates when the target location is changed or the agent requires a repath. The path array is not intended to be used in direct path movement as the agent has its own internal path logic that would get corrupted by changing the path array manually. Use the intended [method get_next_location] once every physics frame to receive the next path point for the agents movement as this function also updates the internal path logic.
</description>
</method>
- <method name="get_nav_path_index" qualifiers="const">
+ <method name="get_current_navigation_path_index" qualifiers="const">
<return type="int" />
<description>
Returns which index the agent is currently on in the navigation path's [PackedVector2Array].
</description>
</method>
+ <method name="get_final_location">
+ <return type="Vector2" />
+ <description>
+ Returns the reachable final location in global coordinates. This can change if the navigation path is altered in any way. Because of this, it would be best to check this each frame.
+ </description>
+ </method>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml
index 44c17647f7..d9a1235bdd 100644
--- a/doc/classes/NavigationAgent3D.xml
+++ b/doc/classes/NavigationAgent3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationAgent3D" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationAgent3D" inherits="Node" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
3D Agent used in navigation for collision avoidance.
</brief_description>
@@ -16,24 +16,24 @@
Returns the distance to the target location, using the agent's global position. The user must set [member target_location] in order for this to be accurate.
</description>
</method>
- <method name="get_final_location">
- <return type="Vector3" />
- <description>
- Returns the reachable final location in global coordinates. This can change if the navigation path is altered in any way. Because of this, it would be best to check this each frame.
- </description>
- </method>
- <method name="get_nav_path" qualifiers="const">
+ <method name="get_current_navigation_path" qualifiers="const">
<return type="PackedVector3Array" />
<description>
Returns this agent's current path from start to finish in global coordinates. The path only updates when the target location is changed or the agent requires a repath. The path array is not intended to be used in direct path movement as the agent has its own internal path logic that would get corrupted by changing the path array manually. Use the intended [method get_next_location] once every physics frame to receive the next path point for the agents movement as this function also updates the internal path logic.
</description>
</method>
- <method name="get_nav_path_index" qualifiers="const">
+ <method name="get_current_navigation_path_index" qualifiers="const">
<return type="int" />
<description>
Returns which index the agent is currently on in the navigation path's [PackedVector3Array].
</description>
</method>
+ <method name="get_final_location">
+ <return type="Vector3" />
+ <description>
+ Returns the reachable final location in global coordinates. This can change if the navigation path is altered in any way. Because of this, it would be best to check this each frame.
+ </description>
+ </method>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
diff --git a/doc/classes/NavigationLink2D.xml b/doc/classes/NavigationLink2D.xml
index 1e086fb730..9d75694360 100644
--- a/doc/classes/NavigationLink2D.xml
+++ b/doc/classes/NavigationLink2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationLink2D" inherits="Node2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationLink2D" inherits="Node2D" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Creates a link between two locations that [NavigationServer2D] can route agents through.
</brief_description>
@@ -38,7 +38,7 @@
The distance the link will search is controlled by [method NavigationServer2D.map_set_link_connection_radius].
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
- When pathfinding enters this link from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
+ When pathfinding enters this link from another regions navigation mesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the link belongs to. These navigation layers will be checked when requesting a path with [method NavigationServer2D.map_get_path].
diff --git a/doc/classes/NavigationLink3D.xml b/doc/classes/NavigationLink3D.xml
index 4d5d81bec5..730c43c5a8 100644
--- a/doc/classes/NavigationLink3D.xml
+++ b/doc/classes/NavigationLink3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationLink3D" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationLink3D" inherits="Node3D" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Creates a link between two locations that [NavigationServer3D] can route agents through.
</brief_description>
@@ -38,7 +38,7 @@
The distance the link will search is controlled by [method NavigationServer3D.map_set_link_connection_radius].
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
- When pathfinding enters this link from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
+ When pathfinding enters this link from another regions navigation mesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the link belongs to. These navigation layers will be checked when requesting a path with [method NavigationServer3D.map_get_path].
diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml
index c86bc47e04..19b3e7d90e 100644
--- a/doc/classes/NavigationMesh.xml
+++ b/doc/classes/NavigationMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationMesh" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationMesh" inherits="Resource" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A mesh to approximate the walkable areas and obstacles.
</brief_description>
@@ -133,11 +133,11 @@
<member name="geometry_source_geometry_mode" type="int" setter="set_source_geometry_mode" getter="get_source_geometry_mode" enum="NavigationMesh.SourceGeometryMode" default="0">
The source of the geometry used when baking. See [enum SourceGeometryMode] for possible values.
</member>
- <member name="geometry_source_group_name" type="StringName" setter="set_source_group_name" getter="get_source_group_name" default="&amp;&quot;navmesh&quot;">
+ <member name="geometry_source_group_name" type="StringName" setter="set_source_group_name" getter="get_source_group_name" default="&amp;&quot;navigation_mesh_source_group&quot;">
The name of the group to scan for geometry.
Only used when [member geometry_source_geometry_mode] is [constant SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN] or [constant SOURCE_GEOMETRY_GROUPS_EXPLICIT].
</member>
- <member name="polygon_verts_per_poly" type="float" setter="set_verts_per_poly" getter="get_verts_per_poly" default="6.0">
+ <member name="polygon_vertices_per_polyon" type="float" setter="set_vertices_per_polyon" getter="get_vertices_per_polyon" default="6.0">
The maximum number of vertices allowed for polygons generated during the contour to polygon conversion process.
</member>
<member name="region_merge_size" type="float" setter="set_region_merge_size" getter="get_region_merge_size" default="20.0">
@@ -177,8 +177,8 @@
<constant name="PARSED_GEOMETRY_MAX" value="3" enum="ParsedGeometryType">
Represents the size of the [enum ParsedGeometryType] enum.
</constant>
- <constant name="SOURCE_GEOMETRY_NAVMESH_CHILDREN" value="0" enum="SourceGeometryMode">
- Scans the child nodes of [NavigationRegion3D] recursively for geometry.
+ <constant name="SOURCE_GEOMETRY_ROOT_NODE_CHILDREN" value="0" enum="SourceGeometryMode">
+ Scans the child nodes of the root node recursively for geometry.
</constant>
<constant name="SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN" value="1" enum="SourceGeometryMode">
Scans nodes in a group and their child nodes recursively for geometry. The group is specified by [member geometry_source_group_name].
diff --git a/doc/classes/NavigationMeshGenerator.xml b/doc/classes/NavigationMeshGenerator.xml
index 4c337db90f..15d149a229 100644
--- a/doc/classes/NavigationMeshGenerator.xml
+++ b/doc/classes/NavigationMeshGenerator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationMeshGenerator" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationMeshGenerator" inherits="Object" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Helper class for creating and clearing navigation meshes.
</brief_description>
@@ -15,17 +15,17 @@
<methods>
<method name="bake">
<return type="void" />
- <param index="0" name="nav_mesh" type="NavigationMesh" />
+ <param index="0" name="navigation_mesh" type="NavigationMesh" />
<param index="1" name="root_node" type="Node" />
<description>
- Bakes navigation data to the provided [param nav_mesh] by parsing child nodes under the provided [param root_node] or a specific group of nodes for potential source geometry. The parse behavior can be controlled with the [member NavigationMesh.geometry_parsed_geometry_type] and [member NavigationMesh.geometry_source_geometry_mode] properties on the [NavigationMesh] resource.
+ Bakes navigation data to the provided [param navigation_mesh] by parsing child nodes under the provided [param root_node] or a specific group of nodes for potential source geometry. The parse behavior can be controlled with the [member NavigationMesh.geometry_parsed_geometry_type] and [member NavigationMesh.geometry_source_geometry_mode] properties on the [NavigationMesh] resource.
</description>
</method>
<method name="clear">
<return type="void" />
- <param index="0" name="nav_mesh" type="NavigationMesh" />
+ <param index="0" name="navigation_mesh" type="NavigationMesh" />
<description>
- Removes all polygons and vertices from the provided [param nav_mesh] resource.
+ Removes all polygons and vertices from the provided [param navigation_mesh] resource.
</description>
</method>
</methods>
diff --git a/doc/classes/NavigationObstacle2D.xml b/doc/classes/NavigationObstacle2D.xml
index 68d9691ccf..ce0f05ad28 100644
--- a/doc/classes/NavigationObstacle2D.xml
+++ b/doc/classes/NavigationObstacle2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationObstacle2D" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationObstacle2D" inherits="Node" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
2D Obstacle used in navigation for collision avoidance.
</brief_description>
diff --git a/doc/classes/NavigationObstacle3D.xml b/doc/classes/NavigationObstacle3D.xml
index 90eb55887f..78bbb788d9 100644
--- a/doc/classes/NavigationObstacle3D.xml
+++ b/doc/classes/NavigationObstacle3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationObstacle3D" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationObstacle3D" inherits="Node" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
3D Obstacle used in navigation for collision avoidance.
</brief_description>
diff --git a/doc/classes/NavigationPathQueryParameters2D.xml b/doc/classes/NavigationPathQueryParameters2D.xml
index 397ca8b713..dff58fc1bd 100644
--- a/doc/classes/NavigationPathQueryParameters2D.xml
+++ b/doc/classes/NavigationPathQueryParameters2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPathQueryParameters2D" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPathQueryParameters2D" inherits="RefCounted" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Parameters to be sent to a 2D navigation path query.
</brief_description>
@@ -33,10 +33,10 @@
The path query uses the default A* pathfinding algorithm.
</constant>
<constant name="PATH_POSTPROCESSING_CORRIDORFUNNEL" value="0" enum="PathPostProcessing">
- Applies a funnel algorithm to the raw path corridor found by the pathfinding algorithm. This will result in the shortest path possible inside the path corridor. This postprocessing very much depends on the navmesh polygon layout and the created corridor. Especially tile- or gridbased layouts can face artificial corners with diagonal movement due to a jagged path corridor imposed by the cell shapes.
+ Applies a funnel algorithm to the raw path corridor found by the pathfinding algorithm. This will result in the shortest path possible inside the path corridor. This postprocessing very much depends on the navigation mesh polygon layout and the created corridor. Especially tile- or gridbased layouts can face artificial corners with diagonal movement due to a jagged path corridor imposed by the cell shapes.
</constant>
<constant name="PATH_POSTPROCESSING_EDGECENTERED" value="1" enum="PathPostProcessing">
- Centers every path position in the middle of the traveled navmesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center.
+ Centers every path position in the middle of the traveled navigation mesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center.
</constant>
</constants>
</class>
diff --git a/doc/classes/NavigationPathQueryParameters3D.xml b/doc/classes/NavigationPathQueryParameters3D.xml
index 29faa5561b..46a35b1071 100644
--- a/doc/classes/NavigationPathQueryParameters3D.xml
+++ b/doc/classes/NavigationPathQueryParameters3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPathQueryParameters3D" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPathQueryParameters3D" inherits="RefCounted" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Parameters to be sent to a 3D navigation path query.
</brief_description>
@@ -33,10 +33,10 @@
The path query uses the default A* pathfinding algorithm.
</constant>
<constant name="PATH_POSTPROCESSING_CORRIDORFUNNEL" value="0" enum="PathPostProcessing">
- Applies a funnel algorithm to the raw path corridor found by the pathfinding algorithm. This will result in the shortest path possible inside the path corridor. This postprocessing very much depends on the navmesh polygon layout and the created corridor. Especially tile- or gridbased layouts can face artificial corners with diagonal movement due to a jagged path corridor imposed by the cell shapes.
+ Applies a funnel algorithm to the raw path corridor found by the pathfinding algorithm. This will result in the shortest path possible inside the path corridor. This postprocessing very much depends on the navigation mesh polygon layout and the created corridor. Especially tile- or gridbased layouts can face artificial corners with diagonal movement due to a jagged path corridor imposed by the cell shapes.
</constant>
<constant name="PATH_POSTPROCESSING_EDGECENTERED" value="1" enum="PathPostProcessing">
- Centers every path position in the middle of the traveled navmesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center.
+ Centers every path position in the middle of the traveled navigation mesh polygon edge. This creates better paths for tile- or gridbased layouts that restrict the movement to the cells center.
</constant>
</constants>
</class>
diff --git a/doc/classes/NavigationPathQueryResult2D.xml b/doc/classes/NavigationPathQueryResult2D.xml
index 95b90e9383..77b19b07b6 100644
--- a/doc/classes/NavigationPathQueryResult2D.xml
+++ b/doc/classes/NavigationPathQueryResult2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPathQueryResult2D" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPathQueryResult2D" inherits="RefCounted" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Result from a [NavigationPathQueryParameters2D] navigation path query.
</brief_description>
diff --git a/doc/classes/NavigationPathQueryResult3D.xml b/doc/classes/NavigationPathQueryResult3D.xml
index b4ca8288db..6c553bf36b 100644
--- a/doc/classes/NavigationPathQueryResult3D.xml
+++ b/doc/classes/NavigationPathQueryResult3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPathQueryResult3D" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPathQueryResult3D" inherits="RefCounted" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Result from a [NavigationPathQueryParameters3D] navigation path query.
</brief_description>
diff --git a/doc/classes/NavigationPolygon.xml b/doc/classes/NavigationPolygon.xml
index 19466c171f..b30dd2703a 100644
--- a/doc/classes/NavigationPolygon.xml
+++ b/doc/classes/NavigationPolygon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationPolygon" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationPolygon" inherits="Resource" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A node that has methods to draw outlines or use indices of vertices to create navigation polygons.
</brief_description>
@@ -12,14 +12,14 @@
var outline = PackedVector2Array([Vector2(0, 0), Vector2(0, 50), Vector2(50, 50), Vector2(50, 0)])
polygon.add_outline(outline)
polygon.make_polygons_from_outlines()
- $NavigationRegion2D.navpoly = polygon
+ $NavigationRegion2D.navigation_polygon = polygon
[/gdscript]
[csharp]
var polygon = new NavigationPolygon();
var outline = new Vector2[] { new Vector2(0, 0), new Vector2(0, 50), new Vector2(50, 50), new Vector2(50, 0) };
polygon.AddOutline(outline);
polygon.MakePolygonsFromOutlines();
- GetNode&lt;NavigationRegion2D&gt;("NavigationRegion2D").Navpoly = polygon;
+ GetNode&lt;NavigationRegion2D&gt;("NavigationRegion2D").NavigationPolygon = polygon;
[/csharp]
[/codeblocks]
Using [method add_polygon] and indices of the vertices array.
@@ -30,7 +30,7 @@
polygon.vertices = vertices
var indices = PackedInt32Array([0, 1, 2, 3])
polygon.add_polygon(indices)
- $NavigationRegion2D.navpoly = polygon
+ $NavigationRegion2D.navigation_polygon = polygon
[/gdscript]
[csharp]
var polygon = new NavigationPolygon();
@@ -38,7 +38,7 @@
polygon.Vertices = vertices;
var indices = new int[] { 0, 1, 2, 3 };
polygon.AddPolygon(indices);
- GetNode&lt;NavigationRegion2D&gt;("NavigationRegion2D").Navpoly = polygon;
+ GetNode&lt;NavigationRegion2D&gt;("NavigationRegion2D").NavigationPolygon = polygon;
[/csharp]
[/codeblocks]
</description>
@@ -80,10 +80,10 @@
Clears the array of polygons, but it doesn't clear the array of outlines and vertices.
</description>
</method>
- <method name="get_mesh">
+ <method name="get_navigation_mesh">
<return type="NavigationMesh" />
<description>
- Returns the [NavigationMesh] resulting from this navigation polygon. This navmesh can be used to update the navmesh of a region with the [method NavigationServer3D.region_set_navmesh] API directly (as 2D uses the 3D server behind the scene).
+ Returns the [NavigationMesh] resulting from this navigation polygon. This navigation mesh can be used to update the navigation mesh of a region with the [method NavigationServer3D.region_set_navigation_mesh] API directly (as 2D uses the 3D server behind the scene).
</description>
</method>
<method name="get_outline" qualifiers="const">
diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml
index 0f28081201..8b8793b3b4 100644
--- a/doc/classes/NavigationRegion2D.xml
+++ b/doc/classes/NavigationRegion2D.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationRegion2D" inherits="Node2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationRegion2D" inherits="Node2D" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A region of the 2D navigation map.
</brief_description>
<description>
A region of the navigation map. It tells the [NavigationServer2D] what can be navigated and what cannot, based on its [NavigationPolygon] resource.
Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer2D.map_set_edge_connection_margin].
- [b]Note:[/b] Overlapping two regions' polygons is not enough for connecting two regions. They must share a similar edge.
+ [b]Note:[/b] Overlapping two regions' navigation polygons is not enough for connecting two regions. They must share a similar edge.
The pathfinding cost of entering this region from another region can be controlled with the [member enter_cost] value.
[b]Note:[/b] This value is not added to the path cost when the start position is already inside this region.
The pathfinding cost of traveling distances inside this region can be controlled with the [member travel_cost] multiplier.
@@ -42,16 +42,16 @@
Determines if the [NavigationRegion2D] is enabled or disabled.
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
- When pathfinding enters this region's navmesh from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
+ When pathfinding enters this region's navigation mesh from another regions navigation mesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the region belongs to. These navigation layers can be checked upon when requesting a path with [method NavigationServer2D.map_get_path].
</member>
- <member name="navpoly" type="NavigationPolygon" setter="set_navigation_polygon" getter="get_navigation_polygon">
+ <member name="navigation_polygon" type="NavigationPolygon" setter="set_navigation_polygon" getter="get_navigation_polygon">
The [NavigationPolygon] resource to use.
</member>
<member name="travel_cost" type="float" setter="set_travel_cost" getter="get_travel_cost" default="1.0">
- When pathfinding moves inside this region's navmesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
+ When pathfinding moves inside this region's navigation mesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
</member>
</members>
</class>
diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml
index 85f163b3c2..10662db869 100644
--- a/doc/classes/NavigationRegion3D.xml
+++ b/doc/classes/NavigationRegion3D.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationRegion3D" inherits="Node3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationRegion3D" inherits="Node3D" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A region of the navigation map.
</brief_description>
<description>
A region of the navigation map. It tells the [NavigationServer3D] what can be navigated and what cannot, based on its [NavigationMesh] resource.
Two regions can be connected to each other if they share a similar edge. You can set the minimum distance between two vertices required to connect two edges by using [method NavigationServer3D.map_set_edge_connection_margin].
- [b]Note:[/b] Overlapping two regions' navmeshes is not enough for connecting two regions. They must share a similar edge.
+ [b]Note:[/b] Overlapping two regions' navigation meshes is not enough for connecting two regions. They must share a similar edge.
The cost of entering this region from another region can be controlled with the [member enter_cost] value.
[b]Note:[/b] This value is not added to the path cost when the start position is already inside this region.
The cost of traveling distances inside this region can be controlled with the [member travel_cost] multiplier.
@@ -49,16 +49,16 @@
Determines if the [NavigationRegion3D] is enabled or disabled.
</member>
<member name="enter_cost" type="float" setter="set_enter_cost" getter="get_enter_cost" default="0.0">
- When pathfinding enters this region's navmesh from another regions navmesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
+ When pathfinding enters this region's navigation mesh from another regions navigation mesh the [code]enter_cost[/code] value is added to the path distance for determining the shortest path.
</member>
<member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
A bitfield determining all navigation layers the region belongs to. These navigation layers can be checked upon when requesting a path with [method NavigationServer3D.map_get_path].
</member>
- <member name="navmesh" type="NavigationMesh" setter="set_navigation_mesh" getter="get_navigation_mesh">
+ <member name="navigation_mesh" type="NavigationMesh" setter="set_navigation_mesh" getter="get_navigation_mesh">
The [NavigationMesh] resource to use.
</member>
<member name="travel_cost" type="float" setter="set_travel_cost" getter="get_travel_cost" default="1.0">
- When pathfinding moves inside this region's navmesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
+ When pathfinding moves inside this region's navigation mesh the traveled distances are multiplied with [code]travel_cost[/code] for determining the shortest path.
</member>
</members>
<signals>
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 230e58a12a..32e48cde54 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationServer2D" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationServer2D" inherits="Object" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Server interface for low-level 2D navigation access
</brief_description>
@@ -489,12 +489,12 @@
Set the region's navigation layers. This allows selecting regions from a path request (when using [method NavigationServer2D.map_get_path]).
</description>
</method>
- <method name="region_set_navpoly" qualifiers="const">
+ <method name="region_set_navigation_polygon" qualifiers="const">
<return type="void" />
<param index="0" name="region" type="RID" />
- <param index="1" name="nav_poly" type="NavigationPolygon" />
+ <param index="1" name="navigation_polygon" type="NavigationPolygon" />
<description>
- Sets the navigation mesh for the region.
+ Sets the [param navigation_polygon] for the region.
</description>
</method>
<method name="region_set_owner_id" qualifiers="const">
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index c7da3b7b5b..c156dfac16 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NavigationServer3D" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="NavigationServer3D" inherits="Object" is_experimental="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Server interface for low-level 3D navigation access
</brief_description>
@@ -433,12 +433,12 @@
Queries a path in a given navigation map. Start and target position and other parameters are defined through [NavigationPathQueryParameters3D]. Updates the provided [NavigationPathQueryResult3D] result object with the path among other results requested by the query.
</description>
</method>
- <method name="region_bake_navmesh" qualifiers="const">
+ <method name="region_bake_navigation_mesh" qualifiers="const">
<return type="void" />
- <param index="0" name="mesh" type="NavigationMesh" />
- <param index="1" name="node" type="Node" />
+ <param index="0" name="navigation_mesh" type="NavigationMesh" />
+ <param index="1" name="root_node" type="Node" />
<description>
- Bakes the navigation mesh.
+ Bakes the [param navigation_mesh] with bake source geometry collected starting from the [param root_node].
</description>
</method>
<method name="region_create" qualifiers="const">
@@ -539,10 +539,10 @@
Set the region's navigation layers. This allows selecting regions from a path request (when using [method NavigationServer3D.map_get_path]).
</description>
</method>
- <method name="region_set_navmesh" qualifiers="const">
+ <method name="region_set_navigation_mesh" qualifiers="const">
<return type="void" />
<param index="0" name="region" type="RID" />
- <param index="1" name="nav_mesh" type="NavigationMesh" />
+ <param index="1" name="navigation_mesh" type="NavigationMesh" />
<description>
Sets the navigation mesh for the region.
</description>
diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml
index 26efe37dce..9d224f09b1 100644
--- a/doc/classes/Node2D.xml
+++ b/doc/classes/Node2D.xml
@@ -99,6 +99,9 @@
<member name="global_rotation" type="float" setter="set_global_rotation" getter="get_global_rotation">
Global rotation in radians.
</member>
+ <member name="global_rotation_degrees" type="float" setter="set_global_rotation_degrees" getter="get_global_rotation_degrees">
+ Helper property to access [member global_rotation] in degrees instead of radians.
+ </member>
<member name="global_scale" type="Vector2" setter="set_global_scale" getter="get_global_scale">
Global scale.
</member>
@@ -114,6 +117,9 @@
<member name="rotation" type="float" setter="set_rotation" getter="get_rotation" default="0.0">
Rotation in radians, relative to the node's parent.
</member>
+ <member name="rotation_degrees" type="float" setter="set_rotation_degrees" getter="get_rotation_degrees">
+ Helper property to access [member rotation] in degrees instead of radians.
+ </member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The node's scale. Unscaled value: [code](1, 1)[/code].
[b]Note:[/b] Negative X scales in 2D are not decomposable from the transformation matrix. Due to the way scale is represented with transformation matrices in Godot, negative scales on the X axis will be changed to negative scales on the Y axis and a rotation of 180 degrees when decomposed.
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index b6024b1887..1aa71113e9 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -274,6 +274,9 @@
Rotation part of the global transformation in radians, specified in terms of YXZ-Euler angles in the format (X angle, Y angle, Z angle).
[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a vector. The three Euler angles, which are the three independent parameters of the Euler-angle parametrization of the rotation matrix, are stored in a [Vector3] data structure not because the rotation is a vector, but only because [Vector3] exists as a convenient data-structure to store 3 floating-point numbers. Therefore, applying affine operations on the rotation "vector" is not meaningful.
</member>
+ <member name="global_rotation_degrees" type="Vector3" setter="set_global_rotation_degrees" getter="get_global_rotation_degrees">
+ Helper property to access [member global_rotation] in degrees instead of radians.
+ </member>
<member name="global_transform" type="Transform3D" setter="set_global_transform" getter="get_global_transform">
World3D space (global) [Transform3D] of this node.
</member>
@@ -287,6 +290,9 @@
Rotation part of the local transformation in radians, specified in terms of Euler angles. The angles construct a rotaton in the order specified by the [member rotation_order] property.
[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a vector. The three Euler angles, which are the three independent parameters of the Euler-angle parametrization of the rotation matrix, are stored in a [Vector3] data structure not because the rotation is a vector, but only because [Vector3] exists as a convenient data-structure to store 3 floating-point numbers. Therefore, applying affine operations on the rotation "vector" is not meaningful.
</member>
+ <member name="rotation_degrees" type="Vector3" setter="set_rotation_degrees" getter="get_rotation_degrees">
+ Helper property to access [member rotation] in degrees instead of radians.
+ </member>
<member name="rotation_edit_mode" type="int" setter="set_rotation_edit_mode" getter="get_rotation_edit_mode" enum="Node3D.RotationEditMode" default="0">
Specify how rotation (and scale) will be presented in the editor.
</member>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 72f9a0e32f..b80d6b2216 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -344,9 +344,6 @@
<member name="compression/formats/zstd/window_log_size" type="int" setter="" getter="" default="27">
Largest size limit (in power of 2) allowed when compressing using long-distance matching with Zstandard. Higher values can result in better compression, but will require more memory when compressing and decompressing.
</member>
- <member name="debug/disable_touch" type="bool" setter="" getter="" default="false">
- Disable touch input. Only has effect on iOS.
- </member>
<member name="debug/file_logging/enable_file_logging" type="bool" setter="" getter="" default="false">
If [code]true[/code], logs all output to files.
</member>
@@ -585,7 +582,7 @@
[b]Note:[/b] This setting has no effect on the home indicator if [code]hide_home_indicator[/code] is [code]true[/code].
</member>
<member name="display/window/per_pixel_transparency/allowed" type="bool" setter="" getter="" default="false">
- If [code]true[/code], allows per-pixel transparency for the window background. This affects performance, so leave it on [code]false[/code] unless you need it. See also [member display/window/size/transparent] and [member rendering/transparent_background].
+ If [code]true[/code], allows per-pixel transparency for the window background. This affects performance, so leave it on [code]false[/code] unless you need it. See also [member display/window/size/transparent] and [member rendering/viewport/transparent_background].
</member>
<member name="display/window/size/always_on_top" type="bool" setter="" getter="" default="false">
Forces the main window to be always on top.
@@ -610,7 +607,7 @@
[b]Note:[/b] This setting is ignored on iOS.
</member>
<member name="display/window/size/transparent" type="bool" setter="" getter="" default="false">
- If [code]true[/code], enables a window manager hint that the main window background [i]can[/i] be transparent. This does not make the background actually transparent. For the background to be transparent, the root viewport must also be made transparent by enabling [member rendering/transparent_background].
+ If [code]true[/code], enables a window manager hint that the main window background [i]can[/i] be transparent. This does not make the background actually transparent. For the background to be transparent, the root viewport must also be made transparent by enabling [member rendering/viewport/transparent_background].
[b]Note:[/b] To use a transparent splash screen, set [member application/boot_splash/bg_color] to [code]Color(0, 0, 0, 0)[/code].
[b]Note:[/b] This setting has no effect if [member display/window/per_pixel_transparency/allowed] is set to [code]false[/code].
</member>
@@ -2256,7 +2253,7 @@
<member name="rendering/textures/webp_compression/lossless_compression_factor" type="float" setter="" getter="" default="25">
The default compression factor for lossless WebP. Decompression speed is mostly unaffected by the compression factor. Supported values are 0 to 100.
</member>
- <member name="rendering/transparent_background" type="bool" setter="" getter="" default="false">
+ <member name="rendering/viewport/transparent_background" type="bool" setter="" getter="" default="false">
If [code]true[/code], enables [member Viewport.transparent_bg] on the root viewport. This allows per-pixel transparency to be effective after also enabling [member display/window/size/transparent] and [member display/window/per_pixel_transparency/allowed].
</member>
<member name="rendering/vrs/mode" type="int" setter="" getter="" default="0">
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index d9b83f2acd..1cc52e6837 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -241,6 +241,7 @@
<param index="4" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<param index="5" name="outline_size" type="int" default="0" />
<param index="6" name="px_range" type="float" default="1.0" />
+ <param index="7" name="scale" type="float" default="1.0" />
<description>
</description>
</method>
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 637e502d49..d2c6dee373 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -930,6 +930,7 @@
<param index="1" name="language" type="String" default="&quot;&quot;" />
<description>
Converts a number from the Western Arabic (0..9) to the numeral systems used in [param language].
+ If [param language] is omitted, the active locale will be used.
</description>
</method>
<method name="free_rid">
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 02cfd3e873..a70a40c5a1 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -96,6 +96,7 @@
#include "editor/export/editor_export.h"
#include "editor/export/export_template_manager.h"
#include "editor/export/project_export.h"
+#include "editor/fbx_importer_manager.h"
#include "editor/filesystem_dock.h"
#include "editor/history_dock.h"
#include "editor/import/audio_stream_import_settings.h"
@@ -2981,7 +2982,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case SETTINGS_MANAGE_EXPORT_TEMPLATES: {
export_template_manager->popup_manager();
-
+ } break;
+ case SETTINGS_MANAGE_FBX_IMPORTER: {
+#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
+ fbx_importer_manager->show_dialog();
+#endif
} break;
case SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE: {
custom_build_manage_templates->hide();
@@ -6624,6 +6629,11 @@ EditorNode::EditorNode() {
gui_base->add_child(about);
feature_profile_manager->connect("current_feature_profile_changed", callable_mp(this, &EditorNode::_feature_profile_changed));
+#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
+ fbx_importer_manager = memnew(FBXImporterManager);
+ gui_base->add_child(fbx_importer_manager);
+#endif
+
warning = memnew(AcceptDialog);
warning->add_button(TTR("Copy Text"), true, "copy");
gui_base->add_child(warning);
@@ -6796,6 +6806,9 @@ EditorNode::EditorNode() {
#ifndef ANDROID_ENABLED
settings_menu->add_item(TTR("Manage Export Templates..."), SETTINGS_MANAGE_EXPORT_TEMPLATES);
#endif
+#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
+ settings_menu->add_item(TTR("Configure FBX Importer..."), SETTINGS_MANAGE_FBX_IMPORTER);
+#endif
help_menu = memnew(PopupMenu);
help_menu->set_name(TTR("Help"));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index c430662c7f..950970379d 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -77,6 +77,7 @@ class EditorSettingsDialog;
class EditorToaster;
class EditorUndoRedoManager;
class ExportTemplateManager;
+class FBXImporterManager;
class FileDialog;
class FileSystemDock;
class HistoryDock;
@@ -209,6 +210,7 @@ private:
SETTINGS_EDITOR_DATA_FOLDER,
SETTINGS_EDITOR_CONFIG_FOLDER,
SETTINGS_MANAGE_EXPORT_TEMPLATES,
+ SETTINGS_MANAGE_FBX_IMPORTER,
SETTINGS_MANAGE_FEATURE_PROFILES,
SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE,
SETTINGS_PICK_MAIN_SCENE,
@@ -285,6 +287,8 @@ private:
ProjectExportDialog *project_export = nullptr;
ProjectSettingsEditor *project_settings_editor = nullptr;
+ FBXImporterManager *fbx_importer_manager = nullptr;
+
Vector<EditorPlugin *> editor_plugins;
bool _initializing_plugins = false;
HashMap<String, EditorPlugin *> addon_name_to_plugin;
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
index 9587e65cad..e8a0912d66 100644
--- a/editor/editor_property_name_processor.cpp
+++ b/editor/editor_property_name_processor.cpp
@@ -231,6 +231,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["tcp"] = "TCP";
capitalize_string_remaps["tls"] = "TLS";
capitalize_string_remaps["ui"] = "UI";
+ capitalize_string_remaps["uri"] = "URI";
capitalize_string_remaps["url"] = "URL";
capitalize_string_remaps["urls"] = "URLs";
capitalize_string_remaps["us"] = String::utf8("(µs)"); // Unit.
diff --git a/editor/fbx_importer_manager.cpp b/editor/fbx_importer_manager.cpp
new file mode 100644
index 0000000000..b258fe7e09
--- /dev/null
+++ b/editor/fbx_importer_manager.cpp
@@ -0,0 +1,158 @@
+/*************************************************************************/
+/* fbx_importer_manager.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "fbx_importer_manager.h"
+
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "scene/gui/link_button.h"
+
+void FBXImporterManager::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ connect("confirmed", callable_mp(this, &FBXImporterManager::_path_confirmed));
+ } break;
+ }
+}
+
+void FBXImporterManager::show_dialog(bool p_exclusive) {
+ String fbx2gltf_path = EDITOR_GET("filesystem/import/fbx/fbx2gltf_path");
+ fbx_path->set_text(fbx2gltf_path);
+ _validate_path(fbx2gltf_path);
+
+ set_flag(Window::FLAG_BORDERLESS, p_exclusive); // Avoid closing accidentally .
+ set_close_on_escape(!p_exclusive);
+
+ popup_centered();
+}
+
+void FBXImporterManager::_validate_path(const String &p_path) {
+ String error;
+ bool success = false;
+
+ if (p_path == "") {
+ error = TTR("Path to FBX2glTF executable is empty.");
+ } else if (!FileAccess::exists(p_path)) {
+ error = TTR("Path to FBX2glTF executable is invalid.");
+ } else {
+ List<String> args;
+ args.push_back("--version");
+ int exitcode;
+ Error err = OS::get_singleton()->execute(p_path, args, nullptr, &exitcode);
+
+ if (err == OK && exitcode == 0) {
+ success = true;
+ } else {
+ error = TTR("Error executing this file (wrong version or architecture).");
+ }
+ }
+
+ if (success) {
+ path_status->set_text(TTR("FBX2glTF executable is valid."));
+ path_status->add_theme_color_override("font_color", path_status->get_theme_color(SNAME("success_color"), SNAME("Editor")));
+ get_ok_button()->set_disabled(false);
+ } else {
+ path_status->set_text(error);
+ path_status->add_theme_color_override("font_color", path_status->get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ get_ok_button()->set_disabled(true);
+ }
+}
+
+void FBXImporterManager::_select_file(const String &p_path) {
+ fbx_path->set_text(p_path);
+ _validate_path(p_path);
+}
+
+void FBXImporterManager::_path_confirmed() {
+ String path = fbx_path->get_text();
+ EditorSettings::get_singleton()->set("filesystem/import/fbx/fbx2gltf_path", path);
+ EditorSettings::get_singleton()->save();
+}
+
+void FBXImporterManager::_browse_install() {
+ if (fbx_path->get_text() != String()) {
+ browse_dialog->set_current_file(fbx_path->get_text());
+ }
+
+ browse_dialog->popup_centered_ratio();
+}
+
+FBXImporterManager *FBXImporterManager::singleton = nullptr;
+
+FBXImporterManager::FBXImporterManager() {
+ singleton = this;
+
+ set_title(TTR("Configure FBX Importer"));
+
+ VBoxContainer *vb = memnew(VBoxContainer);
+ vb->add_child(memnew(Label(TTR("FBX2glTF is required for importing FBX files.\nPlease download it and provide a valid path to the binary:"))));
+ LinkButton *lb = memnew(LinkButton);
+ lb->set_text(TTR("Click this link to download FBX2glTF"));
+ lb->set_uri("https://godotengine.org/fbx-import");
+ vb->add_child(lb);
+
+ HBoxContainer *hb = memnew(HBoxContainer);
+
+ fbx_path = memnew(LineEdit);
+ fbx_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hb->add_child(fbx_path);
+ fbx_path_browse = memnew(Button);
+ hb->add_child(fbx_path_browse);
+ fbx_path_browse->set_text(TTR("Browse"));
+ fbx_path_browse->connect("pressed", callable_mp(this, &FBXImporterManager::_browse_install));
+ hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hb->set_custom_minimum_size(Size2(400 * EDSCALE, 0));
+
+ vb->add_child(hb);
+
+ path_status = memnew(Label);
+ vb->add_child(path_status);
+
+ add_child(vb);
+
+ fbx_path->connect("text_changed", callable_mp(this, &FBXImporterManager::_validate_path));
+
+ get_ok_button()->set_text(TTR("Confirm Path"));
+
+ browse_dialog = memnew(EditorFileDialog);
+ browse_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ browse_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+#if defined(X11_ENABLED)
+ browse_dialog->add_filter("FBX2glTF-linux-x86_64");
+#elif defined(OSX_ENABLED)
+ browse_dialog->add_filter("FBX2glTF-macos-x86_64");
+#elif defined(WINDOWS_ENABLED)
+ browse_dialog->add_filter("FBX2glTF-windows-x86_64");
+#endif
+
+ browse_dialog->connect("file_selected", callable_mp(this, &FBXImporterManager::_select_file));
+
+ add_child(browse_dialog);
+}
diff --git a/editor/fbx_importer_manager.h b/editor/fbx_importer_manager.h
new file mode 100644
index 0000000000..28de761519
--- /dev/null
+++ b/editor/fbx_importer_manager.h
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* fbx_importer_manager.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef FBX_IMPORTER_MANAGER_H
+#define FBX_IMPORTER_MANAGER_H
+
+#include "editor/editor_file_dialog.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/line_edit.h"
+
+class FBXImporterManager : public ConfirmationDialog {
+ GDCLASS(FBXImporterManager, ConfirmationDialog)
+
+ Label *message = nullptr;
+ LineEdit *fbx_path = nullptr;
+ Button *fbx_path_browse = nullptr;
+ EditorFileDialog *browse_dialog = nullptr;
+ Label *path_status = nullptr;
+
+ void _validate_path(const String &p_path);
+ void _select_file(const String &p_path);
+ void _path_confirmed();
+ void _browse_install();
+ void _link_clicked();
+
+ static FBXImporterManager *singleton;
+
+protected:
+ void _notification(int p_what);
+
+public:
+ static FBXImporterManager *get_singleton() { return singleton; }
+
+ void show_dialog(bool p_exclusive = false);
+
+ FBXImporterManager();
+};
+
+#endif // FBX_IMPORTER_MANAGER_H
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
new file mode 100644
index 0000000000..60d949cdf0
--- /dev/null
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -0,0 +1,280 @@
+/*************************************************************************/
+/* audio_stream_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "audio_stream_editor_plugin.h"
+
+#include "core/core_string_names.h"
+#include "editor/audio_stream_preview.h"
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "scene/resources/audio_stream_wav.h"
+
+// AudioStreamEditor
+
+void AudioStreamEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ AudioStreamPreviewGenerator::get_singleton()->connect(SNAME("preview_updated"), callable_mp(this, &AudioStreamEditor::_preview_changed));
+ } break;
+ case NOTIFICATION_THEME_CHANGED:
+ case NOTIFICATION_ENTER_TREE: {
+ Ref<Font> font = get_theme_font(SNAME("status_source"), SNAME("EditorFonts"));
+
+ _current_label->add_theme_font_override(SNAME("font"), font);
+ _duration_label->add_theme_font_override(SNAME("font"), font);
+
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ _stop_button->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
+ _preview->set_color(get_theme_color(SNAME("dark_color_2"), SNAME("Editor")));
+
+ set_color(get_theme_color(SNAME("dark_color_1"), SNAME("Editor")));
+
+ _indicator->queue_redraw();
+ _preview->queue_redraw();
+ } break;
+ case NOTIFICATION_PROCESS: {
+ _current = _player->get_playback_position();
+ _indicator->queue_redraw();
+ } break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible_in_tree()) {
+ _stop();
+ }
+ } break;
+ default: {
+ } break;
+ }
+}
+
+void AudioStreamEditor::_draw_preview() {
+ Rect2 rect = _preview->get_rect();
+ Size2 size = get_size();
+
+ Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream);
+ float preview_len = preview->get_length();
+
+ Vector<Vector2> lines;
+ lines.resize(size.width * 2);
+
+ for (int i = 0; i < size.width; i++) {
+ float ofs = i * preview_len / size.width;
+ float ofs_n = (i + 1) * preview_len / size.width;
+ float max = preview->get_max(ofs, ofs_n) * 0.5 + 0.5;
+ float min = preview->get_min(ofs, ofs_n) * 0.5 + 0.5;
+
+ int idx = i;
+ lines.write[idx * 2 + 0] = Vector2(i + 1, rect.position.y + min * rect.size.y);
+ lines.write[idx * 2 + 1] = Vector2(i + 1, rect.position.y + max * rect.size.y);
+ }
+
+ RS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, { get_theme_color(SNAME("contrast_color_2"), SNAME("Editor")) });
+}
+
+void AudioStreamEditor::_preview_changed(ObjectID p_which) {
+ if (stream.is_valid() && stream->get_instance_id() == p_which) {
+ _preview->queue_redraw();
+ }
+}
+
+void AudioStreamEditor::_stream_changed() {
+ if (!is_visible()) {
+ return;
+ }
+ queue_redraw();
+}
+
+void AudioStreamEditor::_play() {
+ if (_player->is_playing()) {
+ _pausing = true;
+ _player->stop();
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ set_process(false);
+ } else {
+ _pausing = false;
+ _player->play(_current);
+ _play_button->set_icon(get_theme_icon(SNAME("Pause"), SNAME("EditorIcons")));
+ set_process(true);
+ }
+}
+
+void AudioStreamEditor::_stop() {
+ _player->stop();
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ _current = 0;
+ _indicator->queue_redraw();
+ set_process(false);
+}
+
+void AudioStreamEditor::_on_finished() {
+ _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ if (!_pausing) {
+ _current = 0;
+ _indicator->queue_redraw();
+ } else {
+ _pausing = false;
+ }
+ set_process(false);
+}
+
+void AudioStreamEditor::_draw_indicator() {
+ if (stream.is_null()) {
+ return;
+ }
+
+ Rect2 rect = _preview->get_rect();
+ float len = stream->get_length();
+ float ofs_x = _current / len * rect.size.width;
+ const Color col = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ Ref<Texture2D> icon = get_theme_icon(SNAME("TimelineIndicator"), SNAME("EditorIcons"));
+ _indicator->draw_line(Point2(ofs_x, 0), Point2(ofs_x, rect.size.height), col, Math::round(2 * EDSCALE));
+ _indicator->draw_texture(
+ icon,
+ Point2(ofs_x - icon->get_width() * 0.5, 0),
+ col);
+
+ _current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /");
+}
+
+void AudioStreamEditor::_on_input_indicator(Ref<InputEvent> p_event) {
+ const Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
+ if (mb->is_pressed()) {
+ _seek_to(mb->get_position().x);
+ }
+ _dragging = mb->is_pressed();
+ }
+
+ const Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ if (_dragging) {
+ _seek_to(mm->get_position().x);
+ }
+ }
+}
+
+void AudioStreamEditor::_seek_to(real_t p_x) {
+ _current = p_x / _preview->get_rect().size.x * stream->get_length();
+ _current = CLAMP(_current, 0, stream->get_length());
+ _player->seek(_current);
+ _indicator->queue_redraw();
+}
+
+void AudioStreamEditor::set_stream(const Ref<AudioStream> &p_stream) {
+ if (stream.is_valid()) {
+ stream->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &AudioStreamEditor::_stream_changed));
+ }
+
+ stream = p_stream;
+ if (stream.is_null()) {
+ hide();
+ return;
+ }
+ stream->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &AudioStreamEditor::_stream_changed));
+
+ _player->set_stream(stream);
+ _current = 0;
+
+ String text = String::num(stream->get_length(), 2).pad_decimals(2) + "s";
+ _duration_label->set_text(text);
+
+ queue_redraw();
+}
+
+AudioStreamEditor::AudioStreamEditor() {
+ set_custom_minimum_size(Size2(1, 100) * EDSCALE);
+
+ _player = memnew(AudioStreamPlayer);
+ _player->connect(SNAME("finished"), callable_mp(this, &AudioStreamEditor::_on_finished));
+ add_child(_player);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+ add_child(vbox);
+
+ _preview = memnew(ColorRect);
+ _preview->set_v_size_flags(SIZE_EXPAND_FILL);
+ _preview->connect(SNAME("draw"), callable_mp(this, &AudioStreamEditor::_draw_preview));
+ vbox->add_child(_preview);
+
+ _indicator = memnew(Control);
+ _indicator->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+ _indicator->connect(SNAME("draw"), callable_mp(this, &AudioStreamEditor::_draw_indicator));
+ _indicator->connect(SNAME("gui_input"), callable_mp(this, &AudioStreamEditor::_on_input_indicator));
+ _preview->add_child(_indicator);
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ hbox->add_theme_constant_override("separation", 0);
+ vbox->add_child(hbox);
+
+ _play_button = memnew(Button);
+ hbox->add_child(_play_button);
+ _play_button->set_flat(true);
+ _play_button->set_focus_mode(Control::FOCUS_NONE);
+ _play_button->connect(SNAME("pressed"), callable_mp(this, &AudioStreamEditor::_play));
+ _play_button->set_shortcut(ED_SHORTCUT("audio_stream_editor/audio_preview_play_pause", TTR("Audio Preview Play/Pause"), Key::SPACE));
+
+ _stop_button = memnew(Button);
+ hbox->add_child(_stop_button);
+ _stop_button->set_flat(true);
+ _stop_button->set_focus_mode(Control::FOCUS_NONE);
+ _stop_button->connect(SNAME("pressed"), callable_mp(this, &AudioStreamEditor::_stop));
+
+ _current_label = memnew(Label);
+ _current_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
+ _current_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ _current_label->set_modulate(Color(1, 1, 1, 0.5));
+ hbox->add_child(_current_label);
+
+ _duration_label = memnew(Label);
+ hbox->add_child(_duration_label);
+}
+
+// EditorInspectorPluginAudioStream
+
+bool EditorInspectorPluginAudioStream::can_handle(Object *p_object) {
+ return Object::cast_to<AudioStreamWAV>(p_object) != nullptr;
+}
+
+void EditorInspectorPluginAudioStream::parse_begin(Object *p_object) {
+ AudioStream *stream = Object::cast_to<AudioStream>(p_object);
+
+ editor = memnew(AudioStreamEditor);
+ editor->set_stream(Ref<AudioStream>(stream));
+
+ add_custom_control(editor);
+}
+
+// AudioStreamEditorPlugin
+
+AudioStreamEditorPlugin::AudioStreamEditorPlugin() {
+ Ref<EditorInspectorPluginAudioStream> plugin;
+ plugin.instantiate();
+ add_inspector_plugin(plugin);
+}
diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/plugins/audio_stream_editor_plugin.h
new file mode 100644
index 0000000000..13e52929ee
--- /dev/null
+++ b/editor/plugins/audio_stream_editor_plugin.h
@@ -0,0 +1,93 @@
+/*************************************************************************/
+/* audio_stream_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef AUDIO_STREAM_EDITOR_PLUGIN_H
+#define AUDIO_STREAM_EDITOR_PLUGIN_H
+
+#include "editor/editor_inspector.h"
+#include "editor/editor_plugin.h"
+#include "scene/audio/audio_stream_player.h"
+#include "scene/gui/button.h"
+#include "scene/gui/color_rect.h"
+#include "scene/gui/label.h"
+
+class AudioStreamEditor : public ColorRect {
+ GDCLASS(AudioStreamEditor, ColorRect);
+
+ Ref<AudioStream> stream;
+
+ AudioStreamPlayer *_player = nullptr;
+ ColorRect *_preview = nullptr;
+ Control *_indicator = nullptr;
+ Label *_current_label = nullptr;
+ Label *_duration_label = nullptr;
+
+ Button *_play_button = nullptr;
+ Button *_stop_button = nullptr;
+
+ float _current = 0;
+ bool _dragging = false;
+ bool _pausing = false;
+
+protected:
+ void _notification(int p_what);
+ void _preview_changed(ObjectID p_which);
+ void _play();
+ void _stop();
+ void _on_finished();
+ void _draw_preview();
+ void _draw_indicator();
+ void _on_input_indicator(Ref<InputEvent> p_event);
+ void _seek_to(real_t p_x);
+ void _stream_changed();
+
+public:
+ void set_stream(const Ref<AudioStream> &p_stream);
+
+ AudioStreamEditor();
+};
+
+class EditorInspectorPluginAudioStream : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginAudioStream, EditorInspectorPlugin);
+ AudioStreamEditor *editor = nullptr;
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+};
+
+class AudioStreamEditorPlugin : public EditorPlugin {
+ GDCLASS(AudioStreamEditorPlugin, EditorPlugin);
+
+public:
+ AudioStreamEditorPlugin();
+};
+
+#endif // AUDIO_STREAM_EDITOR_PLUGIN_H
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 4a8e5d9979..4b31e99f0e 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -160,23 +160,23 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
p_library->set_item_shapes(id, collisions);
- Ref<NavigationMesh> navmesh;
- Transform3D navmesh_transform;
+ Ref<NavigationMesh> navigation_mesh;
+ Transform3D navigation_mesh_transform;
for (int j = 0; j < mi->get_child_count(); j++) {
Node *child2 = mi->get_child(j);
if (!Object::cast_to<NavigationRegion3D>(child2)) {
continue;
}
NavigationRegion3D *sb = Object::cast_to<NavigationRegion3D>(child2);
- navmesh = sb->get_navigation_mesh();
- navmesh_transform = sb->get_transform();
- if (!navmesh.is_null()) {
+ navigation_mesh = sb->get_navigation_mesh();
+ navigation_mesh_transform = sb->get_transform();
+ if (!navigation_mesh.is_null()) {
break;
}
}
- if (!navmesh.is_null()) {
- p_library->set_item_navmesh(id, navmesh);
- p_library->set_item_navmesh_transform(id, navmesh_transform);
+ if (!navigation_mesh.is_null()) {
+ p_library->set_item_navigation_mesh(id, navigation_mesh);
+ p_library->set_item_navigation_mesh_transform(id, navigation_mesh_transform);
}
}
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 363ad273a8..4976c8c750 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -2606,7 +2606,7 @@ void Node3DEditorViewport::_project_settings_changed() {
const bool use_taa = GLOBAL_GET("rendering/anti_aliasing/quality/use_taa");
viewport->set_use_taa(use_taa);
- const bool transparent_background = GLOBAL_GET("rendering/transparent_background");
+ const bool transparent_background = GLOBAL_GET("rendering/viewport/transparent_background");
viewport->set_transparent_background(transparent_background);
const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding");
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 57f9b3135a..1fdf940a82 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -309,7 +309,22 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) {
case ROTATE_LEFT:
case FLIP_HORIZONTALLY:
case FLIP_VERTICALLY: {
- undo_redo->create_action(TTR("Rotate Polygons Left"));
+ switch (p_item_pressed) {
+ case ROTATE_RIGHT: {
+ undo_redo->create_action(TTR("Rotate Polygons Right"));
+ } break;
+ case ROTATE_LEFT: {
+ undo_redo->create_action(TTR("Rotate Polygons Left"));
+ } break;
+ case FLIP_HORIZONTALLY: {
+ undo_redo->create_action(TTR("Flip Polygons Horizontally"));
+ } break;
+ case FLIP_VERTICALLY: {
+ undo_redo->create_action(TTR("Flip Polygons Vertically"));
+ } break;
+ default:
+ break;
+ }
for (unsigned int i = 0; i < polygons.size(); i++) {
Vector<Point2> new_polygon;
for (int point_index = 0; point_index < polygons[i].size(); point_index++) {
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 4131c06745..5a1f214933 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -924,6 +924,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
Color modulate = tile_data->get_modulate();
Color self_modulate = tile_map->get_self_modulate();
modulate *= self_modulate;
+ modulate *= tile_map->get_layer_modulate(tile_map_layer);
// Draw the tile.
p_overlay->draw_texture_rect_region(atlas_source->get_texture(), dest_rect, source_rect, modulate * Color(1.0, 1.0, 1.0, 0.5), transpose, tile_set->is_uv_clipping());
diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp
index 247d5e1717..8ac0aa6fe3 100644
--- a/editor/register_editor_types.cpp
+++ b/editor/register_editor_types.cpp
@@ -48,6 +48,7 @@
#include "editor/import/editor_import_plugin.h"
#include "editor/import/resource_importer_scene.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
+#include "editor/plugins/audio_stream_editor_plugin.h"
#include "editor/plugins/audio_stream_randomizer_editor_plugin.h"
#include "editor/plugins/bit_map_editor_plugin.h"
#include "editor/plugins/bone_map_editor_plugin.h"
@@ -155,6 +156,7 @@ void register_editor_types() {
// This list is alphabetized, and plugins that depend on Node2D are in their own section below.
EditorPlugins::add_by_type<AnimationTreeEditorPlugin>();
+ EditorPlugins::add_by_type<AudioStreamEditorPlugin>();
EditorPlugins::add_by_type<AudioStreamRandomizerEditorPlugin>();
EditorPlugins::add_by_type<BitMapEditorPlugin>();
EditorPlugins::add_by_type<BoneMapEditorPlugin>();
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 96688a3614..f91b571118 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1965,37 +1965,21 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
}
Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo();
- if (selected.size() == 1) {
- Node *node = selected.front()->get();
- Ref<Script> existing = node->get_script();
-
- undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, node);
- undo_redo->add_do_method(InspectorDock::get_singleton(), "store_script_properties", node);
- undo_redo->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", node);
- undo_redo->add_do_method(node, "set_script", p_script);
- undo_redo->add_undo_method(node, "set_script", existing);
- undo_redo->add_do_method(InspectorDock::get_singleton(), "apply_script_properties", node);
- undo_redo->add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", node);
+ undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, selected.front()->get());
+ for (Node *E : selected) {
+ Ref<Script> existing = E->get_script();
+ undo_redo->add_do_method(InspectorDock::get_singleton(), "store_script_properties", E);
+ undo_redo->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", E);
+ undo_redo->add_do_method(E, "set_script", p_script);
+ undo_redo->add_undo_method(E, "set_script", existing);
+ undo_redo->add_do_method(InspectorDock::get_singleton(), "apply_script_properties", E);
+ undo_redo->add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", E);
undo_redo->add_do_method(this, "_update_script_button");
undo_redo->add_undo_method(this, "_update_script_button");
- undo_redo->commit_action();
- } else {
- undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, selected.front()->get());
- for (Node *E : selected) {
- Ref<Script> existing = E->get_script();
- undo_redo->add_do_method(InspectorDock::get_singleton(), "store_script_properties", E);
- undo_redo->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", E);
- undo_redo->add_do_method(E, "set_script", p_script);
- undo_redo->add_undo_method(E, "set_script", existing);
- undo_redo->add_do_method(InspectorDock::get_singleton(), "apply_script_properties", E);
- undo_redo->add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", E);
- undo_redo->add_do_method(this, "_update_script_button");
- undo_redo->add_undo_method(this, "_update_script_button");
- }
- undo_redo->commit_action();
}
+ undo_redo->commit_action();
- _push_item(p_script.operator->());
+ _push_item(p_script.ptr());
_update_script_button();
}
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 258f1a80f7..57a29cc81e 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1111,21 +1111,27 @@ bool GDScript::inherits_script(const Ref<Script> &p_script) const {
GDScript *GDScript::find_class(const String &p_qualified_name) {
String first = p_qualified_name.get_slice("::", 0);
+ Vector<String> class_names;
GDScript *result = nullptr;
+ // Empty initial name means start here.
if (first.is_empty() || first == name) {
+ class_names = p_qualified_name.split("::");
result = this;
- } else if (first == get_root_script()->path) {
+ } else if (p_qualified_name.begins_with(get_root_script()->path)) {
+ // Script path could have a class path separator("::") in it.
+ class_names = p_qualified_name.trim_prefix(get_root_script()->path).split("::");
result = get_root_script();
} else if (HashMap<StringName, Ref<GDScript>>::Iterator E = subclasses.find(first)) {
+ class_names = p_qualified_name.split("::");
result = E->value.ptr();
} else if (_owner != nullptr) {
// Check parent scope.
return _owner->find_class(p_qualified_name);
}
- int name_count = p_qualified_name.get_slice_count("::");
- for (int i = 1; result != nullptr && i < name_count; i++) {
- String current_name = p_qualified_name.get_slice("::", i);
+ // Starts at index 1 because index 0 was handled above.
+ for (int i = 1; result != nullptr && i < class_names.size(); i++) {
+ String current_name = class_names[i];
if (HashMap<StringName, Ref<GDScript>>::Iterator E = result->subclasses.find(current_name)) {
result = E->value.ptr();
} else {
@@ -1137,11 +1143,12 @@ GDScript *GDScript::find_class(const String &p_qualified_name) {
return result;
}
-bool GDScript::is_subclass(const GDScript *p_script) {
+bool GDScript::has_class(const GDScript *p_script) {
String fqn = p_script->fully_qualified_name;
- if (!fqn.is_empty() && fqn != fully_qualified_name && fqn.begins_with(fully_qualified_name)) {
- String fqn_rest = fqn.substr(fully_qualified_name.length());
- return find_class(fqn_rest) == p_script;
+ if (fully_qualified_name.is_empty() && fqn.get_slice("::", 0).is_empty()) {
+ return p_script == this;
+ } else if (fqn.begins_with(fully_qualified_name)) {
+ return p_script == find_class(fqn.trim_prefix(fully_qualified_name));
}
return false;
}
@@ -2592,8 +2599,7 @@ Ref<GDScript> GDScriptLanguage::get_script_by_fully_qualified_name(const String
SelfList<GDScript> *elem = script_list.first();
while (elem) {
GDScript *scr = elem->self();
- scr = scr->find_class(p_name);
- if (scr != nullptr) {
+ if (scr->fully_qualified_name == p_name) {
return scr;
}
elem = elem->next();
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 7911ea47ec..332d18f720 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -187,7 +187,7 @@ public:
bool inherits_script(const Ref<Script> &p_script) const override;
GDScript *find_class(const String &p_qualified_name);
- bool is_subclass(const GDScript *p_script);
+ bool has_class(const GDScript *p_script);
GDScript *get_root_script();
bool is_root_script() const { return _owner == nullptr; }
String get_fully_qualified_name() const { return fully_qualified_name; }
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index a443556fd5..1a1c2193bf 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -3148,6 +3148,16 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
case GDScriptParser::ClassNode::Member::FUNCTION:
p_identifier->set_datatype(make_callable_type(member.function->info));
break;
+ case GDScriptParser::ClassNode::Member::CLASS:
+ if (p_base != nullptr && p_base->is_constant) {
+ Error err = OK;
+ GDScript *scr = GDScriptCache::get_full_script(base.script_path, err).ptr();
+ ERR_FAIL_COND_MSG(err != OK, "Error while getting subscript full script.");
+ scr = scr->find_class(p_identifier->get_datatype().class_type->fqcn);
+ p_identifier->reduced_value = scr;
+ p_identifier->is_constant = true;
+ }
+ break;
default:
break; // Type already set.
}
@@ -3157,7 +3167,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
// TODO: Allow outer static functions.
if (base_class->outer != nullptr) {
List<GDScriptParser::ClassNode *> script_classes;
- get_class_node_current_scope_classes(parser->current_class, &script_classes);
+ get_class_node_current_scope_classes(base_class->outer, &script_classes);
for (GDScriptParser::ClassNode *script_class : script_classes) {
if (script_class->has_member(name)) {
resolve_class_member(script_class, name, p_identifier);
@@ -3617,7 +3627,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
result_type = attr_type;
p_subscript->is_constant = p_subscript->attribute->is_constant;
p_subscript->reduced_value = p_subscript->attribute->reduced_value;
- } else if (!base_type.is_constant) {
+ } else if (!base_type.is_meta_type || !base_type.is_constant) {
valid = base_type.kind != GDScriptParser::DataType::BUILTIN;
#ifdef DEBUG_ENABLED
if (valid) {
@@ -3996,37 +4006,27 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
result.kind = GDScriptParser::DataType::CLASS;
// This might be an inner class, so we want to get the parser for the root.
// But still get the inner class from that tree.
- GDScript *current = gds.ptr();
- List<StringName> class_chain;
- while (current->_owner) {
- // Push to front so it's in reverse.
- class_chain.push_front(current->name);
- current = current->_owner;
- }
-
- Ref<GDScriptParserRef> ref = get_parser_for(current->get_path());
+ String script_path = gds->get_script_path();
+ Ref<GDScriptParserRef> ref = get_parser_for(script_path);
if (ref.is_null()) {
- push_error("Could not find script in path.", p_source);
+ push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
GDScriptParser::DataType error_type;
error_type.kind = GDScriptParser::DataType::VARIANT;
return error_type;
}
- ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
-
- GDScriptParser::ClassNode *found = ref->get_parser()->head;
-
- for (const StringName &E : class_chain) {
- if (!found->has_member(E)) {
- return GDScriptParser::DataType();
- }
-
- if (found->get_member(E).type != GDScriptParser::ClassNode::Member::CLASS) {
- return GDScriptParser::DataType();
+ Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
+ GDScriptParser::ClassNode *found = nullptr;
+ if (err == OK) {
+ found = ref->get_parser()->find_class(gds->fully_qualified_name);
+ if (found != nullptr) {
+ err = resolve_class_inheritance(found, p_source);
}
-
- resolve_class_member(found, E, p_source);
-
- found = found->get_member(E).m_class;
+ }
+ if (err || found == nullptr) {
+ push_error(vformat(R"(Could not resolve script "%s".)", script_path), p_source);
+ GDScriptParser::DataType error_type;
+ error_type.kind = GDScriptParser::DataType::VARIANT;
+ return error_type;
}
result.class_type = found;
diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h
index 5972481c3a..6a94c25c88 100644
--- a/modules/gdscript/gdscript_codegen.h
+++ b/modules/gdscript/gdscript_codegen.h
@@ -59,7 +59,7 @@ public:
type = p_type;
}
Address(AddressMode p_mode, uint32_t p_address, const GDScriptDataType &p_type = GDScriptDataType()) {
- mode = p_mode,
+ mode = p_mode;
address = p_address;
type = p_type;
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 4740b9b5a9..50588110c4 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -117,8 +117,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.builtin_type = p_datatype.builtin_type;
result.native_type = p_datatype.native_type;
- String root_name = p_datatype.class_type->fqcn.get_slice("::", 0);
- bool is_local_class = !root_name.is_empty() && root_name == main_script->fully_qualified_name;
+ bool is_local_class = parser->has_class(p_datatype.class_type);
Ref<GDScript> script;
if (is_local_class) {
@@ -2300,7 +2299,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
return ERR_COMPILATION_FAILED;
}
- if (base.ptr() == main_script || main_script->is_subclass(base.ptr())) {
+ if (main_script->has_class(base.ptr())) {
Error err = _populate_class_members(base.ptr(), p_class->base_type.class_type, p_keep_state);
if (err) {
return err;
diff --git a/modules/gdscript/language_server/godot_lsp.h b/modules/gdscript/language_server/godot_lsp.h
index 024da1cab7..8b58d7731e 100644
--- a/modules/gdscript/language_server/godot_lsp.h
+++ b/modules/gdscript/language_server/godot_lsp.h
@@ -702,7 +702,7 @@ struct DiagnosticRelatedInformation {
Dictionary to_json() const {
Dictionary dict;
- dict["location"] = location.to_json(),
+ dict["location"] = location.to_json();
dict["message"] = message;
return dict;
}
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
new file mode 100644
index 0000000000..65c0d9dabc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
@@ -0,0 +1,12 @@
+class A:
+ class B:
+ func test():
+ print(A.B.D)
+
+class C:
+ class D:
+ pass
+
+func test():
+ var inst = A.B.new()
+ inst.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.out
new file mode 100644
index 0000000000..6baed366f6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot find member "D" in base "B".
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.gd b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.gd
new file mode 100644
index 0000000000..ed5fb18b73
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.gd
@@ -0,0 +1,7 @@
+const External = preload("inner_class_constant_assignment_external.notest.gd")
+const ExternalInnerClass = External.InnerClass
+
+func test():
+ var inst_external: ExternalInnerClass = ExternalInnerClass.new()
+ inst_external.x = 4.0
+ print(inst_external.x)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.out b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.out
new file mode 100644
index 0000000000..15666c46ad
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+4
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment_external.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment_external.notest.gd
new file mode 100644
index 0000000000..788c99d469
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment_external.notest.gd
@@ -0,0 +1,2 @@
+class InnerClass:
+ var x: = 3.0
diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp
index fb5fb455b8..27e0052c1a 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.cpp
+++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp
@@ -36,6 +36,7 @@
#include "core/config/project_settings.h"
#include "editor/editor_settings.h"
+#include "main/main.h"
uint32_t EditorSceneFormatImporterFBX::get_import_flags() const {
return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION;
@@ -111,4 +112,30 @@ void EditorSceneFormatImporterFBX::get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) {
}
+bool EditorFileSystemImportFormatSupportQueryFBX::is_active() const {
+ String fbx2gltf_path = EDITOR_GET("filesystem/import/fbx/fbx2gltf_path");
+ return !FileAccess::exists(fbx2gltf_path);
+}
+
+Vector<String> EditorFileSystemImportFormatSupportQueryFBX::get_file_extensions() const {
+ Vector<String> ret;
+ ret.push_back("fbx");
+ return ret;
+}
+
+bool EditorFileSystemImportFormatSupportQueryFBX::query() {
+ FBXImporterManager::get_singleton()->show_dialog(true);
+
+ while (true) {
+ OS::get_singleton()->delay_usec(1);
+ DisplayServer::get_singleton()->process_events();
+ Main::iteration();
+ if (!FBXImporterManager::get_singleton()->is_visible()) {
+ break;
+ }
+ }
+
+ return false;
+}
+
#endif // TOOLS_ENABLED
diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h
index 6bf9f3e033..82179cc460 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.h
+++ b/modules/gltf/editor/editor_scene_importer_fbx.h
@@ -33,6 +33,8 @@
#ifdef TOOLS_ENABLED
+#include "editor/editor_file_system.h"
+#include "editor/fbx_importer_manager.h"
#include "editor/import/resource_importer_scene.h"
class Animation;
@@ -53,6 +55,15 @@ public:
const HashMap<StringName, Variant> &p_options) override;
};
+class EditorFileSystemImportFormatSupportQueryFBX : public EditorFileSystemImportFormatSupportQuery {
+ GDCLASS(EditorFileSystemImportFormatSupportQueryFBX, EditorFileSystemImportFormatSupportQuery);
+
+public:
+ virtual bool is_active() const override;
+ virtual Vector<String> get_file_extensions() const override;
+ virtual bool query() override;
+};
+
#endif // TOOLS_ENABLED
#endif // EDITOR_SCENE_IMPORTER_FBX_H
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index f4db576b0c..d858f76b28 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -3384,177 +3384,179 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
if (!material->get_name().is_empty()) {
d["name"] = _gen_unique_name(p_state, material->get_name());
}
+
Ref<BaseMaterial3D> base_material = material;
- if (base_material.is_valid()) {
- Dictionary mr;
- {
- Array arr;
- const Color c = base_material->get_albedo().srgb_to_linear();
- arr.push_back(c.r);
- arr.push_back(c.g);
- arr.push_back(c.b);
- arr.push_back(c.a);
- mr["baseColorFactor"] = arr;
+ if (base_material.is_null()) {
+ materials.push_back(d);
+ continue;
+ }
+
+ Dictionary mr;
+ {
+ Array arr;
+ const Color c = base_material->get_albedo().srgb_to_linear();
+ arr.push_back(c.r);
+ arr.push_back(c.g);
+ arr.push_back(c.b);
+ arr.push_back(c.a);
+ mr["baseColorFactor"] = arr;
+ }
+ {
+ Dictionary bct;
+ Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
+ GLTFTextureIndex gltf_texture_index = -1;
+
+ if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
+ albedo_texture->set_name(material->get_name() + "_albedo");
+ gltf_texture_index = _set_texture(p_state, albedo_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
}
- {
- Dictionary bct;
- if (base_material.is_valid()) {
- Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
- GLTFTextureIndex gltf_texture_index = -1;
-
- if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
- albedo_texture->set_name(material->get_name() + "_albedo");
- gltf_texture_index = _set_texture(p_state, albedo_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
- }
- if (gltf_texture_index != -1) {
- bct["index"] = gltf_texture_index;
- Dictionary extensions = _serialize_texture_transform_uv1(material);
- if (!extensions.is_empty()) {
- bct["extensions"] = extensions;
- p_state->use_khr_texture_transform = true;
- }
- mr["baseColorTexture"] = bct;
- }
+ if (gltf_texture_index != -1) {
+ bct["index"] = gltf_texture_index;
+ Dictionary extensions = _serialize_texture_transform_uv1(material);
+ if (!extensions.is_empty()) {
+ bct["extensions"] = extensions;
+ p_state->use_khr_texture_transform = true;
+ }
+ mr["baseColorTexture"] = bct;
+ }
+ }
+
+ mr["metallicFactor"] = base_material->get_metallic();
+ mr["roughnessFactor"] = base_material->get_roughness();
+ bool has_roughness = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid();
+ bool has_ao = base_material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid();
+ bool has_metalness = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid();
+ if (has_ao || has_roughness || has_metalness) {
+ Dictionary mrt;
+ Ref<Texture2D> roughness_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS);
+ BaseMaterial3D::TextureChannel roughness_channel = base_material->get_roughness_texture_channel();
+ Ref<Texture2D> metallic_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC);
+ BaseMaterial3D::TextureChannel metalness_channel = base_material->get_metallic_texture_channel();
+ Ref<Texture2D> ao_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION);
+ BaseMaterial3D::TextureChannel ao_channel = base_material->get_ao_texture_channel();
+ Ref<ImageTexture> orm_texture;
+ orm_texture.instantiate();
+ Ref<Image> orm_image;
+ orm_image.instantiate();
+ int32_t height = 0;
+ int32_t width = 0;
+ Ref<Image> ao_image;
+ if (has_ao) {
+ height = ao_texture->get_height();
+ width = ao_texture->get_width();
+ ao_image = ao_texture->get_image();
+ Ref<ImageTexture> img_tex = ao_image;
+ if (img_tex.is_valid()) {
+ ao_image = img_tex->get_image();
+ }
+ if (ao_image->is_compressed()) {
+ ao_image->decompress();
+ }
+ }
+ Ref<Image> roughness_image;
+ if (has_roughness) {
+ height = roughness_texture->get_height();
+ width = roughness_texture->get_width();
+ roughness_image = roughness_texture->get_image();
+ Ref<ImageTexture> img_tex = roughness_image;
+ if (img_tex.is_valid()) {
+ roughness_image = img_tex->get_image();
+ }
+ if (roughness_image->is_compressed()) {
+ roughness_image->decompress();
}
}
- if (base_material.is_valid()) {
- mr["metallicFactor"] = base_material->get_metallic();
- mr["roughnessFactor"] = base_material->get_roughness();
- bool has_roughness = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid();
- bool has_ao = base_material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid();
- bool has_metalness = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid();
- if (has_ao || has_roughness || has_metalness) {
- Dictionary mrt;
- Ref<Texture2D> roughness_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS);
- BaseMaterial3D::TextureChannel roughness_channel = base_material->get_roughness_texture_channel();
- Ref<Texture2D> metallic_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC);
- BaseMaterial3D::TextureChannel metalness_channel = base_material->get_metallic_texture_channel();
- Ref<Texture2D> ao_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION);
- BaseMaterial3D::TextureChannel ao_channel = base_material->get_ao_texture_channel();
- Ref<ImageTexture> orm_texture;
- orm_texture.instantiate();
- Ref<Image> orm_image;
- orm_image.instantiate();
- int32_t height = 0;
- int32_t width = 0;
- Ref<Image> ao_image;
+ Ref<Image> metallness_image;
+ if (has_metalness) {
+ height = metallic_texture->get_height();
+ width = metallic_texture->get_width();
+ metallness_image = metallic_texture->get_image();
+ Ref<ImageTexture> img_tex = metallness_image;
+ if (img_tex.is_valid()) {
+ metallness_image = img_tex->get_image();
+ }
+ if (metallness_image->is_compressed()) {
+ metallness_image->decompress();
+ }
+ }
+ Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
+ if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
+ height = albedo_texture->get_height();
+ width = albedo_texture->get_width();
+ }
+ orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8);
+ if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) {
+ ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ }
+ if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) {
+ roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ }
+ if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) {
+ metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
+ }
+ for (int32_t h = 0; h < height; h++) {
+ for (int32_t w = 0; w < width; w++) {
+ Color c = Color(1.0f, 1.0f, 1.0f);
if (has_ao) {
- height = ao_texture->get_height();
- width = ao_texture->get_width();
- ao_image = ao_texture->get_image();
- Ref<ImageTexture> img_tex = ao_image;
- if (img_tex.is_valid()) {
- ao_image = img_tex->get_image();
- }
- if (ao_image->is_compressed()) {
- ao_image->decompress();
+ if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) {
+ c.r = ao_image->get_pixel(w, h).r;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) {
+ c.r = ao_image->get_pixel(w, h).g;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) {
+ c.r = ao_image->get_pixel(w, h).b;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) {
+ c.r = ao_image->get_pixel(w, h).a;
}
}
- Ref<Image> roughness_image;
if (has_roughness) {
- height = roughness_texture->get_height();
- width = roughness_texture->get_width();
- roughness_image = roughness_texture->get_image();
- Ref<ImageTexture> img_tex = roughness_image;
- if (img_tex.is_valid()) {
- roughness_image = img_tex->get_image();
- }
- if (roughness_image->is_compressed()) {
- roughness_image->decompress();
+ if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) {
+ c.g = roughness_image->get_pixel(w, h).r;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) {
+ c.g = roughness_image->get_pixel(w, h).g;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) {
+ c.g = roughness_image->get_pixel(w, h).b;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) {
+ c.g = roughness_image->get_pixel(w, h).a;
}
}
- Ref<Image> metallness_image;
if (has_metalness) {
- height = metallic_texture->get_height();
- width = metallic_texture->get_width();
- metallness_image = metallic_texture->get_image();
- Ref<ImageTexture> img_tex = metallness_image;
- if (img_tex.is_valid()) {
- metallness_image = img_tex->get_image();
- }
- if (metallness_image->is_compressed()) {
- metallness_image->decompress();
- }
- }
- Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
- if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
- height = albedo_texture->get_height();
- width = albedo_texture->get_width();
- }
- orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8);
- if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) {
- ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
- }
- if (roughness_image.is_valid() && roughness_image->get_size() != Vector2(width, height)) {
- roughness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
- }
- if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) {
- metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS);
- }
- for (int32_t h = 0; h < height; h++) {
- for (int32_t w = 0; w < width; w++) {
- Color c = Color(1.0f, 1.0f, 1.0f);
- if (has_ao) {
- if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) {
- c.r = ao_image->get_pixel(w, h).r;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) {
- c.r = ao_image->get_pixel(w, h).g;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) {
- c.r = ao_image->get_pixel(w, h).b;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) {
- c.r = ao_image->get_pixel(w, h).a;
- }
- }
- if (has_roughness) {
- if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) {
- c.g = roughness_image->get_pixel(w, h).r;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) {
- c.g = roughness_image->get_pixel(w, h).g;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) {
- c.g = roughness_image->get_pixel(w, h).b;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) {
- c.g = roughness_image->get_pixel(w, h).a;
- }
- }
- if (has_metalness) {
- if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) {
- c.b = metallness_image->get_pixel(w, h).r;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) {
- c.b = metallness_image->get_pixel(w, h).g;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) {
- c.b = metallness_image->get_pixel(w, h).b;
- } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) {
- c.b = metallness_image->get_pixel(w, h).a;
- }
- }
- orm_image->set_pixel(w, h, c);
- }
- }
- orm_image->generate_mipmaps();
- orm_texture->set_image(orm_image);
- GLTFTextureIndex orm_texture_index = -1;
- if (has_ao || has_roughness || has_metalness) {
- orm_texture->set_name(material->get_name() + "_orm");
- orm_texture_index = _set_texture(p_state, orm_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
- }
- if (has_ao) {
- Dictionary occt;
- occt["index"] = orm_texture_index;
- d["occlusionTexture"] = occt;
- }
- if (has_roughness || has_metalness) {
- mrt["index"] = orm_texture_index;
- Dictionary extensions = _serialize_texture_transform_uv1(material);
- if (!extensions.is_empty()) {
- mrt["extensions"] = extensions;
- p_state->use_khr_texture_transform = true;
+ if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) {
+ c.b = metallness_image->get_pixel(w, h).r;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) {
+ c.b = metallness_image->get_pixel(w, h).g;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) {
+ c.b = metallness_image->get_pixel(w, h).b;
+ } else if (BaseMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) {
+ c.b = metallness_image->get_pixel(w, h).a;
}
- mr["metallicRoughnessTexture"] = mrt;
}
+ orm_image->set_pixel(w, h, c);
}
}
- d["pbrMetallicRoughness"] = mr;
+ orm_image->generate_mipmaps();
+ orm_texture->set_image(orm_image);
+ GLTFTextureIndex orm_texture_index = -1;
+ if (has_ao || has_roughness || has_metalness) {
+ orm_texture->set_name(material->get_name() + "_orm");
+ orm_texture_index = _set_texture(p_state, orm_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
+ }
+ if (has_ao) {
+ Dictionary occt;
+ occt["index"] = orm_texture_index;
+ d["occlusionTexture"] = occt;
+ }
+ if (has_roughness || has_metalness) {
+ mrt["index"] = orm_texture_index;
+ Dictionary extensions = _serialize_texture_transform_uv1(material);
+ if (!extensions.is_empty()) {
+ mrt["extensions"] = extensions;
+ p_state->use_khr_texture_transform = true;
+ }
+ mr["metallicRoughnessTexture"] = mrt;
+ }
}
+
+ d["pbrMetallicRoughness"] = mr;
if (base_material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING)) {
Dictionary nt;
Ref<ImageTexture> tex;
@@ -3607,6 +3609,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
arr.push_back(c.b);
d["emissiveFactor"] = arr;
}
+
if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
Dictionary et;
Ref<Texture2D> emission_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
@@ -3621,16 +3624,19 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
d["emissiveTexture"] = et;
}
}
+
const bool ds = base_material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED;
if (ds) {
d["doubleSided"] = ds;
}
+
if (base_material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) {
d["alphaMode"] = "MASK";
d["alphaCutoff"] = base_material->get_alpha_scissor_threshold();
} else if (base_material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) {
d["alphaMode"] = "BLEND";
}
+
materials.push_back(d);
}
if (!materials.size()) {
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index cd7a23fbb2..2322e13ae2 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -80,16 +80,13 @@ static void _editor_init() {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,
"filesystem/import/fbx/fbx2gltf_path", PROPERTY_HINT_GLOBAL_FILE));
if (fbx_enabled) {
- Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (fbx2gltf_path.is_empty()) {
- WARN_PRINT("FBX file import is enabled in the project settings, but no FBX2glTF path is configured in the editor settings. FBX files will not be imported.");
- } else if (!da->file_exists(fbx2gltf_path)) {
- WARN_PRINT("FBX file import is enabled, but the FBX2glTF path doesn't point to an accessible file. FBX files will not be imported.");
- } else {
- Ref<EditorSceneFormatImporterFBX> importer;
- importer.instantiate();
- ResourceImporterScene::add_importer(importer);
- }
+ Ref<EditorSceneFormatImporterFBX> importer;
+ importer.instantiate();
+ ResourceImporterScene::get_scene_singleton()->add_importer(importer);
+
+ Ref<EditorFileSystemImportFormatSupportQueryFBX> fbx_import_query;
+ fbx_import_query.instantiate();
+ EditorFileSystem::get_singleton()->add_import_format_support_query(fbx_import_query);
}
}
#endif // TOOLS_ENABLED
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 06ad806afc..1df5aadb75 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -230,7 +230,7 @@ void GridMap::set_navigation_map(RID p_navigation_map) {
map_override = p_navigation_map;
for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
Octant &g = *octant_map[E.key];
- for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ for (KeyValue<IndexKey, Octant::NavigationCell> &F : g.navigation_cell_ids) {
if (F.value.region.is_valid()) {
NavigationServer3D::get_singleton()->region_set_map(F.value.region, map_override);
}
@@ -542,13 +542,13 @@ void GridMap::_octant_transform(const OctantKey &p_key) {
}
// update transform for NavigationServer regions and navigation debugmesh instances
- for (const KeyValue<IndexKey, Octant::NavMesh> &E : g.navmesh_ids) {
+ for (const KeyValue<IndexKey, Octant::NavigationCell> &E : g.navigation_cell_ids) {
if (bake_navigation) {
if (E.value.region.is_valid()) {
NavigationServer3D::get_singleton()->region_set_transform(E.value.region, get_global_transform() * E.value.xform);
}
- if (E.value.navmesh_debug_instance.is_valid()) {
- RS::get_singleton()->instance_set_transform(E.value.navmesh_debug_instance, get_global_transform() * E.value.xform);
+ if (E.value.navigation_mesh_debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_transform(E.value.navigation_mesh_debug_instance, get_global_transform() * E.value.xform);
}
}
}
@@ -574,13 +574,13 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
}
//erase navigation
- for (const KeyValue<IndexKey, Octant::NavMesh> &E : g.navmesh_ids) {
+ for (const KeyValue<IndexKey, Octant::NavigationCell> &E : g.navigation_cell_ids) {
NavigationServer3D::get_singleton()->free(E.value.region);
- if (E.value.navmesh_debug_instance.is_valid()) {
- RS::get_singleton()->free(E.value.navmesh_debug_instance);
+ if (E.value.navigation_mesh_debug_instance.is_valid()) {
+ RS::get_singleton()->free(E.value.navigation_mesh_debug_instance);
}
}
- g.navmesh_ids.clear();
+ g.navigation_cell_ids.clear();
//erase multimeshes
@@ -648,17 +648,17 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
}
}
- // add the item's navmesh at given xform to GridMap's Navigation ancestor
- Ref<NavigationMesh> navmesh = mesh_library->get_item_navmesh(c.item);
- if (navmesh.is_valid()) {
- Octant::NavMesh nm;
- nm.xform = xform * mesh_library->get_item_navmesh_transform(c.item);
+ // add the item's navigation_mesh at given xform to GridMap's Navigation ancestor
+ Ref<NavigationMesh> navigation_mesh = mesh_library->get_item_navigation_mesh(c.item);
+ if (navigation_mesh.is_valid()) {
+ Octant::NavigationCell nm;
+ nm.xform = xform * mesh_library->get_item_navigation_mesh_transform(c.item);
if (bake_navigation) {
RID region = NavigationServer3D::get_singleton()->region_create();
NavigationServer3D::get_singleton()->region_set_owner_id(region, get_instance_id());
NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
- NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh);
+ NavigationServer3D::get_singleton()->region_set_navigation_mesh(region, navigation_mesh);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * nm.xform);
if (is_inside_tree()) {
if (map_override.is_valid()) {
@@ -673,19 +673,19 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
// add navigation debugmesh visual instances if debug is enabled
SceneTree *st = SceneTree::get_singleton();
if (st && st->is_debugging_navigation_hint()) {
- if (!nm.navmesh_debug_instance.is_valid()) {
- RID navmesh_debug_rid = navmesh->get_debug_mesh()->get_rid();
- nm.navmesh_debug_instance = RS::get_singleton()->instance_create();
- RS::get_singleton()->instance_set_base(nm.navmesh_debug_instance, navmesh_debug_rid);
+ if (!nm.navigation_mesh_debug_instance.is_valid()) {
+ RID navigation_mesh_debug_rid = navigation_mesh->get_debug_mesh()->get_rid();
+ nm.navigation_mesh_debug_instance = RS::get_singleton()->instance_create();
+ RS::get_singleton()->instance_set_base(nm.navigation_mesh_debug_instance, navigation_mesh_debug_rid);
}
if (is_inside_tree()) {
- RS::get_singleton()->instance_set_scenario(nm.navmesh_debug_instance, get_world_3d()->get_scenario());
- RS::get_singleton()->instance_set_transform(nm.navmesh_debug_instance, get_global_transform() * nm.xform);
+ RS::get_singleton()->instance_set_scenario(nm.navigation_mesh_debug_instance, get_world_3d()->get_scenario());
+ RS::get_singleton()->instance_set_transform(nm.navigation_mesh_debug_instance, get_global_transform() * nm.xform);
}
}
#endif // DEBUG_ENABLED
}
- g.navmesh_ids[E] = nm;
+ g.navigation_cell_ids[E] = nm;
}
}
@@ -775,14 +775,14 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
}
if (bake_navigation && mesh_library.is_valid()) {
- for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ for (KeyValue<IndexKey, Octant::NavigationCell> &F : g.navigation_cell_ids) {
if (cell_map.has(F.key) && F.value.region.is_valid() == false) {
- Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F.key].item);
- if (nm.is_valid()) {
+ Ref<NavigationMesh> navigation_mesh = mesh_library->get_item_navigation_mesh(cell_map[F.key].item);
+ if (navigation_mesh.is_valid()) {
RID region = NavigationServer3D::get_singleton()->region_create();
NavigationServer3D::get_singleton()->region_set_owner_id(region, get_instance_id());
NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
- NavigationServer3D::get_singleton()->region_set_navmesh(region, nm);
+ NavigationServer3D::get_singleton()->region_set_navigation_mesh(region, navigation_mesh);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F.value.xform);
if (map_override.is_valid()) {
NavigationServer3D::get_singleton()->region_set_map(region, map_override);
@@ -824,14 +824,14 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID());
}
- for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ for (KeyValue<IndexKey, Octant::NavigationCell> &F : g.navigation_cell_ids) {
if (F.value.region.is_valid()) {
NavigationServer3D::get_singleton()->free(F.value.region);
F.value.region = RID();
}
- if (F.value.navmesh_debug_instance.is_valid()) {
- RS::get_singleton()->free(F.value.navmesh_debug_instance);
- F.value.navmesh_debug_instance = RID();
+ if (F.value.navigation_mesh_debug_instance.is_valid()) {
+ RS::get_singleton()->free(F.value.navigation_mesh_debug_instance);
+ F.value.navigation_mesh_debug_instance = RID();
}
}
@@ -862,15 +862,15 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) {
PhysicsServer3D::get_singleton()->free(g.static_body);
// Erase navigation
- for (const KeyValue<IndexKey, Octant::NavMesh> &E : g.navmesh_ids) {
+ for (const KeyValue<IndexKey, Octant::NavigationCell> &E : g.navigation_cell_ids) {
if (E.value.region.is_valid()) {
NavigationServer3D::get_singleton()->free(E.value.region);
}
- if (E.value.navmesh_debug_instance.is_valid()) {
- RS::get_singleton()->free(E.value.navmesh_debug_instance);
+ if (E.value.navigation_mesh_debug_instance.is_valid()) {
+ RS::get_singleton()->free(E.value.navigation_mesh_debug_instance);
}
}
- g.navmesh_ids.clear();
+ g.navigation_cell_ids.clear();
#ifdef DEBUG_ENABLED
if (bake_navigation) {
@@ -1390,7 +1390,7 @@ void GridMap::_update_octant_navigation_debug_edge_connections_mesh(const Octant
Vector<Vector3> vertex_array;
- for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ for (KeyValue<IndexKey, Octant::NavigationCell> &F : g.navigation_cell_ids) {
if (cell_map.has(F.key) && F.value.region.is_valid()) {
int connections_count = NavigationServer3D::get_singleton()->region_get_connections_count(F.value.region);
if (connections_count == 0) {
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 6a53457d25..02a988935d 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -95,10 +95,10 @@ class GridMap : public Node3D {
* A GridMap can have multiple Octants.
*/
struct Octant {
- struct NavMesh {
+ struct NavigationCell {
RID region;
Transform3D xform;
- RID navmesh_debug_instance;
+ RID navigation_mesh_debug_instance;
};
struct MultimeshInstance {
@@ -124,7 +124,7 @@ class GridMap : public Node3D {
bool dirty = false;
RID static_body;
- HashMap<IndexKey, NavMesh> navmesh_ids;
+ HashMap<IndexKey, NavigationCell> navigation_cell_ids;
};
union OctantKey {
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index d0f52488bb..eca53c4831 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2292,7 +2292,7 @@ bool CSharpScript::can_instantiate() const {
// For tool scripts, this will never fire if the class is not found. That's because we
// don't know if it's a tool script if we can't find the class to access the attributes.
if (extra_cond && !valid) {
- ERR_FAIL_V_MSG(false, "Cannot instance script because the associated class could not be found. Script: '" + get_path() + "'.");
+ ERR_FAIL_V_MSG(false, "Cannot instance script because the associated class could not be found. Script: '" + get_path() + "'. Make sure the script exists and contains a class definition with a name that matches the filename of the script exactly (it's case-sensitive).");
}
return valid && extra_cond;
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index e5949c935b..c5c1912621 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -421,20 +421,20 @@ uint32_t GodotNavigationServer::region_get_navigation_layers(RID p_region) const
return region->get_navigation_layers();
}
-COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) {
+COMMAND_2(region_set_navigation_mesh, RID, p_region, Ref<NavigationMesh>, p_navigation_mesh) {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND(region == nullptr);
- region->set_mesh(p_nav_mesh);
+ region->set_mesh(p_navigation_mesh);
}
-void GodotNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const {
- ERR_FAIL_COND(r_mesh.is_null());
- ERR_FAIL_COND(p_node == nullptr);
+void GodotNavigationServer::region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) const {
+ ERR_FAIL_COND(p_navigation_mesh.is_null());
+ ERR_FAIL_COND(p_root_node == nullptr);
#ifndef _3D_DISABLED
- NavigationMeshGenerator::get_singleton()->clear(r_mesh);
- NavigationMeshGenerator::get_singleton()->bake(r_mesh, p_node);
+ NavigationMeshGenerator::get_singleton()->clear(p_navigation_mesh);
+ NavigationMeshGenerator::get_singleton()->bake(p_navigation_mesh, p_root_node);
#endif
}
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 18431e39b8..6f39420c67 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -135,8 +135,8 @@ public:
COMMAND_2(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers);
virtual uint32_t region_get_navigation_layers(RID p_region) const override;
COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform);
- COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh);
- virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const override;
+ COMMAND_2(region_set_navigation_mesh, RID, p_region, Ref<NavigationMesh>, p_navigation_mesh);
+ virtual void region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) const override;
virtual int region_get_connections_count(RID p_region) const override;
virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override;
virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override;
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index f0d3e329ce..74727648cb 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -470,14 +470,14 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
}
}
-void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh) {
+void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_navigation_mesh) {
Vector<Vector3> nav_vertices;
for (int i = 0; i < p_detail_mesh->nverts; i++) {
const float *v = &p_detail_mesh->verts[i * 3];
nav_vertices.push_back(Vector3(v[0], v[1], v[2]));
}
- p_nav_mesh->set_vertices(nav_vertices);
+ p_navigation_mesh->set_vertices(nav_vertices);
for (int i = 0; i < p_detail_mesh->nmeshes; i++) {
const unsigned int *m = &p_detail_mesh->meshes[i * 4];
@@ -492,13 +492,13 @@ void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(con
nav_indices.write[0] = ((int)(bverts + tris[j * 4 + 0]));
nav_indices.write[1] = ((int)(bverts + tris[j * 4 + 2]));
nav_indices.write[2] = ((int)(bverts + tris[j * 4 + 1]));
- p_nav_mesh->add_polygon(nav_indices);
+ p_navigation_mesh->add_polygon(nav_indices);
}
}
}
void NavigationMeshGenerator::_build_recast_navigation_mesh(
- Ref<NavigationMesh> p_nav_mesh,
+ Ref<NavigationMesh> p_navigation_mesh,
#ifdef TOOLS_ENABLED
EditorProgress *ep,
#endif
@@ -528,42 +528,42 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
rcConfig cfg;
memset(&cfg, 0, sizeof(cfg));
- cfg.cs = p_nav_mesh->get_cell_size();
- cfg.ch = p_nav_mesh->get_cell_height();
- cfg.walkableSlopeAngle = p_nav_mesh->get_agent_max_slope();
- cfg.walkableHeight = (int)Math::ceil(p_nav_mesh->get_agent_height() / cfg.ch);
- cfg.walkableClimb = (int)Math::floor(p_nav_mesh->get_agent_max_climb() / cfg.ch);
- cfg.walkableRadius = (int)Math::ceil(p_nav_mesh->get_agent_radius() / cfg.cs);
- cfg.maxEdgeLen = (int)(p_nav_mesh->get_edge_max_length() / p_nav_mesh->get_cell_size());
- cfg.maxSimplificationError = p_nav_mesh->get_edge_max_error();
- cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size());
- cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size());
- cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly();
- cfg.detailSampleDist = MAX(p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(), 0.1f);
- cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error();
-
- if (!Math::is_equal_approx((float)cfg.walkableHeight * cfg.ch, p_nav_mesh->get_agent_height())) {
+ cfg.cs = p_navigation_mesh->get_cell_size();
+ cfg.ch = p_navigation_mesh->get_cell_height();
+ cfg.walkableSlopeAngle = p_navigation_mesh->get_agent_max_slope();
+ cfg.walkableHeight = (int)Math::ceil(p_navigation_mesh->get_agent_height() / cfg.ch);
+ cfg.walkableClimb = (int)Math::floor(p_navigation_mesh->get_agent_max_climb() / cfg.ch);
+ cfg.walkableRadius = (int)Math::ceil(p_navigation_mesh->get_agent_radius() / cfg.cs);
+ cfg.maxEdgeLen = (int)(p_navigation_mesh->get_edge_max_length() / p_navigation_mesh->get_cell_size());
+ cfg.maxSimplificationError = p_navigation_mesh->get_edge_max_error();
+ cfg.minRegionArea = (int)(p_navigation_mesh->get_region_min_size() * p_navigation_mesh->get_region_min_size());
+ cfg.mergeRegionArea = (int)(p_navigation_mesh->get_region_merge_size() * p_navigation_mesh->get_region_merge_size());
+ cfg.maxVertsPerPoly = (int)p_navigation_mesh->get_vertices_per_polyon();
+ cfg.detailSampleDist = MAX(p_navigation_mesh->get_cell_size() * p_navigation_mesh->get_detail_sample_distance(), 0.1f);
+ cfg.detailSampleMaxError = p_navigation_mesh->get_cell_height() * p_navigation_mesh->get_detail_sample_max_error();
+
+ if (!Math::is_equal_approx((float)cfg.walkableHeight * cfg.ch, p_navigation_mesh->get_agent_height())) {
WARN_PRINT("Property agent_height is ceiled to cell_height voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.walkableClimb * cfg.ch, p_nav_mesh->get_agent_max_climb())) {
+ if (!Math::is_equal_approx((float)cfg.walkableClimb * cfg.ch, p_navigation_mesh->get_agent_max_climb())) {
WARN_PRINT("Property agent_max_climb is floored to cell_height voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.walkableRadius * cfg.cs, p_nav_mesh->get_agent_radius())) {
+ if (!Math::is_equal_approx((float)cfg.walkableRadius * cfg.cs, p_navigation_mesh->get_agent_radius())) {
WARN_PRINT("Property agent_radius is ceiled to cell_size voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.maxEdgeLen * cfg.cs, p_nav_mesh->get_edge_max_length())) {
+ if (!Math::is_equal_approx((float)cfg.maxEdgeLen * cfg.cs, p_navigation_mesh->get_edge_max_length())) {
WARN_PRINT("Property edge_max_length is rounded to cell_size voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.minRegionArea, p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size())) {
+ if (!Math::is_equal_approx((float)cfg.minRegionArea, p_navigation_mesh->get_region_min_size() * p_navigation_mesh->get_region_min_size())) {
WARN_PRINT("Property region_min_size is converted to int and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.mergeRegionArea, p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size())) {
+ if (!Math::is_equal_approx((float)cfg.mergeRegionArea, p_navigation_mesh->get_region_merge_size() * p_navigation_mesh->get_region_merge_size())) {
WARN_PRINT("Property region_merge_size is converted to int and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.maxVertsPerPoly, p_nav_mesh->get_verts_per_poly())) {
- WARN_PRINT("Property verts_per_poly is converted to int and loses precision.");
+ if (!Math::is_equal_approx((float)cfg.maxVertsPerPoly, p_navigation_mesh->get_vertices_per_polyon())) {
+ WARN_PRINT("Property vertices_per_polyon is converted to int and loses precision.");
}
- if (p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance() < 0.1f) {
+ if (p_navigation_mesh->get_cell_size() * p_navigation_mesh->get_detail_sample_distance() < 0.1f) {
WARN_PRINT("Property detail_sample_distance is clamped to 0.1 world units as the resulting value from multiplying with cell_size is too low.");
}
@@ -574,9 +574,9 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
cfg.bmax[1] = bmax[1];
cfg.bmax[2] = bmax[2];
- AABB baking_aabb = p_nav_mesh->get_filter_baking_aabb();
+ AABB baking_aabb = p_navigation_mesh->get_filter_baking_aabb();
if (baking_aabb.has_volume()) {
- Vector3 baking_aabb_offset = p_nav_mesh->get_filter_baking_aabb_offset();
+ Vector3 baking_aabb_offset = p_navigation_mesh->get_filter_baking_aabb_offset();
cfg.bmin[0] = baking_aabb.position[0] + baking_aabb_offset.x;
cfg.bmin[1] = baking_aabb.position[1] + baking_aabb_offset.y;
cfg.bmin[2] = baking_aabb.position[2] + baking_aabb_offset.z;
@@ -627,13 +627,13 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
ERR_FAIL_COND(!rcRasterizeTriangles(&ctx, verts, nverts, tris, tri_areas.ptr(), ntris, *hf, cfg.walkableClimb));
}
- if (p_nav_mesh->get_filter_low_hanging_obstacles()) {
+ if (p_navigation_mesh->get_filter_low_hanging_obstacles()) {
rcFilterLowHangingWalkableObstacles(&ctx, cfg.walkableClimb, *hf);
}
- if (p_nav_mesh->get_filter_ledge_spans()) {
+ if (p_navigation_mesh->get_filter_ledge_spans()) {
rcFilterLedgeSpans(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf);
}
- if (p_nav_mesh->get_filter_walkable_low_height_spans()) {
+ if (p_navigation_mesh->get_filter_walkable_low_height_spans()) {
rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf);
}
@@ -665,10 +665,10 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
}
#endif
- if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
+ if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf));
ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
- } else if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) {
+ } else if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) {
ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
} else {
ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, 0, cfg.minRegionArea));
@@ -710,7 +710,7 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
}
#endif
- _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_nav_mesh);
+ _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_navigation_mesh);
rcFreePolyMesh(poly_mesh);
poly_mesh = nullptr;
@@ -729,8 +729,8 @@ NavigationMeshGenerator::NavigationMeshGenerator() {
NavigationMeshGenerator::~NavigationMeshGenerator() {
}
-void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) {
- ERR_FAIL_COND_MSG(!p_nav_mesh.is_valid(), "Invalid navigation mesh.");
+void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) {
+ ERR_FAIL_COND_MSG(!p_navigation_mesh.is_valid(), "Invalid navigation mesh.");
#ifdef TOOLS_ENABLED
EditorProgress *ep(nullptr);
@@ -755,17 +755,17 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
List<Node *> parse_nodes;
- if (p_nav_mesh->get_source_geometry_mode() == NavigationMesh::SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
- parse_nodes.push_back(p_node);
+ if (p_navigation_mesh->get_source_geometry_mode() == NavigationMesh::SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) {
+ parse_nodes.push_back(p_root_node);
} else {
- p_node->get_tree()->get_nodes_in_group(p_nav_mesh->get_source_group_name(), &parse_nodes);
+ p_root_node->get_tree()->get_nodes_in_group(p_navigation_mesh->get_source_group_name(), &parse_nodes);
}
- Transform3D navmesh_xform = Object::cast_to<Node3D>(p_node)->get_global_transform().affine_inverse();
+ Transform3D navmesh_xform = Object::cast_to<Node3D>(p_root_node)->get_global_transform().affine_inverse();
for (Node *E : parse_nodes) {
- NavigationMesh::ParsedGeometryType geometry_type = p_nav_mesh->get_parsed_geometry_type();
- uint32_t collision_mask = p_nav_mesh->get_collision_mask();
- bool recurse_children = p_nav_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
+ NavigationMesh::ParsedGeometryType geometry_type = p_navigation_mesh->get_parsed_geometry_type();
+ uint32_t collision_mask = p_navigation_mesh->get_collision_mask();
+ bool recurse_children = p_navigation_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
_parse_geometry(navmesh_xform, E, vertices, indices, geometry_type, collision_mask, recurse_children);
}
@@ -777,7 +777,7 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
rcPolyMeshDetail *detail_mesh = nullptr;
_build_recast_navigation_mesh(
- p_nav_mesh,
+ p_navigation_mesh,
#ifdef TOOLS_ENABLED
ep,
#endif
@@ -816,16 +816,16 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
#endif
}
-void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_nav_mesh) {
- if (p_nav_mesh.is_valid()) {
- p_nav_mesh->clear_polygons();
- p_nav_mesh->set_vertices(Vector<Vector3>());
+void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_navigation_mesh) {
+ if (p_navigation_mesh.is_valid()) {
+ p_navigation_mesh->clear_polygons();
+ p_navigation_mesh->set_vertices(Vector<Vector3>());
}
}
void NavigationMeshGenerator::_bind_methods() {
- ClassDB::bind_method(D_METHOD("bake", "nav_mesh", "root_node"), &NavigationMeshGenerator::bake);
- ClassDB::bind_method(D_METHOD("clear", "nav_mesh"), &NavigationMeshGenerator::clear);
+ ClassDB::bind_method(D_METHOD("bake", "navigation_mesh", "root_node"), &NavigationMeshGenerator::bake);
+ ClassDB::bind_method(D_METHOD("clear", "navigation_mesh"), &NavigationMeshGenerator::clear);
}
#endif
diff --git a/modules/navigation/navigation_mesh_generator.h b/modules/navigation/navigation_mesh_generator.h
index 8cc1531b53..f6bf39d714 100644
--- a/modules/navigation/navigation_mesh_generator.h
+++ b/modules/navigation/navigation_mesh_generator.h
@@ -55,9 +55,9 @@ protected:
static void _add_faces(const PackedVector3Array &p_faces, const Transform3D &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
static void _parse_geometry(const Transform3D &p_navmesh_transform, Node *p_node, Vector<float> &p_vertices, Vector<int> &p_indices, NavigationMesh::ParsedGeometryType p_generate_from, uint32_t p_collision_mask, bool p_recurse_children);
- static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh);
+ static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_navigation_mesh);
static void _build_recast_navigation_mesh(
- Ref<NavigationMesh> p_nav_mesh,
+ Ref<NavigationMesh> p_navigation_mesh,
#ifdef TOOLS_ENABLED
EditorProgress *ep,
#endif
@@ -75,8 +75,8 @@ public:
NavigationMeshGenerator();
~NavigationMeshGenerator();
- void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node);
- void clear(Ref<NavigationMesh> p_nav_mesh);
+ void bake(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node);
+ void clear(Ref<NavigationMesh> p_navigation_mesh);
};
#endif
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 046973d193..f3e7ae9b83 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -3296,7 +3296,7 @@ void TextServerAdvanced::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
Point2 cpos = p_pos;
cpos += gl.rect.position * (double)p_size / (double)fd->msdf_source_size;
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range, (double)p_size / (double)fd->msdf_source_size);
} else {
double scale = _font_get_scale(p_font_rid, p_size);
Point2 cpos = p_pos;
@@ -3388,7 +3388,7 @@ void TextServerAdvanced::_font_draw_glyph_outline(const RID &p_font_rid, const R
Point2 cpos = p_pos;
cpos += gl.rect.position * (double)p_size / (double)fd->msdf_source_size;
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size, fd->msdf_range, (double)p_size / (double)fd->msdf_source_size);
} else {
Point2 cpos = p_pos;
double scale = _font_get_scale(p_font_rid, p_size);
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 2cee360f42..ea7b7a271b 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -2359,7 +2359,7 @@ void TextServerFallback::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
Point2 cpos = p_pos;
cpos += gl.rect.position * (double)p_size / (double)fd->msdf_source_size;
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range, (double)p_size / (double)fd->msdf_source_size);
} else {
Point2 cpos = p_pos;
double scale = _font_get_scale(p_font_rid, p_size);
@@ -2451,7 +2451,7 @@ void TextServerFallback::_font_draw_glyph_outline(const RID &p_font_rid, const R
Point2 cpos = p_pos;
cpos += gl.rect.position * (double)p_size / (double)fd->msdf_source_size;
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size, fd->msdf_range, (double)p_size / (double)fd->msdf_source_size);
} else {
Point2 cpos = p_pos;
double scale = _font_get_scale(p_font_rid, p_size);
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index 23b70fbc28..3f4a406116 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -227,27 +227,23 @@ void DisplayServerIOS::_window_callback(const Callable &p_callable, const Varian
// MARK: Touches
void DisplayServerIOS::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) {
- if (!GLOBAL_GET("debug/disable_touch")) {
- Ref<InputEventScreenTouch> ev;
- ev.instantiate();
-
- ev->set_index(p_idx);
- ev->set_pressed(p_pressed);
- ev->set_position(Vector2(p_x, p_y));
- ev->set_double_tap(p_double_click);
- perform_event(ev);
- }
+ Ref<InputEventScreenTouch> ev;
+ ev.instantiate();
+
+ ev->set_index(p_idx);
+ ev->set_pressed(p_pressed);
+ ev->set_position(Vector2(p_x, p_y));
+ ev->set_double_tap(p_double_click);
+ perform_event(ev);
}
void DisplayServerIOS::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) {
- if (!GLOBAL_GET("debug/disable_touch")) {
- Ref<InputEventScreenDrag> ev;
- ev.instantiate();
- ev->set_index(p_idx);
- ev->set_position(Vector2(p_x, p_y));
- ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
- perform_event(ev);
- }
+ Ref<InputEventScreenDrag> ev;
+ ev.instantiate();
+ ev->set_index(p_idx);
+ ev->set_position(Vector2(p_x, p_y));
+ ev->set_relative(Vector2(p_x - p_prev_x, p_y - p_prev_y));
+ perform_event(ev);
}
void DisplayServerIOS::perform_event(const Ref<InputEvent> &p_event) {
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index f04177d79a..89f56ffd93 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -226,7 +226,7 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/modify_resources"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/console_wrapper_icon", PROPERTY_HINT_FILE, "*.ico.*.png,*.webp,*.svg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/console_wrapper_icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), ""));
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 904b6564bd..67c32dffb4 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -79,8 +79,8 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent2D::get_next_location);
ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent2D::distance_to_target);
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent2D::set_velocity);
- ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent2D::get_nav_path);
- ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent2D::get_nav_path_index);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_path"), &NavigationAgent2D::get_current_navigation_path);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_path_index"), &NavigationAgent2D::get_current_navigation_path_index);
ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent2D::is_target_reached);
ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent2D::is_target_reachable);
ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent2D::is_navigation_finished);
@@ -329,11 +329,11 @@ Vector2 NavigationAgent2D::get_next_location() {
ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector2(), "The agent has no parent.");
return agent_parent->get_global_position();
} else {
- return navigation_path[nav_path_index];
+ return navigation_path[navigation_path_index];
}
}
-const Vector<Vector2> &NavigationAgent2D::get_nav_path() const {
+const Vector<Vector2> &NavigationAgent2D::get_current_navigation_path() const {
return navigation_result->get_path();
}
@@ -418,12 +418,12 @@ void NavigationAgent2D::update_navigation() {
reload_path = true;
} else {
// Check if too far from the navigation path
- if (nav_path_index > 0) {
+ if (navigation_path_index > 0) {
const Vector<Vector2> &navigation_path = navigation_result->get_path();
Vector2 segment[2];
- segment[0] = navigation_path[nav_path_index - 1];
- segment[1] = navigation_path[nav_path_index];
+ segment[0] = navigation_path[navigation_path_index - 1];
+ segment[1] = navigation_path[navigation_path_index];
Vector2 p = Geometry2D::get_closest_point_to_segment(origin, segment);
if (origin.distance_to(p) >= path_max_distance) {
// To faraway, reload path
@@ -445,7 +445,7 @@ void NavigationAgent2D::update_navigation() {
NavigationServer2D::get_singleton()->query_path(navigation_query, navigation_result);
navigation_finished = false;
- nav_path_index = 0;
+ navigation_path_index = 0;
emit_signal(SNAME("path_changed"));
}
@@ -457,11 +457,11 @@ void NavigationAgent2D::update_navigation() {
if (navigation_finished == false) {
// Advances to the next far away location.
const Vector<Vector2> &navigation_path = navigation_result->get_path();
- while (origin.distance_to(navigation_path[nav_path_index]) < path_desired_distance) {
- nav_path_index += 1;
- if (nav_path_index == navigation_path.size()) {
+ while (origin.distance_to(navigation_path[navigation_path_index]) < path_desired_distance) {
+ navigation_path_index += 1;
+ if (navigation_path_index == navigation_path.size()) {
_check_distance_to_target();
- nav_path_index -= 1;
+ navigation_path_index -= 1;
navigation_finished = true;
emit_signal(SNAME("navigation_finished"));
break;
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index 5abd3c0317..2c77bdc8db 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -62,7 +62,7 @@ class NavigationAgent2D : public Node {
Vector2 target_location;
Ref<NavigationPathQueryParameters2D> navigation_query;
Ref<NavigationPathQueryResult2D> navigation_result;
- int nav_path_index = 0;
+ int navigation_path_index = 0;
bool velocity_submitted = false;
Vector2 prev_safe_velocity;
/// The submitted target velocity
@@ -141,10 +141,10 @@ public:
Vector2 get_next_location();
- const Vector<Vector2> &get_nav_path() const;
+ const Vector<Vector2> &get_current_navigation_path() const;
- int get_nav_path_index() const {
- return nav_path_index;
+ int get_current_navigation_path_index() const {
+ return navigation_path_index;
}
real_t distance_to_target() const;
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 7bf3eec79b..e030628110 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -31,333 +31,10 @@
#include "navigation_region_2d.h"
#include "core/core_string_names.h"
-#include "core/math/geometry_2d.h"
-#include "core/os/mutex.h"
#include "scene/resources/world_2d.h"
#include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h"
-#include "thirdparty/misc/polypartition.h"
-
-#ifdef TOOLS_ENABLED
-Rect2 NavigationPolygon::_edit_get_rect() const {
- if (rect_cache_dirty) {
- item_rect = Rect2();
- bool first = true;
-
- for (int i = 0; i < outlines.size(); i++) {
- const Vector<Vector2> &outline = outlines[i];
- const int outline_size = outline.size();
- if (outline_size < 3) {
- continue;
- }
- const Vector2 *p = outline.ptr();
- for (int j = 0; j < outline_size; j++) {
- if (first) {
- item_rect = Rect2(p[j], Vector2(0, 0));
- first = false;
- } else {
- item_rect.expand_to(p[j]);
- }
- }
- }
-
- rect_cache_dirty = false;
- }
- return item_rect;
-}
-
-bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
- for (int i = 0; i < outlines.size(); i++) {
- const Vector<Vector2> &outline = outlines[i];
- const int outline_size = outline.size();
- if (outline_size < 3) {
- continue;
- }
- if (Geometry2D::is_point_in_polygon(p_point, Variant(outline))) {
- return true;
- }
- }
- return false;
-}
-#endif
-
-void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) {
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
- vertices = p_vertices;
- rect_cache_dirty = true;
-}
-
-Vector<Vector2> NavigationPolygon::get_vertices() const {
- return vertices;
-}
-
-void NavigationPolygon::_set_polygons(const TypedArray<Vector<int32_t>> &p_array) {
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
- polygons.resize(p_array.size());
- for (int i = 0; i < p_array.size(); i++) {
- polygons.write[i].indices = p_array[i];
- }
-}
-
-TypedArray<Vector<int32_t>> NavigationPolygon::_get_polygons() const {
- TypedArray<Vector<int32_t>> ret;
- ret.resize(polygons.size());
- for (int i = 0; i < ret.size(); i++) {
- ret[i] = polygons[i].indices;
- }
-
- return ret;
-}
-
-void NavigationPolygon::_set_outlines(const TypedArray<Vector<Vector2>> &p_array) {
- outlines.resize(p_array.size());
- for (int i = 0; i < p_array.size(); i++) {
- outlines.write[i] = p_array[i];
- }
- rect_cache_dirty = true;
-}
-
-TypedArray<Vector<Vector2>> NavigationPolygon::_get_outlines() const {
- TypedArray<Vector<Vector2>> ret;
- ret.resize(outlines.size());
- for (int i = 0; i < ret.size(); i++) {
- ret[i] = outlines[i];
- }
-
- return ret;
-}
-
-void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {
- Polygon polygon;
- polygon.indices = p_polygon;
- polygons.push_back(polygon);
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
-}
-
-void NavigationPolygon::add_outline_at_index(const Vector<Vector2> &p_outline, int p_index) {
- outlines.insert(p_index, p_outline);
- rect_cache_dirty = true;
-}
-
-int NavigationPolygon::get_polygon_count() const {
- return polygons.size();
-}
-
-Vector<int> NavigationPolygon::get_polygon(int p_idx) {
- ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>());
- return polygons[p_idx].indices;
-}
-
-void NavigationPolygon::clear_polygons() {
- polygons.clear();
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
-}
-
-Ref<NavigationMesh> NavigationPolygon::get_mesh() {
- MutexLock lock(navmesh_generation);
-
- if (navmesh.is_null()) {
- navmesh.instantiate();
- Vector<Vector3> verts;
- {
- verts.resize(get_vertices().size());
- Vector3 *w = verts.ptrw();
-
- const Vector2 *r = get_vertices().ptr();
-
- for (int i(0); i < get_vertices().size(); i++) {
- w[i] = Vector3(r[i].x, 0.0, r[i].y);
- }
- }
- navmesh->set_vertices(verts);
-
- for (int i(0); i < get_polygon_count(); i++) {
- navmesh->add_polygon(get_polygon(i));
- }
- }
-
- return navmesh;
-}
-
-void NavigationPolygon::add_outline(const Vector<Vector2> &p_outline) {
- outlines.push_back(p_outline);
- rect_cache_dirty = true;
-}
-
-int NavigationPolygon::get_outline_count() const {
- return outlines.size();
-}
-
-void NavigationPolygon::set_outline(int p_idx, const Vector<Vector2> &p_outline) {
- ERR_FAIL_INDEX(p_idx, outlines.size());
- outlines.write[p_idx] = p_outline;
- rect_cache_dirty = true;
-}
-
-void NavigationPolygon::remove_outline(int p_idx) {
- ERR_FAIL_INDEX(p_idx, outlines.size());
- outlines.remove_at(p_idx);
- rect_cache_dirty = true;
-}
-
-Vector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, outlines.size(), Vector<Vector2>());
- return outlines[p_idx];
-}
-
-void NavigationPolygon::clear_outlines() {
- outlines.clear();
- rect_cache_dirty = true;
-}
-
-void NavigationPolygon::make_polygons_from_outlines() {
- {
- MutexLock lock(navmesh_generation);
- navmesh.unref();
- }
- List<TPPLPoly> in_poly, out_poly;
-
- Vector2 outside_point(-1e10, -1e10);
-
- for (int i = 0; i < outlines.size(); i++) {
- Vector<Vector2> ol = outlines[i];
- int olsize = ol.size();
- if (olsize < 3) {
- continue;
- }
- const Vector2 *r = ol.ptr();
- for (int j = 0; j < olsize; j++) {
- outside_point.x = MAX(r[j].x, outside_point.x);
- outside_point.y = MAX(r[j].y, outside_point.y);
- }
- }
-
- outside_point += Vector2(0.7239784, 0.819238); //avoid precision issues
-
- for (int i = 0; i < outlines.size(); i++) {
- Vector<Vector2> ol = outlines[i];
- int olsize = ol.size();
- if (olsize < 3) {
- continue;
- }
- const Vector2 *r = ol.ptr();
-
- int interscount = 0;
- //test if this is an outer outline
- for (int k = 0; k < outlines.size(); k++) {
- if (i == k) {
- continue; //no self intersect
- }
-
- Vector<Vector2> ol2 = outlines[k];
- int olsize2 = ol2.size();
- if (olsize2 < 3) {
- continue;
- }
- const Vector2 *r2 = ol2.ptr();
-
- for (int l = 0; l < olsize2; l++) {
- if (Geometry2D::segment_intersects_segment(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], nullptr)) {
- interscount++;
- }
- }
- }
-
- bool outer = (interscount % 2) == 0;
-
- TPPLPoly tp;
- tp.Init(olsize);
- for (int j = 0; j < olsize; j++) {
- tp[j] = r[j];
- }
-
- if (outer) {
- tp.SetOrientation(TPPL_ORIENTATION_CCW);
- } else {
- tp.SetOrientation(TPPL_ORIENTATION_CW);
- tp.SetHole(true);
- }
-
- in_poly.push_back(tp);
- }
-
- TPPLPartition tpart;
- if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
- ERR_PRINT("NavigationPolygon: Convex partition failed! Failed to convert outlines to a valid NavigationMesh."
- "\nNavigationPolygon outlines can not overlap vertices or edges inside same outline or with other outlines or have any intersections."
- "\nAdd the outmost and largest outline first. To add holes inside this outline add the smaller outlines with opposite winding order.");
- return;
- }
-
- polygons.clear();
- vertices.clear();
-
- HashMap<Vector2, int> points;
- for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
- TPPLPoly &tp = I->get();
-
- struct Polygon p;
-
- for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
- HashMap<Vector2, int>::Iterator E = points.find(tp[i]);
- if (!E) {
- E = points.insert(tp[i], vertices.size());
- vertices.push_back(tp[i]);
- }
- p.indices.push_back(E->value);
- }
-
- polygons.push_back(p);
- }
-
- emit_signal(CoreStringNames::get_singleton()->changed);
-}
-
-void NavigationPolygon::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationPolygon::set_vertices);
- ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationPolygon::get_vertices);
-
- ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationPolygon::add_polygon);
- ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationPolygon::get_polygon_count);
- ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationPolygon::get_polygon);
- ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationPolygon::clear_polygons);
- ClassDB::bind_method(D_METHOD("get_mesh"), &NavigationPolygon::get_mesh);
-
- ClassDB::bind_method(D_METHOD("add_outline", "outline"), &NavigationPolygon::add_outline);
- ClassDB::bind_method(D_METHOD("add_outline_at_index", "outline", "index"), &NavigationPolygon::add_outline_at_index);
- ClassDB::bind_method(D_METHOD("get_outline_count"), &NavigationPolygon::get_outline_count);
- ClassDB::bind_method(D_METHOD("set_outline", "idx", "outline"), &NavigationPolygon::set_outline);
- ClassDB::bind_method(D_METHOD("get_outline", "idx"), &NavigationPolygon::get_outline);
- ClassDB::bind_method(D_METHOD("remove_outline", "idx"), &NavigationPolygon::remove_outline);
- ClassDB::bind_method(D_METHOD("clear_outlines"), &NavigationPolygon::clear_outlines);
- ClassDB::bind_method(D_METHOD("make_polygons_from_outlines"), &NavigationPolygon::make_polygons_from_outlines);
-
- ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationPolygon::_set_polygons);
- ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationPolygon::_get_polygons);
-
- ClassDB::bind_method(D_METHOD("_set_outlines", "outlines"), &NavigationPolygon::_set_outlines);
- ClassDB::bind_method(D_METHOD("_get_outlines"), &NavigationPolygon::_get_outlines);
-
- ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");
-}
-
-/////////////////////////////
-
void NavigationRegion2D::set_enabled(bool p_enabled) {
if (enabled == p_enabled) {
return;
@@ -460,11 +137,11 @@ RID NavigationRegion2D::get_region_rid() const {
#ifdef TOOLS_ENABLED
Rect2 NavigationRegion2D::_edit_get_rect() const {
- return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2();
+ return navigation_polygon.is_valid() ? navigation_polygon->_edit_get_rect() : Rect2();
}
bool NavigationRegion2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
- return navpoly.is_valid() ? navpoly->_edit_is_selected_on_click(p_point, p_tolerance) : false;
+ return navigation_polygon.is_valid() ? navigation_polygon->_edit_is_selected_on_click(p_point, p_tolerance) : false;
}
#endif
@@ -490,8 +167,8 @@ void NavigationRegion2D::_notification(int p_what) {
case NOTIFICATION_DRAW: {
#ifdef DEBUG_ENABLED
- if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer3D::get_singleton()->get_debug_enabled()) && navpoly.is_valid()) {
- Vector<Vector2> verts = navpoly->get_vertices();
+ if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer3D::get_singleton()->get_debug_enabled()) && navigation_polygon.is_valid()) {
+ Vector<Vector2> verts = navigation_polygon->get_vertices();
if (verts.size() < 3) {
return;
}
@@ -506,9 +183,9 @@ void NavigationRegion2D::_notification(int p_what) {
RandomPCG rand;
- for (int i = 0; i < navpoly->get_polygon_count(); i++) {
+ for (int i = 0; i < navigation_polygon->get_polygon_count(); i++) {
// An array of vertices for this polygon.
- Vector<int> polygon = navpoly->get_polygon(i);
+ Vector<int> polygon = navigation_polygon->get_polygon(i);
Vector<Vector2> vertices;
vertices.resize(polygon.size());
for (int j = 0; j < polygon.size(); j++) {
@@ -549,36 +226,36 @@ void NavigationRegion2D::_notification(int p_what) {
}
}
-void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly) {
- if (p_navpoly == navpoly) {
+void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_navigation_polygon) {
+ if (p_navigation_polygon == navigation_polygon) {
return;
}
- if (navpoly.is_valid()) {
- navpoly->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navpoly_changed));
+ if (navigation_polygon.is_valid()) {
+ navigation_polygon->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navigation_polygon_changed));
}
- navpoly = p_navpoly;
- NavigationServer2D::get_singleton()->region_set_navpoly(region, p_navpoly);
+ navigation_polygon = p_navigation_polygon;
+ NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, p_navigation_polygon);
- if (navpoly.is_valid()) {
- navpoly->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navpoly_changed));
+ if (navigation_polygon.is_valid()) {
+ navigation_polygon->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navigation_polygon_changed));
}
- _navpoly_changed();
+ _navigation_polygon_changed();
update_configuration_warnings();
}
Ref<NavigationPolygon> NavigationRegion2D::get_navigation_polygon() const {
- return navpoly;
+ return navigation_polygon;
}
-void NavigationRegion2D::_navpoly_changed() {
+void NavigationRegion2D::_navigation_polygon_changed() {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) {
queue_redraw();
}
- if (navpoly.is_valid()) {
- NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
+ if (navigation_polygon.is_valid()) {
+ NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, navigation_polygon);
}
}
@@ -594,7 +271,7 @@ PackedStringArray NavigationRegion2D::get_configuration_warnings() const {
PackedStringArray warnings = Node2D::get_configuration_warnings();
if (is_visible_in_tree() && is_inside_tree()) {
- if (!navpoly.is_valid()) {
+ if (!navigation_polygon.is_valid()) {
warnings.push_back(RTR("A NavigationMesh resource must be set or created for this node to work. Please set a property or draw a polygon."));
}
}
@@ -603,7 +280,7 @@ PackedStringArray NavigationRegion2D::get_configuration_warnings() const {
}
void NavigationRegion2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navpoly"), &NavigationRegion2D::set_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navigation_polygon"), &NavigationRegion2D::set_navigation_polygon);
ClassDB::bind_method(D_METHOD("get_navigation_polygon"), &NavigationRegion2D::get_navigation_polygon);
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled);
@@ -623,9 +300,9 @@ void NavigationRegion2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationRegion2D::set_travel_cost);
ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationRegion2D::get_travel_cost);
- ClassDB::bind_method(D_METHOD("_navpoly_changed"), &NavigationRegion2D::_navpoly_changed);
+ ClassDB::bind_method(D_METHOD("_navigation_polygon_changed"), &NavigationRegion2D::_navigation_polygon_changed);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navpoly", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_polygon", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h
index c630e20780..216e6088bc 100644
--- a/scene/2d/navigation_region_2d.h
+++ b/scene/2d/navigation_region_2d.h
@@ -31,65 +31,7 @@
#ifndef NAVIGATION_REGION_2D_H
#define NAVIGATION_REGION_2D_H
-#include "scene/2d/node_2d.h"
-#include "scene/resources/navigation_mesh.h"
-
-class NavigationPolygon : public Resource {
- GDCLASS(NavigationPolygon, Resource);
-
- Vector<Vector2> vertices;
- struct Polygon {
- Vector<int> indices;
- };
- Vector<Polygon> polygons;
- Vector<Vector<Vector2>> outlines;
-
- mutable Rect2 item_rect;
- mutable bool rect_cache_dirty = true;
-
- Mutex navmesh_generation;
- // Navigation mesh
- Ref<NavigationMesh> navmesh;
-
-protected:
- static void _bind_methods();
-
- void _set_polygons(const TypedArray<Vector<int32_t>> &p_array);
- TypedArray<Vector<int32_t>> _get_polygons() const;
-
- void _set_outlines(const TypedArray<Vector<Vector2>> &p_array);
- TypedArray<Vector<Vector2>> _get_outlines() const;
-
-public:
-#ifdef TOOLS_ENABLED
- Rect2 _edit_get_rect() const;
- bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
-#endif
-
- void set_vertices(const Vector<Vector2> &p_vertices);
- Vector<Vector2> get_vertices() const;
-
- void add_polygon(const Vector<int> &p_polygon);
- int get_polygon_count() const;
-
- void add_outline(const Vector<Vector2> &p_outline);
- void add_outline_at_index(const Vector<Vector2> &p_outline, int p_index);
- void set_outline(int p_idx, const Vector<Vector2> &p_outline);
- Vector<Vector2> get_outline(int p_idx) const;
- void remove_outline(int p_idx);
- int get_outline_count() const;
-
- void clear_outlines();
- void make_polygons_from_outlines();
-
- Vector<int> get_polygon(int p_idx);
- void clear_polygons();
-
- Ref<NavigationMesh> get_mesh();
-
- NavigationPolygon() {}
- ~NavigationPolygon() {}
-};
+#include "scene/resources/navigation_polygon.h"
class NavigationRegion2D : public Node2D {
GDCLASS(NavigationRegion2D, Node2D);
@@ -99,9 +41,9 @@ class NavigationRegion2D : public Node2D {
uint32_t navigation_layers = 1;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
- Ref<NavigationPolygon> navpoly;
+ Ref<NavigationPolygon> navigation_polygon;
- void _navpoly_changed();
+ void _navigation_polygon_changed();
void _map_changed(RID p_RID);
protected:
@@ -131,7 +73,7 @@ public:
void set_travel_cost(real_t p_travel_cost);
real_t get_travel_cost() const;
- void set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly);
+ void set_navigation_polygon(const Ref<NavigationPolygon> &p_navigation_polygon);
Ref<NavigationPolygon> get_navigation_polygon() const;
PackedStringArray get_configuration_warnings() const override;
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 4788a1b813..166bc26848 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -149,6 +149,10 @@ void Node2D::set_rotation(real_t p_radians) {
_update_transform();
}
+void Node2D::set_rotation_degrees(real_t p_degrees) {
+ set_rotation(Math::deg_to_rad(p_degrees));
+}
+
void Node2D::set_skew(real_t p_radians) {
if (_xform_dirty) {
const_cast<Node2D *>(this)->_update_xform_values();
@@ -187,6 +191,10 @@ real_t Node2D::get_rotation() const {
return rotation;
}
+real_t Node2D::get_rotation_degrees() const {
+ return Math::rad_to_deg(get_rotation());
+}
+
real_t Node2D::get_skew() const {
if (_xform_dirty) {
const_cast<Node2D *>(this)->_update_xform_values();
@@ -259,6 +267,10 @@ real_t Node2D::get_global_rotation() const {
return get_global_transform().get_rotation();
}
+real_t Node2D::get_global_rotation_degrees() const {
+ return Math::rad_to_deg(get_global_rotation());
+}
+
real_t Node2D::get_global_skew() const {
return get_global_transform().get_skew();
}
@@ -276,6 +288,10 @@ void Node2D::set_global_rotation(const real_t p_radians) {
}
}
+void Node2D::set_global_rotation_degrees(const real_t p_degrees) {
+ set_global_rotation(Math::deg_to_rad(p_degrees));
+}
+
void Node2D::set_global_skew(const real_t p_radians) {
CanvasItem *parent = get_parent_item();
if (parent) {
@@ -372,11 +388,13 @@ void Node2D::_notification(int p_notification) {
void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_position", "position"), &Node2D::set_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Node2D::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Node2D::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_skew", "radians"), &Node2D::set_skew);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Node2D::set_scale);
ClassDB::bind_method(D_METHOD("get_position"), &Node2D::get_position);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node2D::get_rotation);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node2D::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_skew"), &Node2D::get_skew);
ClassDB::bind_method(D_METHOD("get_scale"), &Node2D::get_scale);
@@ -390,7 +408,9 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_global_position", "position"), &Node2D::set_global_position);
ClassDB::bind_method(D_METHOD("get_global_position"), &Node2D::get_global_position);
ClassDB::bind_method(D_METHOD("set_global_rotation", "radians"), &Node2D::set_global_rotation);
+ ClassDB::bind_method(D_METHOD("set_global_rotation_degrees", "degrees"), &Node2D::set_global_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_global_rotation"), &Node2D::get_global_rotation);
+ ClassDB::bind_method(D_METHOD("get_global_rotation_degrees"), &Node2D::get_global_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_global_skew", "radians"), &Node2D::set_global_skew);
ClassDB::bind_method(D_METHOD("get_global_skew"), &Node2D::get_global_skew);
ClassDB::bind_method(D_METHOD("set_global_scale", "scale"), &Node2D::set_global_scale);
@@ -410,12 +430,14 @@ void Node2D::_bind_methods() {
ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_less,or_greater,hide_slider,suffix:px"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians"), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale", PROPERTY_HINT_LINK), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_rotation", PROPERTY_HINT_NONE, "radians", PROPERTY_USAGE_NONE), "set_global_rotation", "get_global_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_rotation_degrees", "get_global_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_scale", "get_global_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "global_skew", PROPERTY_HINT_NONE, "radians", PROPERTY_USAGE_NONE), "set_global_skew", "get_global_skew");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 76707dc422..b066332dcb 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -73,6 +73,7 @@ public:
void set_position(const Point2 &p_pos);
void set_rotation(real_t p_radians);
+ void set_rotation_degrees(real_t p_degrees);
void set_skew(real_t p_radians);
void set_scale(const Size2 &p_scale);
@@ -85,11 +86,13 @@ public:
Point2 get_position() const;
real_t get_rotation() const;
+ real_t get_rotation_degrees() const;
real_t get_skew() const;
Size2 get_scale() const;
Point2 get_global_position() const;
real_t get_global_rotation() const;
+ real_t get_global_rotation_degrees() const;
real_t get_global_skew() const;
Size2 get_global_scale() const;
@@ -97,6 +100,7 @@ public:
void set_global_transform(const Transform2D &p_transform);
void set_global_position(const Point2 &p_pos);
void set_global_rotation(const real_t p_radians);
+ void set_global_rotation_degrees(const real_t p_degrees);
void set_global_skew(const real_t p_radians);
void set_global_scale(const Size2 &p_scale);
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 842b614032..6ab13c9aa7 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -1092,7 +1092,7 @@ void TileMap::_rendering_update_layer(int p_layer) {
/*Transform2D xform;
xform.set_origin(Vector2(0, p_layer));
rs->canvas_item_set_transform(ci, xform);*/
- rs->canvas_item_set_draw_index(ci, p_layer);
+ rs->canvas_item_set_draw_index(ci, p_layer - (int64_t)0x80000000);
layers[p_layer].canvas_item = ci;
}
@@ -1728,10 +1728,10 @@ void TileMap::_navigation_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
q.navigation_regions[E_cell].resize(tile_set->get_navigation_layers_count());
for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) {
- Ref<NavigationPolygon> navpoly;
- navpoly = tile_data->get_navigation_polygon(layer_index);
+ Ref<NavigationPolygon> navigation_polygon;
+ navigation_polygon = tile_data->get_navigation_polygon(layer_index);
- if (navpoly.is_valid()) {
+ if (navigation_polygon.is_valid()) {
Transform2D tile_transform;
tile_transform.set_origin(map_to_local(E_cell));
@@ -1739,7 +1739,7 @@ void TileMap::_navigation_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
NavigationServer2D::get_singleton()->region_set_owner_id(region, get_instance_id());
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform);
- NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
+ NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, navigation_polygon);
q.navigation_regions[E_cell].write[layer_index] = region;
}
}
@@ -3904,35 +3904,26 @@ void TileMap::draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_ce
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 2, 3);
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 3, 0);
DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 0, 1);
+ } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 3, 0);
} else {
if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
- } else {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
- }
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
} else {
- if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
- } else {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
- }
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
}
}
}
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index e907b9f66f..08ceb946df 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -83,8 +83,8 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent3D::get_next_location);
ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent3D::distance_to_target);
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent3D::set_velocity);
- ClassDB::bind_method(D_METHOD("get_nav_path"), &NavigationAgent3D::get_nav_path);
- ClassDB::bind_method(D_METHOD("get_nav_path_index"), &NavigationAgent3D::get_nav_path_index);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_path"), &NavigationAgent3D::get_current_navigation_path);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_path_index"), &NavigationAgent3D::get_current_navigation_path_index);
ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent3D::is_target_reached);
ClassDB::bind_method(D_METHOD("is_target_reachable"), &NavigationAgent3D::is_target_reachable);
ClassDB::bind_method(D_METHOD("is_navigation_finished"), &NavigationAgent3D::is_navigation_finished);
@@ -345,11 +345,11 @@ Vector3 NavigationAgent3D::get_next_location() {
ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector3(), "The agent has no parent.");
return agent_parent->get_global_transform().origin;
} else {
- return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0);
+ return navigation_path[navigation_path_index] - Vector3(0, navigation_height_offset, 0);
}
}
-const Vector<Vector3> &NavigationAgent3D::get_nav_path() const {
+const Vector<Vector3> &NavigationAgent3D::get_current_navigation_path() const {
return navigation_result->get_path();
}
@@ -433,12 +433,12 @@ void NavigationAgent3D::update_navigation() {
reload_path = true;
} else {
// Check if too far from the navigation path
- if (nav_path_index > 0) {
+ if (navigation_path_index > 0) {
const Vector<Vector3> &navigation_path = navigation_result->get_path();
Vector3 segment[2];
- segment[0] = navigation_path[nav_path_index - 1];
- segment[1] = navigation_path[nav_path_index];
+ segment[0] = navigation_path[navigation_path_index - 1];
+ segment[1] = navigation_path[navigation_path_index];
segment[0].y -= navigation_height_offset;
segment[1].y -= navigation_height_offset;
Vector3 p = Geometry3D::get_closest_point_to_segment(origin, segment);
@@ -462,7 +462,7 @@ void NavigationAgent3D::update_navigation() {
NavigationServer3D::get_singleton()->query_path(navigation_query, navigation_result);
navigation_finished = false;
- nav_path_index = 0;
+ navigation_path_index = 0;
emit_signal(SNAME("path_changed"));
}
@@ -474,11 +474,11 @@ void NavigationAgent3D::update_navigation() {
if (navigation_finished == false) {
// Advances to the next far away location.
const Vector<Vector3> &navigation_path = navigation_result->get_path();
- while (origin.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < path_desired_distance) {
- nav_path_index += 1;
- if (nav_path_index == navigation_path.size()) {
+ while (origin.distance_to(navigation_path[navigation_path_index] - Vector3(0, navigation_height_offset, 0)) < path_desired_distance) {
+ navigation_path_index += 1;
+ if (navigation_path_index == navigation_path.size()) {
_check_distance_to_target();
- nav_path_index -= 1;
+ navigation_path_index -= 1;
navigation_finished = true;
emit_signal(SNAME("navigation_finished"));
break;
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index 90ceab0242..1caa783a8b 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -64,7 +64,7 @@ class NavigationAgent3D : public Node {
Vector3 target_location;
Ref<NavigationPathQueryParameters3D> navigation_query;
Ref<NavigationPathQueryResult3D> navigation_result;
- int nav_path_index = 0;
+ int navigation_path_index = 0;
bool velocity_submitted = false;
Vector3 prev_safe_velocity;
/// The submitted target velocity
@@ -153,10 +153,10 @@ public:
Vector3 get_next_location();
- const Vector<Vector3> &get_nav_path() const;
+ const Vector<Vector3> &get_current_navigation_path() const;
- int get_nav_path_index() const {
- return nav_path_index;
+ int get_current_navigation_path_index() const {
+ return navigation_path_index;
}
real_t distance_to_target() const;
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index bd96c55512..520bf0a1aa 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -192,26 +192,26 @@ void NavigationRegion3D::_notification(int p_what) {
}
}
-void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh) {
- if (p_navmesh == navmesh) {
+void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navigation_mesh) {
+ if (p_navigation_mesh == navigation_mesh) {
return;
}
- if (navmesh.is_valid()) {
- navmesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
+ if (navigation_mesh.is_valid()) {
+ navigation_mesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
- navmesh = p_navmesh;
+ navigation_mesh = p_navigation_mesh;
- if (navmesh.is_valid()) {
- navmesh->connect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
+ if (navigation_mesh.is_valid()) {
+ navigation_mesh->connect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
- NavigationServer3D::get_singleton()->region_set_navmesh(region, p_navmesh);
+ NavigationServer3D::get_singleton()->region_set_navigation_mesh(region, p_navigation_mesh);
#ifdef DEBUG_ENABLED
if (is_inside_tree() && NavigationServer3D::get_singleton()->get_debug_enabled()) {
- if (navmesh.is_valid()) {
+ if (navigation_mesh.is_valid()) {
_update_debug_mesh();
_update_debug_edge_connections_mesh();
} else {
@@ -232,7 +232,7 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
}
Ref<NavigationMesh> NavigationRegion3D::get_navigation_mesh() const {
- return navmesh;
+ return navigation_mesh;
}
struct BakeThreadsArgs {
@@ -245,7 +245,7 @@ void _bake_navigation_mesh(void *p_user_data) {
if (args->nav_region->get_navigation_mesh().is_valid()) {
Ref<NavigationMesh> nav_mesh = args->nav_region->get_navigation_mesh()->duplicate();
- NavigationServer3D::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_region);
+ NavigationServer3D::get_singleton()->region_bake_navigation_mesh(nav_mesh, args->nav_region);
args->nav_region->call_deferred(SNAME("_bake_finished"), nav_mesh);
memdelete(args);
} else {
@@ -278,7 +278,7 @@ PackedStringArray NavigationRegion3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
if (is_visible_in_tree() && is_inside_tree()) {
- if (!navmesh.is_valid()) {
+ if (!navigation_mesh.is_valid()) {
warnings.push_back(RTR("A NavigationMesh resource must be set or created for this node to work."));
}
}
@@ -287,7 +287,7 @@ PackedStringArray NavigationRegion3D::get_configuration_warnings() const {
}
void NavigationRegion3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationRegion3D::set_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navigation_mesh"), &NavigationRegion3D::set_navigation_mesh);
ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationRegion3D::get_navigation_mesh);
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion3D::set_enabled);
@@ -308,9 +308,9 @@ void NavigationRegion3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationRegion3D::get_travel_cost);
ClassDB::bind_method(D_METHOD("bake_navigation_mesh", "on_thread"), &NavigationRegion3D::bake_navigation_mesh, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationRegion3D::_bake_finished);
+ ClassDB::bind_method(D_METHOD("_bake_finished", "navigation_mesh"), &NavigationRegion3D::_bake_finished);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_mesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
@@ -353,8 +353,8 @@ NavigationRegion3D::NavigationRegion3D() {
}
NavigationRegion3D::~NavigationRegion3D() {
- if (navmesh.is_valid()) {
- navmesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
+ if (navigation_mesh.is_valid()) {
+ navigation_mesh->disconnect("changed", callable_mp(this, &NavigationRegion3D::_navigation_changed));
}
NavigationServer3D::get_singleton()->free(region);
@@ -392,7 +392,7 @@ void NavigationRegion3D::_update_debug_mesh() {
return;
}
- if (!navmesh.is_valid()) {
+ if (!navigation_mesh.is_valid()) {
if (debug_instance.is_valid()) {
RS::get_singleton()->instance_set_visible(debug_instance, false);
}
@@ -412,12 +412,12 @@ void NavigationRegion3D::_update_debug_mesh() {
bool enabled_geometry_face_random_color = NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color();
bool enabled_edge_lines = NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines();
- Vector<Vector3> vertices = navmesh->get_vertices();
+ Vector<Vector3> vertices = navigation_mesh->get_vertices();
if (vertices.size() == 0) {
return;
}
- int polygon_count = navmesh->get_polygon_count();
+ int polygon_count = navigation_mesh->get_polygon_count();
if (polygon_count == 0) {
return;
}
@@ -450,7 +450,7 @@ void NavigationRegion3D::_update_debug_mesh() {
polygon_color.a = debug_navigation_geometry_face_color.a;
}
- Vector<int> polygon = navmesh->get_polygon(i);
+ Vector<int> polygon = navigation_mesh->get_polygon(i);
face_vertex_array.push_back(vertices[polygon[0]]);
face_vertex_array.push_back(vertices[polygon[1]]);
@@ -528,7 +528,7 @@ void NavigationRegion3D::_update_debug_edge_connections_mesh() {
return;
}
- if (!navmesh.is_valid()) {
+ if (!navigation_mesh.is_valid()) {
if (debug_edge_connections_instance.is_valid()) {
RS::get_singleton()->instance_set_visible(debug_edge_connections_instance, false);
}
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index 660538d314..7dcfa9cfa4 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -42,7 +42,7 @@ class NavigationRegion3D : public Node3D {
uint32_t navigation_layers = 1;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
- Ref<NavigationMesh> navmesh;
+ Ref<NavigationMesh> navigation_mesh;
Thread bake_thread;
@@ -82,13 +82,13 @@ public:
void set_travel_cost(real_t p_travel_cost);
real_t get_travel_cost() const;
- void set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh);
+ void set_navigation_mesh(const Ref<NavigationMesh> &p_navigation_mesh);
Ref<NavigationMesh> get_navigation_mesh() const;
/// Bakes the navigation mesh; once done, automatically
/// sets the new navigation mesh and emits a signal
void bake_navigation_mesh(bool p_on_thread);
- void _bake_finished(Ref<NavigationMesh> p_nav_mesh);
+ void _bake_finished(Ref<NavigationMesh> p_navigation_mesh);
PackedStringArray get_configuration_warnings() const override;
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index a60ccd2169..32bbea8ff3 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -251,12 +251,22 @@ Vector3 Node3D::get_global_rotation() const {
return get_global_transform().get_basis().get_euler();
}
+Vector3 Node3D::get_global_rotation_degrees() const {
+ Vector3 radians = get_global_rotation();
+ return Vector3(Math::rad_to_deg(radians.x), Math::rad_to_deg(radians.y), Math::rad_to_deg(radians.z));
+}
+
void Node3D::set_global_rotation(const Vector3 &p_euler_rad) {
Transform3D transform = get_global_transform();
transform.basis = Basis::from_euler(p_euler_rad);
set_global_transform(transform);
}
+void Node3D::set_global_rotation_degrees(const Vector3 &p_euler_degrees) {
+ Vector3 radians(Math::deg_to_rad(p_euler_degrees.x), Math::deg_to_rad(p_euler_degrees.y), Math::deg_to_rad(p_euler_degrees.z));
+ set_global_rotation(radians);
+}
+
void Node3D::set_transform(const Transform3D &p_transform) {
data.local_transform = p_transform;
data.dirty = DIRTY_EULER_ROTATION_AND_SCALE; // Make rot/scale dirty.
@@ -440,6 +450,11 @@ void Node3D::set_rotation(const Vector3 &p_euler_rad) {
}
}
+void Node3D::set_rotation_degrees(const Vector3 &p_euler_degrees) {
+ Vector3 radians(Math::deg_to_rad(p_euler_degrees.x), Math::deg_to_rad(p_euler_degrees.y), Math::deg_to_rad(p_euler_degrees.z));
+ set_rotation(radians);
+}
+
void Node3D::set_scale(const Vector3 &p_scale) {
if (data.dirty & DIRTY_EULER_ROTATION_AND_SCALE) {
// Update rotation only if rotation and scale are dirty, as scale will be overridden.
@@ -467,6 +482,11 @@ Vector3 Node3D::get_rotation() const {
return data.euler_rotation;
}
+Vector3 Node3D::get_rotation_degrees() const {
+ Vector3 radians = get_rotation();
+ return Vector3(Math::rad_to_deg(radians.x), Math::rad_to_deg(radians.y), Math::rad_to_deg(radians.z));
+}
+
Vector3 Node3D::get_scale() const {
if (data.dirty & DIRTY_EULER_ROTATION_AND_SCALE) {
_update_rotation_and_scale();
@@ -958,8 +978,10 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_transform"), &Node3D::get_transform);
ClassDB::bind_method(D_METHOD("set_position", "position"), &Node3D::set_position);
ClassDB::bind_method(D_METHOD("get_position"), &Node3D::get_position);
- ClassDB::bind_method(D_METHOD("set_rotation", "euler"), &Node3D::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation", "euler_radians"), &Node3D::set_rotation);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node3D::get_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "euler_degrees"), &Node3D::set_rotation_degrees);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node3D::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_rotation_order", "order"), &Node3D::set_rotation_order);
ClassDB::bind_method(D_METHOD("get_rotation_order"), &Node3D::get_rotation_order);
ClassDB::bind_method(D_METHOD("set_rotation_edit_mode", "edit_mode"), &Node3D::set_rotation_edit_mode);
@@ -975,8 +997,10 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_global_transform"), &Node3D::get_global_transform);
ClassDB::bind_method(D_METHOD("set_global_position", "position"), &Node3D::set_global_position);
ClassDB::bind_method(D_METHOD("get_global_position"), &Node3D::get_global_position);
- ClassDB::bind_method(D_METHOD("set_global_rotation", "radians"), &Node3D::set_global_rotation);
+ ClassDB::bind_method(D_METHOD("set_global_rotation", "euler_radians"), &Node3D::set_global_rotation);
ClassDB::bind_method(D_METHOD("get_global_rotation"), &Node3D::get_global_rotation);
+ ClassDB::bind_method(D_METHOD("set_global_rotation_degrees", "euler_degrees"), &Node3D::set_global_rotation_degrees);
+ ClassDB::bind_method(D_METHOD("get_global_rotation_degrees"), &Node3D::get_global_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_parent_node_3d"), &Node3D::get_parent_node_3d);
ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Node3D::set_ignore_transform_notification);
@@ -1045,6 +1069,7 @@ void Node3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "suffix:m", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_greater,or_less,hide_slider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_HIDE_QUATERNION_EDIT, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion");
ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_LINK, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
@@ -1054,6 +1079,7 @@ void Node3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "global_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_rotation", "get_global_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "global_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_rotation_degrees", "get_global_rotation_degrees");
ADD_GROUP("Visibility", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "visibility_parent", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GeometryInstance3D"), "set_visibility_parent", "get_visibility_parent");
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index 76c1e3e22c..9558a978fd 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -172,19 +172,23 @@ public:
void set_rotation_order(EulerOrder p_order);
void set_rotation(const Vector3 &p_euler_rad);
+ void set_rotation_degrees(const Vector3 &p_euler_degrees);
void set_scale(const Vector3 &p_scale);
void set_global_position(const Vector3 &p_position);
void set_global_rotation(const Vector3 &p_euler_rad);
+ void set_global_rotation_degrees(const Vector3 &p_euler_degrees);
Vector3 get_position() const;
EulerOrder get_rotation_order() const;
Vector3 get_rotation() const;
+ Vector3 get_rotation_degrees() const;
Vector3 get_scale() const;
Vector3 get_global_position() const;
Vector3 get_global_rotation() const;
+ Vector3 get_global_rotation_degrees() const;
void set_transform(const Transform3D &p_transform);
void set_basis(const Basis &p_basis);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 68af7af5d4..21c7c4ddb4 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1475,10 +1475,18 @@ void Control::set_rotation(real_t p_radians) {
_notify_transform();
}
+void Control::set_rotation_degrees(real_t p_degrees) {
+ set_rotation(Math::deg_to_rad(p_degrees));
+}
+
real_t Control::get_rotation() const {
return data.rotation;
}
+real_t Control::get_rotation_degrees() const {
+ return Math::rad_to_deg(get_rotation());
+}
+
void Control::set_pivot_offset(const Vector2 &p_pivot) {
if (data.pivot_offset == p_pivot) {
return;
@@ -3042,6 +3050,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_global_position", "position", "keep_offsets"), &Control::set_global_position, DEFVAL(false));
ClassDB::bind_method(D_METHOD("_set_global_position", "position"), &Control::_set_global_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Control::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale);
ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset);
ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin);
@@ -3049,6 +3058,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &Control::get_position);
ClassDB::bind_method(D_METHOD("get_size"), &Control::get_size);
ClassDB::bind_method(D_METHOD("get_rotation"), &Control::get_rotation);
+ ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Control::get_rotation_degrees);
ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale);
ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset);
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
@@ -3217,6 +3227,7 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_EDITOR), "_set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians"), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_pivot_offset", "get_pivot_offset");
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 12710f3a93..f82fba3b1b 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -451,7 +451,9 @@ public:
void set_scale(const Vector2 &p_scale);
Vector2 get_scale() const;
void set_rotation(real_t p_radians);
+ void set_rotation_degrees(real_t p_degrees);
real_t get_rotation() const;
+ real_t get_rotation_degrees() const;
void set_pivot_offset(const Vector2 &p_pivot);
Vector2 get_pivot_offset() const;
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 7219e86f52..2c43ca7143 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -108,6 +108,14 @@ String LinkButton::get_language() const {
return language;
}
+void LinkButton::set_uri(const String &p_uri) {
+ uri = p_uri;
+}
+
+String LinkButton::get_uri() const {
+ return uri;
+}
+
void LinkButton::set_underline_mode(UnderlineMode p_underline_mode) {
if (underline_mode == p_underline_mode) {
return;
@@ -121,6 +129,14 @@ LinkButton::UnderlineMode LinkButton::get_underline_mode() const {
return underline_mode;
}
+void LinkButton::pressed() {
+ if (uri.is_empty()) {
+ return;
+ }
+
+ OS::get_singleton()->shell_open(uri);
+}
+
Size2 LinkButton::get_minimum_size() const {
return text_buf->get_size();
}
@@ -245,6 +261,8 @@ void LinkButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text_direction"), &LinkButton::get_text_direction);
ClassDB::bind_method(D_METHOD("set_language", "language"), &LinkButton::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &LinkButton::get_language);
+ ClassDB::bind_method(D_METHOD("set_uri", "uri"), &LinkButton::set_uri);
+ ClassDB::bind_method(D_METHOD("get_uri"), &LinkButton::get_uri);
ClassDB::bind_method(D_METHOD("set_underline_mode", "underline_mode"), &LinkButton::set_underline_mode);
ClassDB::bind_method(D_METHOD("get_underline_mode"), &LinkButton::get_underline_mode);
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &LinkButton::set_structured_text_bidi_override);
@@ -258,6 +276,7 @@ void LinkButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "uri"), "set_uri", "get_uri");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index accd848163..c71872fc86 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -49,6 +49,7 @@ private:
String xl_text;
Ref<TextLine> text_buf;
UnderlineMode underline_mode = UNDERLINE_MODE_ALWAYS;
+ String uri;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
@@ -76,6 +77,7 @@ private:
void _shape();
protected:
+ virtual void pressed() override;
virtual Size2 get_minimum_size() const override;
virtual void _update_theme_item_cache() override;
void _notification(int p_what);
@@ -84,6 +86,8 @@ protected:
public:
void set_text(const String &p_text);
String get_text() const;
+ void set_uri(const String &p_uri);
+ String get_uri() const;
void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
TextServer::StructuredTextParser get_structured_text_bidi_override() const;
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 2563fa5914..377e189313 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -144,7 +144,7 @@ void CanvasItem::_redraw_callback() {
Transform2D CanvasItem::get_global_transform_with_canvas() const {
if (canvas_layer) {
- return canvas_layer->get_transform() * get_global_transform();
+ return canvas_layer->get_final_transform() * get_global_transform();
} else if (is_inside_tree()) {
return get_viewport()->get_canvas_transform() * get_global_transform();
} else {
@@ -621,10 +621,10 @@ void CanvasItem::draw_texture_rect_region(const Ref<Texture2D> &p_texture, const
p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_clip_uv);
}
-void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, double p_outline, double p_pixel_range) {
+void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, double p_outline, double p_pixel_range, double p_scale) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_texture.is_null());
- RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range);
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range, p_scale);
}
void CanvasItem::draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate) {
@@ -974,7 +974,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0));
+ ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range", "scale"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_lcd_texture_rect_region", "texture", "rect", "src_rect", "modulate"), &CanvasItem::draw_lcd_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box);
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0));
@@ -1099,7 +1099,7 @@ Transform2D CanvasItem::get_canvas_transform() const {
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
if (canvas_layer) {
- return canvas_layer->get_transform();
+ return canvas_layer->get_final_transform();
} else if (Object::cast_to<CanvasItem>(get_parent())) {
return Object::cast_to<CanvasItem>(get_parent())->get_canvas_transform();
} else {
@@ -1111,7 +1111,7 @@ Transform2D CanvasItem::get_viewport_transform() const {
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
if (canvas_layer) {
- return get_viewport()->get_final_transform() * canvas_layer->get_transform();
+ return get_viewport()->get_final_transform() * canvas_layer->get_final_transform();
} else {
return get_viewport()->get_final_transform() * get_viewport()->get_canvas_transform();
}
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index 4ace982825..bae03d706a 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -259,7 +259,7 @@ public:
void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1));
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
- void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0);
+ void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0, double p_scale = 1.0);
void draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect);
void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), real_t p_width = 1);
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index 5fde18721a..97b784e9d0 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -88,6 +88,18 @@ Transform2D CanvasLayer::get_transform() const {
return transform;
}
+Transform2D CanvasLayer::get_final_transform() const {
+ if (is_following_viewport()) {
+ Transform2D follow;
+ follow.scale(Vector2(get_follow_viewport_scale(), get_follow_viewport_scale()));
+ if (vp) {
+ follow = vp->get_canvas_transform() * follow;
+ }
+ return follow * transform;
+ }
+ return transform;
+}
+
void CanvasLayer::_update_xform() {
transform.set_rotation_and_scale(rot, scale);
transform.set_origin(ofs);
@@ -304,6 +316,7 @@ void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &CanvasLayer::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &CanvasLayer::get_transform);
+ ClassDB::bind_method(D_METHOD("get_final_transform"), &CanvasLayer::get_final_transform);
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &CanvasLayer::set_offset);
ClassDB::bind_method(D_METHOD("get_offset"), &CanvasLayer::get_offset);
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index 74b5ebd453..2afc842a50 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -77,6 +77,7 @@ public:
void set_transform(const Transform2D &p_xform);
Transform2D get_transform() const;
+ Transform2D get_final_transform() const;
void set_offset(const Vector2 &p_offset);
Vector2 get_offset() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index e17947c27b..e61cca0a0f 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1422,7 +1422,7 @@ SceneTree::SceneTree() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa_3d", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")));
root->set_msaa_3d(Viewport::MSAA(msaa_mode_3d));
- const bool transparent_background = GLOBAL_DEF("rendering/transparent_background", false);
+ const bool transparent_background = GLOBAL_DEF("rendering/viewport/transparent_background", false);
root->set_transparent_background(transparent_background);
const int ssaa_mode = GLOBAL_DEF_BASIC("rendering/anti_aliasing/quality/screen_space_aa", 0);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index fdbcb20d30..afc31ae480 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -642,7 +642,7 @@ void Viewport::_process_picking() {
ObjectID canvas_layer_id;
if (E) {
// A descendant CanvasLayer.
- canvas_layer_transform = E->get_transform();
+ canvas_layer_transform = E->get_final_transform();
canvas_layer_id = E->get_instance_id();
} else {
// This Viewport's builtin canvas.
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 043895b591..4f300cb5d6 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -56,6 +56,7 @@
#include "scene/2d/navigation_agent_2d.h"
#include "scene/2d/navigation_link_2d.h"
#include "scene/2d/navigation_obstacle_2d.h"
+#include "scene/2d/navigation_region_2d.h"
#include "scene/2d/parallax_background.h"
#include "scene/2d/parallax_layer.h"
#include "scene/2d/path_2d.h"
@@ -163,6 +164,7 @@
#include "scene/resources/mesh_data_tool.h"
#include "scene/resources/multimesh.h"
#include "scene/resources/navigation_mesh.h"
+#include "scene/resources/navigation_polygon.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/particle_process_material.h"
#include "scene/resources/physics_material.h"
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index 7c78b757c7..8b47d12308 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -57,10 +57,10 @@ bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
_set_item_shapes(idx, p_value);
} else if (what == "preview") {
set_item_preview(idx, p_value);
- } else if (what == "navmesh") {
- set_item_navmesh(idx, p_value);
- } else if (what == "navmesh_transform") {
- set_item_navmesh_transform(idx, p_value);
+ } else if (what == "navigation_mesh") {
+ set_item_navigation_mesh(idx, p_value);
+ } else if (what == "navigation_mesh_transform") {
+ set_item_navigation_mesh_transform(idx, p_value);
} else {
return false;
}
@@ -85,10 +85,10 @@ bool MeshLibrary::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = get_item_mesh_transform(idx);
} else if (what == "shapes") {
r_ret = _get_item_shapes(idx);
- } else if (what == "navmesh") {
- r_ret = get_item_navmesh(idx);
- } else if (what == "navmesh_transform") {
- r_ret = get_item_navmesh_transform(idx);
+ } else if (what == "navigation_mesh") {
+ r_ret = get_item_navigation_mesh(idx);
+ } else if (what == "navigation_mesh_transform") {
+ r_ret = get_item_navigation_mesh_transform(idx);
} else if (what == "preview") {
r_ret = get_item_preview(idx);
} else {
@@ -105,8 +105,8 @@ void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + PNAME("mesh"), PROPERTY_HINT_RESOURCE_TYPE, "Mesh"));
p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prop_name + PNAME("mesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
p_list->push_back(PropertyInfo(Variant::ARRAY, prop_name + PNAME("shapes")));
- p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + PNAME("navmesh"), PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
- p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prop_name + PNAME("navmesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + PNAME("navigation_mesh"), PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prop_name + PNAME("navigation_mesh_transform"), PROPERTY_HINT_NONE, "suffix:m"));
p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + PNAME("preview"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT));
}
}
@@ -150,18 +150,18 @@ void MeshLibrary::set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes)
notify_property_list_changed();
}
-void MeshLibrary::set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh) {
+void MeshLibrary::set_item_navigation_mesh(int p_item, const Ref<NavigationMesh> &p_navigation_mesh) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
- item_map[p_item].navmesh = p_navmesh;
+ item_map[p_item].navigation_mesh = p_navigation_mesh;
notify_property_list_changed();
notify_change_to_owners();
emit_changed();
notify_property_list_changed();
}
-void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform3D &p_transform) {
+void MeshLibrary::set_item_navigation_mesh_transform(int p_item, const Transform3D &p_transform) {
ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
- item_map[p_item].navmesh_transform = p_transform;
+ item_map[p_item].navigation_mesh_transform = p_transform;
notify_change_to_owners();
emit_changed();
notify_property_list_changed();
@@ -194,14 +194,14 @@ Vector<MeshLibrary::ShapeData> MeshLibrary::get_item_shapes(int p_item) const {
return item_map[p_item].shapes;
}
-Ref<NavigationMesh> MeshLibrary::get_item_navmesh(int p_item) const {
+Ref<NavigationMesh> MeshLibrary::get_item_navigation_mesh(int p_item) const {
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<NavigationMesh>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
- return item_map[p_item].navmesh;
+ return item_map[p_item].navigation_mesh;
}
-Transform3D MeshLibrary::get_item_navmesh_transform(int p_item) const {
+Transform3D MeshLibrary::get_item_navigation_mesh_transform(int p_item) const {
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform3D(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
- return item_map[p_item].navmesh_transform;
+ return item_map[p_item].navigation_mesh_transform;
}
Ref<Texture2D> MeshLibrary::get_item_preview(int p_item) const {
@@ -314,15 +314,15 @@ void MeshLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_name", "id", "name"), &MeshLibrary::set_item_name);
ClassDB::bind_method(D_METHOD("set_item_mesh", "id", "mesh"), &MeshLibrary::set_item_mesh);
ClassDB::bind_method(D_METHOD("set_item_mesh_transform", "id", "mesh_transform"), &MeshLibrary::set_item_mesh_transform);
- ClassDB::bind_method(D_METHOD("set_item_navmesh", "id", "navmesh"), &MeshLibrary::set_item_navmesh);
- ClassDB::bind_method(D_METHOD("set_item_navmesh_transform", "id", "navmesh"), &MeshLibrary::set_item_navmesh_transform);
+ ClassDB::bind_method(D_METHOD("set_item_navigation_mesh", "id", "navigation_mesh"), &MeshLibrary::set_item_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("set_item_navigation_mesh_transform", "id", "navigation_mesh"), &MeshLibrary::set_item_navigation_mesh_transform);
ClassDB::bind_method(D_METHOD("set_item_shapes", "id", "shapes"), &MeshLibrary::_set_item_shapes);
ClassDB::bind_method(D_METHOD("set_item_preview", "id", "texture"), &MeshLibrary::set_item_preview);
ClassDB::bind_method(D_METHOD("get_item_name", "id"), &MeshLibrary::get_item_name);
ClassDB::bind_method(D_METHOD("get_item_mesh", "id"), &MeshLibrary::get_item_mesh);
ClassDB::bind_method(D_METHOD("get_item_mesh_transform", "id"), &MeshLibrary::get_item_mesh_transform);
- ClassDB::bind_method(D_METHOD("get_item_navmesh", "id"), &MeshLibrary::get_item_navmesh);
- ClassDB::bind_method(D_METHOD("get_item_navmesh_transform", "id"), &MeshLibrary::get_item_navmesh_transform);
+ ClassDB::bind_method(D_METHOD("get_item_navigation_mesh", "id"), &MeshLibrary::get_item_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("get_item_navigation_mesh_transform", "id"), &MeshLibrary::get_item_navigation_mesh_transform);
ClassDB::bind_method(D_METHOD("get_item_shapes", "id"), &MeshLibrary::_get_item_shapes);
ClassDB::bind_method(D_METHOD("get_item_preview", "id"), &MeshLibrary::get_item_preview);
ClassDB::bind_method(D_METHOD("remove_item", "id"), &MeshLibrary::remove_item);
diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h
index 79acb41c4e..a18e2b20d3 100644
--- a/scene/resources/mesh_library.h
+++ b/scene/resources/mesh_library.h
@@ -49,11 +49,11 @@ public:
struct Item {
String name;
Ref<Mesh> mesh;
+ Transform3D mesh_transform;
Vector<ShapeData> shapes;
Ref<Texture2D> preview;
- Transform3D navmesh_transform;
- Transform3D mesh_transform;
- Ref<NavigationMesh> navmesh;
+ Ref<NavigationMesh> navigation_mesh;
+ Transform3D navigation_mesh_transform;
};
RBMap<int, Item> item_map;
@@ -74,15 +74,15 @@ public:
void set_item_name(int p_item, const String &p_name);
void set_item_mesh(int p_item, const Ref<Mesh> &p_mesh);
void set_item_mesh_transform(int p_item, const Transform3D &p_transform);
- void set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh);
- void set_item_navmesh_transform(int p_item, const Transform3D &p_transform);
+ void set_item_navigation_mesh(int p_item, const Ref<NavigationMesh> &p_navigation_mesh);
+ void set_item_navigation_mesh_transform(int p_item, const Transform3D &p_transform);
void set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes);
void set_item_preview(int p_item, const Ref<Texture2D> &p_preview);
String get_item_name(int p_item) const;
Ref<Mesh> get_item_mesh(int p_item) const;
Transform3D get_item_mesh_transform(int p_item) const;
- Ref<NavigationMesh> get_item_navmesh(int p_item) const;
- Transform3D get_item_navmesh_transform(int p_item) const;
+ Ref<NavigationMesh> get_item_navigation_mesh(int p_item) const;
+ Transform3D get_item_navigation_mesh_transform(int p_item) const;
Vector<ShapeData> get_item_shapes(int p_item) const;
Ref<Texture2D> get_item_preview(int p_item) const;
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index de97498674..76552faec1 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -225,13 +225,13 @@ float NavigationMesh::get_edge_max_error() const {
return edge_max_error;
}
-void NavigationMesh::set_verts_per_poly(float p_value) {
+void NavigationMesh::set_vertices_per_polyon(float p_value) {
ERR_FAIL_COND(p_value < 3);
- verts_per_poly = p_value;
+ vertices_per_polyon = p_value;
}
-float NavigationMesh::get_verts_per_poly() const {
- return verts_per_poly;
+float NavigationMesh::get_vertices_per_polyon() const {
+ return vertices_per_polyon;
}
void NavigationMesh::set_detail_sample_distance(float p_value) {
@@ -483,8 +483,8 @@ void NavigationMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_edge_max_error", "edge_max_error"), &NavigationMesh::set_edge_max_error);
ClassDB::bind_method(D_METHOD("get_edge_max_error"), &NavigationMesh::get_edge_max_error);
- ClassDB::bind_method(D_METHOD("set_verts_per_poly", "verts_per_poly"), &NavigationMesh::set_verts_per_poly);
- ClassDB::bind_method(D_METHOD("get_verts_per_poly"), &NavigationMesh::get_verts_per_poly);
+ ClassDB::bind_method(D_METHOD("set_vertices_per_polyon", "vertices_per_polyon"), &NavigationMesh::set_vertices_per_polyon);
+ ClassDB::bind_method(D_METHOD("get_vertices_per_polyon"), &NavigationMesh::get_vertices_per_polyon);
ClassDB::bind_method(D_METHOD("set_detail_sample_distance", "detail_sample_dist"), &NavigationMesh::set_detail_sample_distance);
ClassDB::bind_method(D_METHOD("get_detail_sample_distance"), &NavigationMesh::get_detail_sample_distance);
@@ -527,9 +527,9 @@ void NavigationMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Both"), "set_parsed_geometry_type", "get_parsed_geometry_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY_DEFAULT("geometry_collision_mask", 0xFFFFFFFF);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_source_geometry_mode", PROPERTY_HINT_ENUM, "NavMesh Children,Group With Children,Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_source_geometry_mode", PROPERTY_HINT_ENUM, "Root Node Children,Group With Children,Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "geometry_source_group_name"), "set_source_group_name", "get_source_group_name");
- ADD_PROPERTY_DEFAULT("geometry_source_group_name", StringName("navmesh"));
+ ADD_PROPERTY_DEFAULT("geometry_source_group_name", StringName("navigation_mesh_source_group"));
ADD_GROUP("Cells", "cell_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_height", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_height", "get_cell_height");
@@ -545,7 +545,7 @@ void NavigationMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_max_length", PROPERTY_HINT_RANGE, "0.0,50.0,0.01,or_greater,suffix:m"), "set_edge_max_length", "get_edge_max_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_max_error", PROPERTY_HINT_RANGE, "0.1,3.0,0.01,or_greater,suffix:m"), "set_edge_max_error", "get_edge_max_error");
ADD_GROUP("Polygons", "polygon_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "polygon_verts_per_poly", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_verts_per_poly", "get_verts_per_poly");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "polygon_vertices_per_polyon", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_vertices_per_polyon", "get_vertices_per_polyon");
ADD_GROUP("Details", "detail_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_distance", PROPERTY_HINT_RANGE, "0.1,16.0,0.01,or_greater,suffix:m"), "set_detail_sample_distance", "get_detail_sample_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_max_error", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater,suffix:m"), "set_detail_sample_max_error", "get_detail_sample_max_error");
@@ -566,7 +566,7 @@ void NavigationMesh::_bind_methods() {
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_BOTH);
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MAX);
- BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_NAVMESH_CHILDREN);
+ BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_ROOT_NODE_CHILDREN);
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN);
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_EXPLICIT);
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_MAX);
@@ -581,7 +581,7 @@ void NavigationMesh::_validate_property(PropertyInfo &p_property) const {
}
if (p_property.name == "geometry_source_group_name") {
- if (source_geometry_mode == SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
+ if (source_geometry_mode == SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) {
p_property.usage = PROPERTY_USAGE_NONE;
return;
}
diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h
index 5ddbd75dcb..93880603eb 100644
--- a/scene/resources/navigation_mesh.h
+++ b/scene/resources/navigation_mesh.h
@@ -84,7 +84,7 @@ public:
};
enum SourceGeometryMode {
- SOURCE_GEOMETRY_NAVMESH_CHILDREN = 0,
+ SOURCE_GEOMETRY_ROOT_NODE_CHILDREN = 0,
SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN,
SOURCE_GEOMETRY_GROUPS_EXPLICIT,
SOURCE_GEOMETRY_MAX
@@ -101,7 +101,7 @@ protected:
float region_merge_size = 20.0f;
float edge_max_length = 12.0f;
float edge_max_error = 1.3f;
- float verts_per_poly = 6.0f;
+ float vertices_per_polyon = 6.0f;
float detail_sample_distance = 6.0f;
float detail_sample_max_error = 1.0f;
@@ -109,8 +109,8 @@ protected:
ParsedGeometryType parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES;
uint32_t collision_mask = 0xFFFFFFFF;
- SourceGeometryMode source_geometry_mode = SOURCE_GEOMETRY_NAVMESH_CHILDREN;
- StringName source_group_name = "navmesh";
+ SourceGeometryMode source_geometry_mode = SOURCE_GEOMETRY_ROOT_NODE_CHILDREN;
+ StringName source_group_name = "navigation_mesh_source_group";
bool filter_low_hanging_obstacles = false;
bool filter_ledge_spans = false;
@@ -168,8 +168,8 @@ public:
void set_edge_max_error(float p_value);
float get_edge_max_error() const;
- void set_verts_per_poly(float p_value);
- float get_verts_per_poly() const;
+ void set_vertices_per_polyon(float p_value);
+ float get_vertices_per_polyon() const;
void set_detail_sample_distance(float p_value);
float get_detail_sample_distance() const;
diff --git a/scene/resources/navigation_polygon.cpp b/scene/resources/navigation_polygon.cpp
new file mode 100644
index 0000000000..04077e95a7
--- /dev/null
+++ b/scene/resources/navigation_polygon.cpp
@@ -0,0 +1,354 @@
+/*************************************************************************/
+/* navigation_polygon.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "navigation_polygon.h"
+
+#include "core/core_string_names.h"
+#include "core/math/geometry_2d.h"
+#include "core/os/mutex.h"
+
+#include "thirdparty/misc/polypartition.h"
+
+#ifdef TOOLS_ENABLED
+Rect2 NavigationPolygon::_edit_get_rect() const {
+ if (rect_cache_dirty) {
+ item_rect = Rect2();
+ bool first = true;
+
+ for (int i = 0; i < outlines.size(); i++) {
+ const Vector<Vector2> &outline = outlines[i];
+ const int outline_size = outline.size();
+ if (outline_size < 3) {
+ continue;
+ }
+ const Vector2 *p = outline.ptr();
+ for (int j = 0; j < outline_size; j++) {
+ if (first) {
+ item_rect = Rect2(p[j], Vector2(0, 0));
+ first = false;
+ } else {
+ item_rect.expand_to(p[j]);
+ }
+ }
+ }
+
+ rect_cache_dirty = false;
+ }
+ return item_rect;
+}
+
+bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+ for (int i = 0; i < outlines.size(); i++) {
+ const Vector<Vector2> &outline = outlines[i];
+ const int outline_size = outline.size();
+ if (outline_size < 3) {
+ continue;
+ }
+ if (Geometry2D::is_point_in_polygon(p_point, Variant(outline))) {
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
+void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) {
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+ vertices = p_vertices;
+ rect_cache_dirty = true;
+}
+
+Vector<Vector2> NavigationPolygon::get_vertices() const {
+ return vertices;
+}
+
+void NavigationPolygon::_set_polygons(const TypedArray<Vector<int32_t>> &p_array) {
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+ polygons.resize(p_array.size());
+ for (int i = 0; i < p_array.size(); i++) {
+ polygons.write[i].indices = p_array[i];
+ }
+}
+
+TypedArray<Vector<int32_t>> NavigationPolygon::_get_polygons() const {
+ TypedArray<Vector<int32_t>> ret;
+ ret.resize(polygons.size());
+ for (int i = 0; i < ret.size(); i++) {
+ ret[i] = polygons[i].indices;
+ }
+
+ return ret;
+}
+
+void NavigationPolygon::_set_outlines(const TypedArray<Vector<Vector2>> &p_array) {
+ outlines.resize(p_array.size());
+ for (int i = 0; i < p_array.size(); i++) {
+ outlines.write[i] = p_array[i];
+ }
+ rect_cache_dirty = true;
+}
+
+TypedArray<Vector<Vector2>> NavigationPolygon::_get_outlines() const {
+ TypedArray<Vector<Vector2>> ret;
+ ret.resize(outlines.size());
+ for (int i = 0; i < ret.size(); i++) {
+ ret[i] = outlines[i];
+ }
+
+ return ret;
+}
+
+void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {
+ Polygon polygon;
+ polygon.indices = p_polygon;
+ polygons.push_back(polygon);
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+}
+
+void NavigationPolygon::add_outline_at_index(const Vector<Vector2> &p_outline, int p_index) {
+ outlines.insert(p_index, p_outline);
+ rect_cache_dirty = true;
+}
+
+int NavigationPolygon::get_polygon_count() const {
+ return polygons.size();
+}
+
+Vector<int> NavigationPolygon::get_polygon(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>());
+ return polygons[p_idx].indices;
+}
+
+void NavigationPolygon::clear_polygons() {
+ polygons.clear();
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+}
+
+Ref<NavigationMesh> NavigationPolygon::get_navigation_mesh() {
+ MutexLock lock(navigation_mesh_generation);
+
+ if (navigation_mesh.is_null()) {
+ navigation_mesh.instantiate();
+ Vector<Vector3> verts;
+ {
+ verts.resize(get_vertices().size());
+ Vector3 *w = verts.ptrw();
+
+ const Vector2 *r = get_vertices().ptr();
+
+ for (int i(0); i < get_vertices().size(); i++) {
+ w[i] = Vector3(r[i].x, 0.0, r[i].y);
+ }
+ }
+ navigation_mesh->set_vertices(verts);
+
+ for (int i(0); i < get_polygon_count(); i++) {
+ navigation_mesh->add_polygon(get_polygon(i));
+ }
+ }
+
+ return navigation_mesh;
+}
+
+void NavigationPolygon::add_outline(const Vector<Vector2> &p_outline) {
+ outlines.push_back(p_outline);
+ rect_cache_dirty = true;
+}
+
+int NavigationPolygon::get_outline_count() const {
+ return outlines.size();
+}
+
+void NavigationPolygon::set_outline(int p_idx, const Vector<Vector2> &p_outline) {
+ ERR_FAIL_INDEX(p_idx, outlines.size());
+ outlines.write[p_idx] = p_outline;
+ rect_cache_dirty = true;
+}
+
+void NavigationPolygon::remove_outline(int p_idx) {
+ ERR_FAIL_INDEX(p_idx, outlines.size());
+ outlines.remove_at(p_idx);
+ rect_cache_dirty = true;
+}
+
+Vector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, outlines.size(), Vector<Vector2>());
+ return outlines[p_idx];
+}
+
+void NavigationPolygon::clear_outlines() {
+ outlines.clear();
+ rect_cache_dirty = true;
+}
+
+void NavigationPolygon::make_polygons_from_outlines() {
+ {
+ MutexLock lock(navigation_mesh_generation);
+ navigation_mesh.unref();
+ }
+ List<TPPLPoly> in_poly, out_poly;
+
+ Vector2 outside_point(-1e10, -1e10);
+
+ for (int i = 0; i < outlines.size(); i++) {
+ Vector<Vector2> ol = outlines[i];
+ int olsize = ol.size();
+ if (olsize < 3) {
+ continue;
+ }
+ const Vector2 *r = ol.ptr();
+ for (int j = 0; j < olsize; j++) {
+ outside_point.x = MAX(r[j].x, outside_point.x);
+ outside_point.y = MAX(r[j].y, outside_point.y);
+ }
+ }
+
+ outside_point += Vector2(0.7239784, 0.819238); //avoid precision issues
+
+ for (int i = 0; i < outlines.size(); i++) {
+ Vector<Vector2> ol = outlines[i];
+ int olsize = ol.size();
+ if (olsize < 3) {
+ continue;
+ }
+ const Vector2 *r = ol.ptr();
+
+ int interscount = 0;
+ //test if this is an outer outline
+ for (int k = 0; k < outlines.size(); k++) {
+ if (i == k) {
+ continue; //no self intersect
+ }
+
+ Vector<Vector2> ol2 = outlines[k];
+ int olsize2 = ol2.size();
+ if (olsize2 < 3) {
+ continue;
+ }
+ const Vector2 *r2 = ol2.ptr();
+
+ for (int l = 0; l < olsize2; l++) {
+ if (Geometry2D::segment_intersects_segment(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], nullptr)) {
+ interscount++;
+ }
+ }
+ }
+
+ bool outer = (interscount % 2) == 0;
+
+ TPPLPoly tp;
+ tp.Init(olsize);
+ for (int j = 0; j < olsize; j++) {
+ tp[j] = r[j];
+ }
+
+ if (outer) {
+ tp.SetOrientation(TPPL_ORIENTATION_CCW);
+ } else {
+ tp.SetOrientation(TPPL_ORIENTATION_CW);
+ tp.SetHole(true);
+ }
+
+ in_poly.push_back(tp);
+ }
+
+ TPPLPartition tpart;
+ if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
+ ERR_PRINT("NavigationPolygon: Convex partition failed! Failed to convert outlines to a valid NavigationMesh."
+ "\nNavigationPolygon outlines can not overlap vertices or edges inside same outline or with other outlines or have any intersections."
+ "\nAdd the outmost and largest outline first. To add holes inside this outline add the smaller outlines with opposite winding order.");
+ return;
+ }
+
+ polygons.clear();
+ vertices.clear();
+
+ HashMap<Vector2, int> points;
+ for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
+ TPPLPoly &tp = I->get();
+
+ struct Polygon p;
+
+ for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
+ HashMap<Vector2, int>::Iterator E = points.find(tp[i]);
+ if (!E) {
+ E = points.insert(tp[i], vertices.size());
+ vertices.push_back(tp[i]);
+ }
+ p.indices.push_back(E->value);
+ }
+
+ polygons.push_back(p);
+ }
+
+ emit_signal(CoreStringNames::get_singleton()->changed);
+}
+
+void NavigationPolygon::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationPolygon::set_vertices);
+ ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationPolygon::get_vertices);
+
+ ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationPolygon::add_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationPolygon::get_polygon_count);
+ ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationPolygon::get_polygon);
+ ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationPolygon::clear_polygons);
+ ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationPolygon::get_navigation_mesh);
+
+ ClassDB::bind_method(D_METHOD("add_outline", "outline"), &NavigationPolygon::add_outline);
+ ClassDB::bind_method(D_METHOD("add_outline_at_index", "outline", "index"), &NavigationPolygon::add_outline_at_index);
+ ClassDB::bind_method(D_METHOD("get_outline_count"), &NavigationPolygon::get_outline_count);
+ ClassDB::bind_method(D_METHOD("set_outline", "idx", "outline"), &NavigationPolygon::set_outline);
+ ClassDB::bind_method(D_METHOD("get_outline", "idx"), &NavigationPolygon::get_outline);
+ ClassDB::bind_method(D_METHOD("remove_outline", "idx"), &NavigationPolygon::remove_outline);
+ ClassDB::bind_method(D_METHOD("clear_outlines"), &NavigationPolygon::clear_outlines);
+ ClassDB::bind_method(D_METHOD("make_polygons_from_outlines"), &NavigationPolygon::make_polygons_from_outlines);
+
+ ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationPolygon::_set_polygons);
+ ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationPolygon::_get_polygons);
+
+ ClassDB::bind_method(D_METHOD("_set_outlines", "outlines"), &NavigationPolygon::_set_outlines);
+ ClassDB::bind_method(D_METHOD("_get_outlines"), &NavigationPolygon::_get_outlines);
+
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");
+}
diff --git a/scene/resources/navigation_polygon.h b/scene/resources/navigation_polygon.h
new file mode 100644
index 0000000000..e943cff04e
--- /dev/null
+++ b/scene/resources/navigation_polygon.h
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* navigation_polygon.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_POLYGON_H
+#define NAVIGATION_POLYGON_H
+
+#include "scene/2d/node_2d.h"
+#include "scene/resources/navigation_mesh.h"
+
+class NavigationPolygon : public Resource {
+ GDCLASS(NavigationPolygon, Resource);
+
+ Vector<Vector2> vertices;
+ struct Polygon {
+ Vector<int> indices;
+ };
+ Vector<Polygon> polygons;
+ Vector<Vector<Vector2>> outlines;
+
+ mutable Rect2 item_rect;
+ mutable bool rect_cache_dirty = true;
+
+ Mutex navigation_mesh_generation;
+ // Navigation mesh
+ Ref<NavigationMesh> navigation_mesh;
+
+protected:
+ static void _bind_methods();
+
+ void _set_polygons(const TypedArray<Vector<int32_t>> &p_array);
+ TypedArray<Vector<int32_t>> _get_polygons() const;
+
+ void _set_outlines(const TypedArray<Vector<Vector2>> &p_array);
+ TypedArray<Vector<Vector2>> _get_outlines() const;
+
+public:
+#ifdef TOOLS_ENABLED
+ Rect2 _edit_get_rect() const;
+ bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+#endif
+
+ void set_vertices(const Vector<Vector2> &p_vertices);
+ Vector<Vector2> get_vertices() const;
+
+ void add_polygon(const Vector<int> &p_polygon);
+ int get_polygon_count() const;
+
+ void add_outline(const Vector<Vector2> &p_outline);
+ void add_outline_at_index(const Vector<Vector2> &p_outline, int p_index);
+ void set_outline(int p_idx, const Vector<Vector2> &p_outline);
+ Vector<Vector2> get_outline(int p_idx) const;
+ void remove_outline(int p_idx);
+ int get_outline_count() const;
+
+ void clear_outlines();
+ void make_polygons_from_outlines();
+
+ Vector<int> get_polygon(int p_idx);
+ void clear_polygons();
+
+ Ref<NavigationMesh> get_navigation_mesh();
+
+ NavigationPolygon() {}
+ ~NavigationPolygon() {}
+};
+
+#endif // NAVIGATION_POLYGON_H
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 2106619a6b..18915e294e 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -1591,35 +1591,28 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect,
return false;
}
- Rect2 rc = region;
-
Rect2 src = p_src_rect;
if (src.size == Size2()) {
- src.size = rc.size;
+ src.size = region.size;
}
Vector2 scale = p_rect.size / src.size;
- src.position += (rc.position - margin.position);
- Rect2 src_c = rc.intersection(src);
- if (src_c.size == Size2()) {
+ src.position += (region.position - margin.position);
+ Rect2 src_clipped = region.intersection(src);
+ if (src_clipped.size == Size2()) {
return false;
}
- Vector2 ofs = (src_c.position - src.position);
+ Vector2 ofs = (src_clipped.position - src.position);
if (scale.x < 0) {
- float mx = (margin.size.width - margin.position.x);
- mx -= margin.position.x;
- ofs.x = -(ofs.x + mx);
+ ofs.x += (src_clipped.size.x - src.size.x);
}
if (scale.y < 0) {
- float my = margin.size.height - margin.position.y;
- my -= margin.position.y;
- ofs.y = -(ofs.y + my);
+ ofs.y += (src_clipped.size.y - src.size.y);
}
- Rect2 dr(p_rect.position + ofs * scale, src_c.size * scale);
- r_rect = dr;
- r_src_rect = src_c;
+ r_rect = Rect2(p_rect.position + ofs * scale, src_clipped.size * scale);
+ r_src_rect = src_clipped;
return true;
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 9d2537bb4d..0b0461432b 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -35,7 +35,6 @@
#include "core/math/geometry_2d.h"
#include "core/templates/local_vector.h"
#include "core/templates/rb_set.h"
-#include "scene/2d/navigation_region_2d.h"
#include "scene/gui/control.h"
#include "scene/resources/convex_polygon_shape_2d.h"
#include "servers/navigation_server_2d.h"
@@ -477,7 +476,7 @@ int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source
int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id;
sources[new_source_id] = p_tile_set_source;
- source_ids.append(new_source_id);
+ source_ids.push_back(new_source_id);
source_ids.sort();
p_tile_set_source->set_tile_set(this);
_compute_next_source_id();
@@ -517,7 +516,7 @@ void TileSet::set_source_id(int p_source_id, int p_new_source_id) {
sources.erase(p_source_id);
source_ids.erase(p_source_id);
- source_ids.append(p_new_source_id);
+ source_ids.push_back(p_new_source_id);
source_ids.sort();
_compute_next_source_id();
@@ -1297,7 +1296,7 @@ void TileSet::cleanup_invalid_tile_proxies() {
Vector<int> source_to_remove;
for (const KeyValue<int, int> &E : source_level_proxies) {
if (has_source(E.key)) {
- source_to_remove.append(E.key);
+ source_to_remove.push_back(E.key);
}
}
for (int i = 0; i < source_to_remove.size(); i++) {
@@ -1309,7 +1308,7 @@ void TileSet::cleanup_invalid_tile_proxies() {
for (const KeyValue<Array, Array> &E : coords_level_proxies) {
Array a = E.key;
if (has_source(a[0]) && get_source(a[0])->has_tile(a[1])) {
- coords_to_remove.append(a);
+ coords_to_remove.push_back(a);
}
}
for (int i = 0; i < coords_to_remove.size(); i++) {
@@ -1322,7 +1321,7 @@ void TileSet::cleanup_invalid_tile_proxies() {
for (const KeyValue<Array, Array> &E : alternative_level_proxies) {
Array a = E.key;
if (has_source(a[0]) && get_source(a[0])->has_tile(a[1]) && get_source(a[0])->has_alternative_tile(a[1], a[2])) {
- alternative_to_remove.append(a);
+ alternative_to_remove.push_back(a);
}
}
for (int i = 0; i < alternative_to_remove.size(); i++) {
@@ -1439,16 +1438,18 @@ TileMapCell TileSet::get_random_tile_from_terrains_pattern(int p_terrain_set, Ti
Vector<Vector2> TileSet::get_tile_shape_polygon() {
Vector<Vector2> points;
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
- points.append(Vector2(-0.5, -0.5));
- points.append(Vector2(0.5, -0.5));
- points.append(Vector2(0.5, 0.5));
- points.append(Vector2(-0.5, 0.5));
+ points.push_back(Vector2(-0.5, -0.5));
+ points.push_back(Vector2(0.5, -0.5));
+ points.push_back(Vector2(0.5, 0.5));
+ points.push_back(Vector2(-0.5, 0.5));
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ points.push_back(Vector2(0.0, -0.5));
+ points.push_back(Vector2(-0.5, 0.0));
+ points.push_back(Vector2(0.0, 0.5));
+ points.push_back(Vector2(0.5, 0.0));
} else {
float overlap = 0.0;
switch (tile_shape) {
- case TileSet::TILE_SHAPE_ISOMETRIC:
- overlap = 0.5;
- break;
case TileSet::TILE_SHAPE_HEXAGON:
overlap = 0.25;
break;
@@ -1459,12 +1460,13 @@ Vector<Vector2> TileSet::get_tile_shape_polygon() {
break;
}
- points.append(Vector2(0.0, -0.5));
- points.append(Vector2(-0.5, overlap - 0.5));
- points.append(Vector2(-0.5, 0.5 - overlap));
- points.append(Vector2(0.0, 0.5));
- points.append(Vector2(0.5, 0.5 - overlap));
- points.append(Vector2(0.5, overlap - 0.5));
+ points.push_back(Vector2(0.0, -0.5));
+ points.push_back(Vector2(-0.5, overlap - 0.5));
+ points.push_back(Vector2(-0.5, 0.5 - overlap));
+ points.push_back(Vector2(0.0, 0.5));
+ points.push_back(Vector2(0.5, 0.5 - overlap));
+ points.push_back(Vector2(0.5, overlap - 0.5));
+
if (get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
for (int i = 0; i < points.size(); i++) {
points.write[i] = Vector2(points[i].y, points[i].x);
@@ -3854,7 +3856,7 @@ bool TileSetAtlasSource::_set(const StringName &p_name, const Variant &p_value)
tiles[coords].alternatives[alternative_id] = memnew(TileData);
tiles[coords].alternatives[alternative_id]->set_tile_set(tile_set);
tiles[coords].alternatives[alternative_id]->set_allow_transform(alternative_id > 0);
- tiles[coords].alternatives_ids.append(alternative_id);
+ tiles[coords].alternatives_ids.push_back(alternative_id);
}
if (components.size() >= 3) {
bool valid;
@@ -4028,11 +4030,11 @@ void TileSetAtlasSource::create_tile(const Vector2i p_atlas_coords, const Vector
tad.alternatives[0]->set_allow_transform(false);
tad.alternatives[0]->connect("changed", callable_mp((Resource *)this, &TileSetAtlasSource::emit_changed));
tad.alternatives[0]->notify_property_list_changed();
- tad.alternatives_ids.append(0);
+ tad.alternatives_ids.push_back(0);
// Create and resize the tile.
tiles.insert(p_atlas_coords, tad);
- tiles_ids.append(p_atlas_coords);
+ tiles_ids.push_back(p_atlas_coords);
tiles_ids.sort();
_create_coords_mapping_cache(p_atlas_coords);
@@ -4343,7 +4345,7 @@ void TileSetAtlasSource::move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_
tiles.erase(p_atlas_coords);
tiles_ids.erase(p_atlas_coords);
- tiles_ids.append(new_atlas_coords);
+ tiles_ids.push_back(new_atlas_coords);
tiles_ids.sort();
}
tiles[new_atlas_coords].size_in_atlas = new_size;
@@ -4365,7 +4367,7 @@ int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, i
tiles[p_atlas_coords].alternatives[new_alternative_id]->set_allow_transform(true);
tiles[p_atlas_coords].alternatives[new_alternative_id]->connect("changed", callable_mp((Resource *)this, &TileSetAtlasSource::emit_changed));
tiles[p_atlas_coords].alternatives[new_alternative_id]->notify_property_list_changed();
- tiles[p_atlas_coords].alternatives_ids.append(new_alternative_id);
+ tiles[p_atlas_coords].alternatives_ids.push_back(new_alternative_id);
tiles[p_atlas_coords].alternatives_ids.sort();
_compute_next_alternative_id(p_atlas_coords);
@@ -4395,7 +4397,7 @@ void TileSetAtlasSource::set_alternative_tile_id(const Vector2i p_atlas_coords,
ERR_FAIL_COND_MSG(tiles[p_atlas_coords].alternatives.has(p_new_id), vformat("TileSetAtlasSource has already an alternative with id %d at %s.", p_new_id, String(p_atlas_coords)));
tiles[p_atlas_coords].alternatives[p_new_id] = tiles[p_atlas_coords].alternatives[p_alternative_tile];
- tiles[p_atlas_coords].alternatives_ids.append(p_new_id);
+ tiles[p_atlas_coords].alternatives_ids.push_back(p_new_id);
tiles[p_atlas_coords].alternatives.erase(p_alternative_tile);
tiles[p_atlas_coords].alternatives_ids.erase(p_alternative_tile);
@@ -4683,7 +4685,7 @@ int TileSetScenesCollectionSource::create_scene_tile(Ref<PackedScene> p_packed_s
int new_scene_id = p_id_override >= 0 ? p_id_override : next_scene_id;
scenes[new_scene_id] = SceneData();
- scenes_ids.append(new_scene_id);
+ scenes_ids.push_back(new_scene_id);
scenes_ids.sort();
set_scene_tile_scene(new_scene_id, p_packed_scene);
_compute_next_alternative_id();
@@ -4700,7 +4702,7 @@ void TileSetScenesCollectionSource::set_scene_tile_id(int p_id, int p_new_id) {
scenes[p_new_id] = SceneData();
scenes[p_new_id] = scenes[p_id];
- scenes_ids.append(p_new_id);
+ scenes_ids.push_back(p_new_id);
scenes_ids.sort();
_compute_next_alternative_id();
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 9f465a17e9..88bbbd157a 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -36,10 +36,10 @@
#include "core/templates/local_vector.h"
#include "core/templates/rb_set.h"
#include "scene/2d/light_occluder_2d.h"
-#include "scene/2d/navigation_region_2d.h"
#include "scene/main/canvas_item.h"
#include "scene/resources/concave_polygon_shape_2d.h"
#include "scene/resources/convex_polygon_shape_2d.h"
+#include "scene/resources/navigation_polygon.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/physics_material.h"
#include "scene/resources/shape_2d.h"
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index e657570f9b..c7d626c159 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -449,12 +449,8 @@ void AudioServer::_mix_step() {
case AudioStreamPlaybackListNode::AWAITING_DELETION:
case AudioStreamPlaybackListNode::FADE_OUT_TO_DELETION:
playback_list.erase(playback, [](AudioStreamPlaybackListNode *p) {
- if (p->prev_bus_details) {
- delete p->prev_bus_details;
- }
- if (p->bus_details) {
- delete p->bus_details;
- }
+ delete p->prev_bus_details;
+ delete p->bus_details;
p->stream_playback.unref();
delete p;
});
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 4ed998a77e..1614b8e2f5 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -154,7 +154,7 @@ static ObjectID id_to_id(const ObjectID &id) {
static Ref<NavigationMesh> poly_to_mesh(Ref<NavigationPolygon> d) {
if (d.is_valid()) {
- return d->get_mesh();
+ return d->get_navigation_mesh();
} else {
return Ref<NavigationMesh>();
}
@@ -258,7 +258,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer2D::region_set_navigation_layers);
ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer2D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform);
- ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_polygon", "region", "navigation_polygon"), &NavigationServer2D::region_set_navigation_polygon);
ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer2D::region_get_connections_count);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_start);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_end);
@@ -361,8 +361,8 @@ void FORWARD_2_C(region_set_navigation_layers, RID, p_region, uint32_t, p_naviga
uint32_t FORWARD_1_C(region_get_navigation_layers, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3);
-void NavigationServer2D::region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const {
- NavigationServer3D::get_singleton()->region_set_navmesh(p_region, poly_to_mesh(p_nav_mesh));
+void NavigationServer2D::region_set_navigation_polygon(RID p_region, Ref<NavigationPolygon> p_navigation_polygon) const {
+ NavigationServer3D::get_singleton()->region_set_navigation_mesh(p_region, poly_to_mesh(p_navigation_polygon));
}
int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index cf6011a0f9..9b921969c0 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -34,7 +34,7 @@
#include "core/object/class_db.h"
#include "core/templates/rid.h"
-#include "scene/2d/navigation_region_2d.h"
+#include "scene/resources/navigation_polygon.h"
#include "servers/navigation/navigation_path_query_parameters_2d.h"
#include "servers/navigation/navigation_path_query_result_2d.h"
@@ -126,7 +126,7 @@ public:
virtual void region_set_transform(RID p_region, Transform2D p_transform) const;
/// Set the navigation poly of this region.
- virtual void region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const;
+ virtual void region_set_navigation_polygon(RID p_region, Ref<NavigationPolygon> p_navigation_polygon) const;
/// Get a list of a region's connection to other regions.
virtual int region_get_connections_count(RID p_region) const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 940dd61f67..cbefe48633 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -77,8 +77,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer3D::region_set_navigation_layers);
ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer3D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform);
- ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh);
- ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_mesh", "region", "navigation_mesh"), &NavigationServer3D::region_set_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("region_bake_navigation_mesh", "navigation_mesh", "root_node"), &NavigationServer3D::region_bake_navigation_mesh);
ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer3D::region_get_connections_count);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_start);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_end);
@@ -155,7 +155,7 @@ NavigationServer3D::NavigationServer3D() {
debug_navigation_enable_link_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections_xray", true);
if (Engine::get_singleton()->is_editor_hint()) {
- // enable NavigationServer3D when in Editor or else navmesh edge connections are invisible
+ // enable NavigationServer3D when in Editor or else navigation mesh edge connections are invisible
// on runtime tests SceneTree has "Visible Navigation" set and main iteration takes care of this
set_debug_enabled(true);
}
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index bf4c22be8a..65d6d19073 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -138,10 +138,10 @@ public:
virtual void region_set_transform(RID p_region, Transform3D p_transform) const = 0;
/// Set the navigation mesh of this region.
- virtual void region_set_navmesh(RID p_region, Ref<NavigationMesh> p_nav_mesh) const = 0;
+ virtual void region_set_navigation_mesh(RID p_region, Ref<NavigationMesh> p_navigation_mesh) const = 0;
/// Bake the navigation mesh.
- virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const = 0;
+ virtual void region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) const = 0;
/// Get a list of a region's connection to other regions.
virtual int region_get_connections_count(RID p_region) const = 0;
diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp
index 79e084e90e..1684835e76 100644
--- a/servers/physics_2d/godot_body_pair_2d.cpp
+++ b/servers/physics_2d/godot_body_pair_2d.cpp
@@ -198,13 +198,13 @@ bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A,
Vector2 from = p_xform_A.xform(s[0]);
// Back up 10% of the per-frame motion behind the support point and use that as the beginning of our cast.
// This should ensure the calculated new velocity will really cause a bit of overlap instead of just getting us very close.
- from -= motion * 0.1;
Vector2 to = from + motion;
Transform2D from_inv = p_xform_B.affine_inverse();
- // Start from a little inside the bounding box.
- Vector2 local_from = from_inv.xform(from);
+ // Back up 10% of the per-frame motion behind the support point and use that as the beginning of our cast.
+ // At high speeds, this may mean we're actually casting from well behind the body instead of inside it, which is odd. But it still works out.
+ Vector2 local_from = from_inv.xform(from - motion * 0.1);
Vector2 local_to = from_inv.xform(to);
Vector2 rpos, rnorm;
@@ -228,7 +228,7 @@ bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A,
// next frame will hit softly or soft enough.
Vector2 hitpos = p_xform_B.xform(rpos);
- real_t newlen = hitpos.distance_to(from);
+ real_t newlen = hitpos.distance_to(from) + (max - min) * 0.01; // adding 1% of body length to the distance between collision and support point should cause body A's support point to arrive just within B's collider next frame.
p_A->set_linear_velocity(mnormal * (newlen / p_step));
return true;
diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp
index 981a7c502f..00b7941292 100644
--- a/servers/physics_3d/godot_body_pair_3d.cpp
+++ b/servers/physics_3d/godot_body_pair_3d.cpp
@@ -194,14 +194,13 @@ bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A,
// convert mnormal into body A's local xform because get_support requires (and returns) local coordinates.
Vector3 s = p_A->get_shape(p_shape_A)->get_support(p_xform_A.basis.xform_inv(mnormal).normalized());
Vector3 from = p_xform_A.xform(s);
- // Back up 10% of the per-frame motion behind the support point and use that as the beginning of our cast.
- // This should ensure the calculated new velocity will really cause a bit of overlap instead of just getting us very close.
- from -= motion * 0.1;
Vector3 to = from + motion;
Transform3D from_inv = p_xform_B.affine_inverse();
- Vector3 local_from = from_inv.xform(from);
+ // Back up 10% of the per-frame motion behind the support point and use that as the beginning of our cast.
+ // At high speeds, this may mean we're actually casting from well behind the body instead of inside it, which is odd. But it still works out.
+ Vector3 local_from = from_inv.xform(from - motion * 0.1);
Vector3 local_to = from_inv.xform(to);
Vector3 rpos, rnorm;
@@ -214,7 +213,8 @@ bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A,
// Shorten the linear velocity so it will collide next frame.
Vector3 hitpos = p_xform_B.xform(rpos);
- real_t newlen = hitpos.distance_to(from); // this length (speed) should cause the point we chose slightly behind A's support point to arrive right at B's collider next frame.
+ real_t newlen = hitpos.distance_to(from) + (max - min) * 0.01; // adding 1% of body length to the distance between collision and support point should cause body A's support point to arrive just within B's collider next frame.
+
p_A->set_linear_velocity((mnormal * newlen) / p_step);
return true;
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 33f1f38bf5..6be0419d98 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -1185,7 +1185,7 @@ void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
rect->texture = p_texture;
}
-void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range) {
+void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range, float p_scale) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1215,7 +1215,7 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co
rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;
rect->source.size.y = -rect->source.size.y;
}
- rect->outline = p_outline_size;
+ rect->outline = (float)p_outline_size / p_scale / 4.0;
rect->px_range = p_px_range;
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 198e1020f0..808c0acc35 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -228,7 +228,7 @@ public:
void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
- void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0);
+ void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0);
void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0);
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 662b582411..3de5083a8b 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -850,7 +850,7 @@ public:
FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
- FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float)
+ FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float)
FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &)
FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp
index 9b1842f1d9..78ce4eb4d0 100644
--- a/servers/rendering/storage/environment_storage.cpp
+++ b/servers/rendering/storage/environment_storage.cpp
@@ -283,7 +283,7 @@ void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool
env->volumetric_fog_scattering = p_albedo;
env->volumetric_fog_emission = p_emission;
env->volumetric_fog_emission_energy = p_emission_energy;
- env->volumetric_fog_anisotropy = p_anisotropy,
+ env->volumetric_fog_anisotropy = p_anisotropy;
env->volumetric_fog_length = p_length;
env->volumetric_fog_detail_spread = p_detail_spread;
env->volumetric_fog_gi_inject = p_gi_inject;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 8d6d756edc..49af56830a 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2596,7 +2596,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range", "scale"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)));
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 1d74bb54b9..5bdbf33c28 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -1339,7 +1339,7 @@ public:
virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0;
- virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0;
+ virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0) = 0;
virtual void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0;