summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/Node2D.xml6
-rw-r--r--doc/classes/Node3D.xml6
-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/fbx_importer_manager.cpp158
-rw-r--r--editor/fbx_importer_manager.h66
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp6
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp3
-rw-r--r--editor/plugins/editor_preview_plugins.h20
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp3
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp17
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp1
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml1
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp2
-rw-r--r--modules/gdscript/gdscript_codegen.h2
-rw-r--r--modules/gdscript/language_server/godot_lsp.h2
-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/register_types.cpp17
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp3
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.h2
-rw-r--r--modules/openxr/editor/openxr_action_set_editor.cpp2
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.cpp4
-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--scene/2d/node_2d.cpp22
-rw-r--r--scene/2d/node_2d.h4
-rw-r--r--scene/2d/tile_map.cpp43
-rw-r--r--scene/3d/collision_shape_3d.cpp11
-rw-r--r--scene/3d/node_3d.cpp30
-rw-r--r--scene/3d/node_3d.h4
-rw-r--r--scene/animation/animation_blend_tree.cpp11
-rw-r--r--scene/animation/animation_node_state_machine.cpp5
-rw-r--r--scene/gui/code_edit.cpp20
-rw-r--r--scene/gui/control.cpp11
-rw-r--r--scene/gui/control.h2
-rw-r--r--scene/main/canvas_item.cpp24
-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/viewport.cpp2
-rw-r--r--scene/resources/tile_set.cpp55
-rw-r--r--servers/audio_server.cpp8
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp4
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp2
-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
-rw-r--r--tests/scene/test_code_edit.h83
57 files changed, 780 insertions, 201 deletions
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/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/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/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/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 5183a738ae..de16400ec9 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -1922,10 +1922,12 @@ void AnimationPlayerEditorPlugin::_notification(int p_what) {
}
void AnimationPlayerEditorPlugin::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
- if (!anim_editor->get_track_editor()->has_keying()) {
+ AnimationTrackEditor *te = anim_editor->get_track_editor();
+ if (!te || !te->has_keying()) {
return;
}
- anim_editor->get_track_editor()->insert_value_key(p_keyed, p_value, p_advance);
+ te->_clear_selection();
+ te->insert_value_key(p_keyed, p_value, p_advance);
}
void AnimationPlayerEditorPlugin::_transform_key_request(Object *sp, const String &p_sub, const Transform3D &p_key) {
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
index 719ae09f47..60d949cdf0 100644
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -34,6 +34,7 @@
#include "editor/audio_stream_preview.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "scene/resources/audio_stream_wav.h"
// AudioStreamEditor
@@ -258,7 +259,7 @@ AudioStreamEditor::AudioStreamEditor() {
// EditorInspectorPluginAudioStream
bool EditorInspectorPluginAudioStream::can_handle(Object *p_object) {
- return Object::cast_to<AudioStream>(p_object) != nullptr;
+ return Object::cast_to<AudioStreamWAV>(p_object) != nullptr;
}
void EditorInspectorPluginAudioStream::parse_begin(Object *p_object) {
diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h
index efb2c80cfd..0f8ed1c857 100644
--- a/editor/plugins/editor_preview_plugins.h
+++ b/editor/plugins/editor_preview_plugins.h
@@ -70,10 +70,12 @@ public:
};
class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator {
+ GDCLASS(EditorPackedScenePreviewPlugin, EditorResourcePreviewGenerator);
+
public:
- virtual bool handles(const String &p_type) const;
- virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const;
- virtual Ref<Texture2D> generate_from_path(const String &p_path, const Size2 &p_size) const;
+ virtual bool handles(const String &p_type) const override;
+ virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const override;
+ virtual Ref<Texture2D> generate_from_path(const String &p_path, const Size2 &p_size) const override;
EditorPackedScenePreviewPlugin();
};
@@ -107,17 +109,21 @@ public:
};
class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
+ GDCLASS(EditorScriptPreviewPlugin, EditorResourcePreviewGenerator);
+
public:
- virtual bool handles(const String &p_type) const;
- virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const;
+ virtual bool handles(const String &p_type) const override;
+ virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const override;
EditorScriptPreviewPlugin();
};
class EditorAudioStreamPreviewPlugin : public EditorResourcePreviewGenerator {
+ GDCLASS(EditorAudioStreamPreviewPlugin, EditorResourcePreviewGenerator);
+
public:
- virtual bool handles(const String &p_type) const;
- virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const;
+ virtual bool handles(const String &p_type) const override;
+ virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size) const override;
EditorAudioStreamPreviewPlugin();
};
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index f79a001efb..d2dadd884b 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -153,9 +153,10 @@ void BoneTransformEditor::set_target(const String &p_prop) {
void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance) {
AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
- if (!te->has_keying()) {
+ if (!te || !te->has_keying()) {
return;
}
+ te->_clear_selection();
PackedStringArray split = p_path.split("/");
if (split.size() == 3 && split[0] == "bones") {
int bone_idx = split[1].to_int();
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/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 4981750b7d..fd748ea569 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -106,6 +106,7 @@
<param index="0" name="instance" type="Object" />
<description>
Returns the passed [param instance] converted to a Dictionary. Can be useful for serializing.
+ [b]Note:[/b] Cannot be used to serialize objects with built-in scripts attached or objects allocated within built-in scripts.
[codeblock]
var foo = "bar"
func _ready():
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 5af0b22d44..1a1c2193bf 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -3627,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) {
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/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/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/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/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index 844423afc0..71fcd3ce7f 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -205,11 +205,12 @@ void OpenXRActionMapEditor::_on_remove_action_set(Object *p_action_set_editor) {
action_map->set_edited(true);
}
-void OpenXRActionMapEditor::_on_action_removed() {
+void OpenXRActionMapEditor::_on_action_removed(Ref<OpenXRAction> p_action) {
for (int i = 0; i < tabs->get_tab_count(); i++) {
// First tab won't be an interaction profile editor, but being thorough..
OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(i));
if (interaction_profile_editor) {
+ interaction_profile_editor->remove_all_bindings_for_action(p_action);
}
}
}
diff --git a/modules/openxr/editor/openxr_action_map_editor.h b/modules/openxr/editor/openxr_action_map_editor.h
index 8e3210a8e9..2ff6ddf785 100644
--- a/modules/openxr/editor/openxr_action_map_editor.h
+++ b/modules/openxr/editor/openxr_action_map_editor.h
@@ -75,7 +75,7 @@ private:
void _on_add_action_set();
void _set_focus_on_action_set(OpenXRActionSetEditor *p_action_set_editor);
void _on_remove_action_set(Object *p_action_set_editor);
- void _on_action_removed();
+ void _on_action_removed(Ref<OpenXRAction> p_action);
void _on_add_interaction_profile();
void _on_interaction_profile_selected(const String p_path);
diff --git a/modules/openxr/editor/openxr_action_set_editor.cpp b/modules/openxr/editor/openxr_action_set_editor.cpp
index d3b6945635..7f4da8b312 100644
--- a/modules/openxr/editor/openxr_action_set_editor.cpp
+++ b/modules/openxr/editor/openxr_action_set_editor.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "openxr_action_set_editor.h"
+#include "editor/editor_node.h"
#include "openxr_action_editor.h"
void OpenXRActionSetEditor::_bind_methods() {
@@ -211,6 +212,7 @@ void OpenXRActionSetEditor::set_focus_on_entry() {
}
OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set) {
+ undo_redo = EditorNode::get_undo_redo();
action_map = p_action_map;
action_set = p_action_set;
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
index ee73f6a5cd..9d8ac76187 100644
--- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
@@ -124,8 +124,8 @@ void OpenXRInteractionProfileEditorBase::remove_all_bindings_for_action(Ref<Open
undo_redo->create_action(TTR("Remove action from interaction profile"));
PackedStringArray paths = binding->get_paths();
for (const String &path : paths) {
- undo_redo->add_do_method(this, "_remove_binding", p_action, path);
- undo_redo->add_undo_method(this, "_add_binding", p_action, path);
+ undo_redo->add_do_method(this, "_remove_binding", action_name, path);
+ undo_redo->add_undo_method(this, "_add_binding", action_name, path);
}
undo_redo->commit_action(false);
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/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 00ac4e87b5..6ab13c9aa7 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -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/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index ef381641ab..2729dfc369 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -34,6 +34,7 @@
#include "physics_body_3d.h"
#include "scene/resources/concave_polygon_shape_3d.h"
#include "scene/resources/convex_polygon_shape_3d.h"
+#include "scene/resources/world_boundary_shape_3d.h"
void CollisionShape3D::make_convex_from_siblings() {
Node *p = get_parent();
@@ -125,10 +126,12 @@ PackedStringArray CollisionShape3D::get_configuration_warnings() const {
warnings.push_back(RTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it."));
}
- if (shape.is_valid() &&
- Object::cast_to<RigidBody3D>(get_parent()) &&
- Object::cast_to<ConcavePolygonShape3D>(*shape)) {
- warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static."));
+ if (shape.is_valid() && Object::cast_to<RigidBody3D>(get_parent())) {
+ if (Object::cast_to<ConcavePolygonShape3D>(*shape)) {
+ warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static."));
+ } else if (Object::cast_to<WorldBoundaryShape3D>(*shape)) {
+ warnings.push_back(RTR("WorldBoundaryShape3D doesn't support RigidBody3D in another mode than static."));
+ }
}
return warnings;
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/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 6200062f60..d10b271b79 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -351,7 +351,7 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_is_exter
} else {
main_rem = blend_input(0, p_time, p_seek, p_is_external_seeking, 1.0 - blend, FILTER_BLEND, sync); // Unlike below, processing this edge is a corner case.
}
- double os_rem = blend_input(1, os_seek ? cur_time : p_time, os_seek, p_is_external_seeking, MAX(CMP_EPSILON, blend), FILTER_PASS, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
+ double os_rem = blend_input(1, os_seek ? cur_time : p_time, os_seek, p_is_external_seeking, Math::is_zero_approx(blend) ? CMP_EPSILON : blend, FILTER_PASS, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
if (do_start) {
cur_remaining = os_rem;
@@ -769,17 +769,18 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_ex
}
// Blend values must be more than CMP_EPSILON to process discrete keys in edge.
+ real_t blend_inv = 1.0 - blend;
if (from_start && !p_seek && switched) { //just switched, seek to start of current
- rem = blend_input(cur_current, 0, true, p_is_external_seeking, MAX(CMP_EPSILON, 1.0 - blend), FILTER_IGNORE, true);
+ rem = blend_input(cur_current, 0, true, p_is_external_seeking, Math::is_zero_approx(blend_inv) ? CMP_EPSILON : blend_inv, FILTER_IGNORE, true);
} else {
- rem = blend_input(cur_current, p_time, p_seek, p_is_external_seeking, MAX(CMP_EPSILON, 1.0 - blend), FILTER_IGNORE, true);
+ rem = blend_input(cur_current, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(blend_inv) ? CMP_EPSILON : blend_inv, FILTER_IGNORE, true);
}
if (p_seek) {
- blend_input(cur_prev, p_time, true, p_is_external_seeking, MAX(CMP_EPSILON, blend), FILTER_IGNORE, true);
+ blend_input(cur_prev, p_time, true, p_is_external_seeking, Math::is_zero_approx(blend) ? CMP_EPSILON : blend, FILTER_IGNORE, true);
cur_time = p_time;
} else {
- blend_input(cur_prev, p_time, false, p_is_external_seeking, MAX(CMP_EPSILON, blend), FILTER_IGNORE, true);
+ blend_input(cur_prev, p_time, false, p_is_external_seeking, Math::is_zero_approx(blend) ? CMP_EPSILON : blend, FILTER_IGNORE, true);
cur_time += p_time;
cur_prev_xfading -= p_time;
if (cur_prev_xfading < 0) {
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index d3746c1144..293e04eb1f 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -433,10 +433,11 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
if (current_curve.is_valid()) {
fade_blend = current_curve->sample(fade_blend);
}
- float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_is_external_seeking, MAX(CMP_EPSILON, fade_blend), AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
+ float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(fade_blend) ? CMP_EPSILON : fade_blend, AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
+ float fade_blend_inv = 1.0 - fade_blend;
if (fading_from != StringName()) {
- p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_is_external_seeking, MAX(CMP_EPSILON, 1.0 - fade_blend), AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
+ p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_is_external_seeking, Math::is_zero_approx(fade_blend_inv) ? CMP_EPSILON : fade_blend_inv, AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
}
//guess playback position
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 3bb02ebf7f..c84438ed5e 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -2081,20 +2081,22 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
}
char32_t last_completion_char_display = display_text[display_text.length() - 1];
+ bool last_char_matches = (last_completion_char == next_char || last_completion_char_display == next_char);
int pre_brace_pair = get_caret_column(i) > 0 ? _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column(i)) : -1;
int post_brace_pair = get_caret_column(i) < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column(i)) : -1;
- if (post_brace_pair != -1 && (last_completion_char == next_char || last_completion_char_display == next_char)) {
+ // Strings do not nest like brackets, so ensure we don't add an additional closing pair.
+ if (has_string_delimiter(String::chr(last_completion_char)) && post_brace_pair != -1 && last_char_matches) {
remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
- }
-
- if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && (last_completion_char == next_char || last_completion_char_display == next_char)) {
- remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
- adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
- } else if (auto_brace_completion_enabled && pre_brace_pair != -1 && post_brace_pair == -1) {
- insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key, i);
- set_caret_column(get_caret_column(i) - auto_brace_completion_pairs[pre_brace_pair].close_key.length(), i == 0, i);
+ } else {
+ if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && last_char_matches) {
+ remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
+ adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
+ } else if (auto_brace_completion_enabled && pre_brace_pair != -1) {
+ insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key, i);
+ set_caret_column(get_caret_column(i) - auto_brace_completion_pairs[pre_brace_pair].close_key.length(), i == 0, i);
+ }
}
if (pre_brace_pair == -1 && post_brace_pair == -1 && get_caret_column(i) > 0 && get_caret_column(i) < get_line(caret_line).length()) {
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/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 2563fa5914..f3812eb497 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) {
@@ -950,14 +950,14 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_self_modulate", "self_modulate"), &CanvasItem::set_self_modulate);
ClassDB::bind_method(D_METHOD("get_self_modulate"), &CanvasItem::get_self_modulate);
- ClassDB::bind_method(D_METHOD("set_z_index", "z_index"), &Node2D::set_z_index);
- ClassDB::bind_method(D_METHOD("get_z_index"), &Node2D::get_z_index);
+ ClassDB::bind_method(D_METHOD("set_z_index", "z_index"), &CanvasItem::set_z_index);
+ ClassDB::bind_method(D_METHOD("get_z_index"), &CanvasItem::get_z_index);
- ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &Node2D::set_z_as_relative);
- ClassDB::bind_method(D_METHOD("is_z_relative"), &Node2D::is_z_relative);
+ ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &CanvasItem::set_z_as_relative);
+ ClassDB::bind_method(D_METHOD("is_z_relative"), &CanvasItem::is_z_relative);
- ClassDB::bind_method(D_METHOD("set_y_sort_enabled", "enabled"), &Node2D::set_y_sort_enabled);
- ClassDB::bind_method(D_METHOD("is_y_sort_enabled"), &Node2D::is_y_sort_enabled);
+ ClassDB::bind_method(D_METHOD("set_y_sort_enabled", "enabled"), &CanvasItem::set_y_sort_enabled);
+ ClassDB::bind_method(D_METHOD("is_y_sort_enabled"), &CanvasItem::is_y_sort_enabled);
ClassDB::bind_method(D_METHOD("set_draw_behind_parent", "enable"), &CanvasItem::set_draw_behind_parent);
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
@@ -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/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/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 9b9e55d0bc..0b0461432b 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -476,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();
@@ -516,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();
@@ -1296,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++) {
@@ -1308,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++) {
@@ -1321,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++) {
@@ -1438,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;
@@ -1458,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);
@@ -3853,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;
@@ -4027,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);
@@ -4342,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;
@@ -4364,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);
@@ -4394,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);
@@ -4682,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();
@@ -4699,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/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/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/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 350a5eb0e4..b60396c7af 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -154,8 +154,8 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBu
render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples);
- format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, usage_bits) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples);
}
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;
diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h
index 326b55d07a..fa31a3a461 100644
--- a/tests/scene/test_code_edit.h
+++ b/tests/scene/test_code_edit.h
@@ -2871,6 +2871,89 @@ TEST_CASE("[SceneTree][CodeEdit] completion") {
CHECK(code_edit->get_text() == "\'\'\'");
}
+ SUBCASE("[CodeEdit] autocomplete with brace completion") {
+ code_edit->set_auto_brace_completion_enabled(true);
+ CHECK(code_edit->is_auto_brace_completion_enabled());
+
+ code_edit->insert_text_at_caret("(te)");
+ code_edit->set_caret_column(3);
+
+ // Full completion.
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test()", "test()");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "(test())");
+ CHECK(code_edit->get_caret_column() == 7);
+ code_edit->undo();
+
+ // With "arg".
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test(", "test(");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "(test())");
+ CHECK(code_edit->get_caret_column() == 6);
+ code_edit->undo();
+
+ // brace completion disbaled
+ code_edit->set_auto_brace_completion_enabled(false);
+
+ // Full completion.
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test()", "test()");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "(test())");
+ CHECK(code_edit->get_caret_column() == 7);
+ code_edit->undo();
+
+ // With "arg".
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_FUNCTION, "test(", "test(");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "(test()");
+ CHECK(code_edit->get_caret_column() == 6);
+
+ // String
+ code_edit->set_auto_brace_completion_enabled(true);
+ code_edit->clear();
+ code_edit->insert_text_at_caret("\"\"");
+ code_edit->set_caret_column(1);
+
+ // Full completion.
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test\"", "\"test\"");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "\"test\"");
+ CHECK(code_edit->get_caret_column() == 6);
+ code_edit->undo();
+
+ // With "arg".
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test", "\"test");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "\"\"test\"\"");
+ CHECK(code_edit->get_caret_column() == 7);
+ code_edit->undo();
+
+ // brace completion disbaled
+ code_edit->set_auto_brace_completion_enabled(false);
+
+ // Full completion.
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test\"", "\"test\"");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "\"test\"");
+ CHECK(code_edit->get_caret_column() == 6);
+ code_edit->undo();
+
+ // With "arg".
+ code_edit->add_code_completion_option(CodeEdit::CodeCompletionKind::KIND_NODE_PATH, "\"test", "\"test");
+ code_edit->update_code_completion_options();
+ code_edit->confirm_code_completion();
+ CHECK(code_edit->get_line(0) == "\"\"test\"");
+ CHECK(code_edit->get_caret_column() == 7);
+ code_edit->undo();
+ }
+
SUBCASE("[CodeEdit] autocomplete") {
code_edit->set_code_completion_enabled(true);
CHECK(code_edit->is_code_completion_enabled());