summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp29
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/range_optimized_in_for_has_int_iterator.gd60
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/range_optimized_in_for_has_int_iterator.out1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/range_returns_ints.gd77
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/range_returns_ints.out1
-rw-r--r--modules/gltf/gltf_document.cpp2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs84
-rw-r--r--modules/text_server_adv/text_server_adv.cpp2
-rw-r--r--modules/tga/image_loader_tga.cpp8
-rw-r--r--modules/zip/zip_packer.cpp1
14 files changed, 231 insertions, 44 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 1401e4b94b..704dda8045 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -985,21 +985,26 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) {
if (getter_function == nullptr) {
push_error(vformat(R"(Getter "%s" not found.)", member.variable->getter_pointer->name), member.variable);
-
- } else if (getter_function->parameters.size() != 0 || getter_function->datatype.has_no_type()) {
- push_error(vformat(R"(Function "%s" cannot be used as getter because of its signature.)", getter_function->identifier->name), member.variable);
-
- } else if (!is_type_compatible(member.variable->datatype, getter_function->datatype, true)) {
- push_error(vformat(R"(Function with return type "%s" cannot be used as getter for a property of type "%s".)", getter_function->datatype.to_string(), member.variable->datatype.to_string()), member.variable);
-
} else {
- has_valid_getter = true;
+ GDScriptParser::DataType return_datatype = getter_function->datatype;
+ if (getter_function->return_type != nullptr) {
+ return_datatype = getter_function->return_type->datatype;
+ return_datatype.is_meta_type = false;
+ }
+
+ if (getter_function->parameters.size() != 0 || return_datatype.has_no_type()) {
+ push_error(vformat(R"(Function "%s" cannot be used as getter because of its signature.)", getter_function->identifier->name), member.variable);
+ } else if (!is_type_compatible(member.variable->datatype, return_datatype, true)) {
+ push_error(vformat(R"(Function with return type "%s" cannot be used as getter for a property of type "%s".)", return_datatype.to_string(), member.variable->datatype.to_string()), member.variable);
+ } else {
+ has_valid_getter = true;
#ifdef DEBUG_ENABLED
- if (member.variable->datatype.builtin_type == Variant::INT && getter_function->datatype.builtin_type == Variant::FLOAT) {
- parser->push_warning(member.variable, GDScriptWarning::NARROWING_CONVERSION);
- }
+ if (member.variable->datatype.builtin_type == Variant::INT && return_datatype.builtin_type == Variant::FLOAT) {
+ parser->push_warning(member.variable, GDScriptWarning::NARROWING_CONVERSION);
+ }
#endif
+ }
}
}
@@ -1377,7 +1382,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
if (all_is_constant) {
switch (args.size()) {
case 1:
- reduced = args[0];
+ reduced = (int32_t)args[0];
break;
case 2:
reduced = Vector2i(args[0], args[1]);
diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd
index c6645c2c34..809d0d28a9 100644
--- a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd
@@ -69,6 +69,10 @@ func test():
value = Transform3D()
print(value == null)
+ # Projection
+ value = Projection()
+ print(value == null)
+
# Color
value = Color()
print(value == null)
diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out
index 639f6027b9..27423ab8e7 100644
--- a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out
+++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out
@@ -33,3 +33,4 @@ false
false
false
false
+false
diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd
index ee622bf22f..f46afb0f18 100644
--- a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd
@@ -69,6 +69,10 @@ func test():
value = Transform3D()
print(value != null)
+ # Projection
+ value = Projection()
+ print(value != null)
+
# Color
value = Color()
print(value != null)
diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out
index d1e332afba..a11c47854a 100644
--- a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out
+++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out
@@ -33,3 +33,4 @@ true
true
true
true
+true
diff --git a/modules/gdscript/tests/scripts/runtime/features/range_optimized_in_for_has_int_iterator.gd b/modules/gdscript/tests/scripts/runtime/features/range_optimized_in_for_has_int_iterator.gd
new file mode 100644
index 0000000000..e24137a20d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/range_optimized_in_for_has_int_iterator.gd
@@ -0,0 +1,60 @@
+func test():
+ # All combinations of 1/2/3 arguments, each being int/float.
+
+ for number in range(5):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(5.2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+
+ for number in range(1, 5):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1, 5.2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1.2, 5):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1.2, 5.2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+
+ for number in range(1, 5, 2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1, 5, 2.2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1, 5.2, 2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1, 5.2, 2.2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1.2, 5, 2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1.2, 5.2, 2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1.2, 5, 2.2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ for number in range(1.2, 5.2, 2.2):
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
diff --git a/modules/gdscript/tests/scripts/runtime/features/range_optimized_in_for_has_int_iterator.out b/modules/gdscript/tests/scripts/runtime/features/range_optimized_in_for_has_int_iterator.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/range_optimized_in_for_has_int_iterator.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/runtime/features/range_returns_ints.gd b/modules/gdscript/tests/scripts/runtime/features/range_returns_ints.gd
new file mode 100644
index 0000000000..63c3b84305
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/range_returns_ints.gd
@@ -0,0 +1,77 @@
+func test():
+ # All combinations of 1/2/3 arguments, each being int/float.
+ # Store result in variable to ensure actual array is created (avoid `for` + `range` optimization).
+
+ var result
+
+ result = range(5)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(5.2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+
+ result = range(1, 5)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1, 5.2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1.2, 5)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1.2, 5.2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+
+ result = range(1, 5, 2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1, 5, 2.2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1, 5.2, 2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1, 5.2, 2.2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1.2, 5, 2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1.2, 5.2, 2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1.2, 5, 2.2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
+
+ result = range(1.2, 5.2, 2.2)
+ for number in result:
+ if typeof(number) != TYPE_INT:
+ print("Number returned from `range` was not an int!")
diff --git a/modules/gdscript/tests/scripts/runtime/features/range_returns_ints.out b/modules/gdscript/tests/scripts/runtime/features/range_returns_ints.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/range_returns_ints.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index cb148463a7..99803ed05d 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -6289,7 +6289,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
for (int32_t key_i = 0; key_i < key_count; key_i++) {
Vector3 rotation_radian = p_animation->track_get_key_value(p_track_i, key_i);
- p_track.rotation_track.values.write[key_i] = Quaternion(rotation_radian);
+ p_track.rotation_track.values.write[key_i] = Quaternion::from_euler(rotation_radian);
}
} else if (path.contains(":scale")) {
p_track.scale_track.times = times;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
index d459fe8c96..5dd629aeb0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
@@ -507,35 +507,6 @@ namespace Godot
}
/// <summary>
- /// Constructs a <see cref="Quaternion"/> that will perform a rotation specified by
- /// Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last),
- /// given in the vector format as (X angle, Y angle, Z angle).
- /// </summary>
- /// <param name="eulerYXZ">Euler angles that the quaternion will be rotated by.</param>
- public Quaternion(Vector3 eulerYXZ)
- {
- real_t halfA1 = eulerYXZ.y * 0.5f;
- real_t halfA2 = eulerYXZ.x * 0.5f;
- real_t halfA3 = eulerYXZ.z * 0.5f;
-
- // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
- // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
- // a3 is the angle of the first rotation, following the notation in this reference.
-
- real_t cosA1 = Mathf.Cos(halfA1);
- real_t sinA1 = Mathf.Sin(halfA1);
- real_t cosA2 = Mathf.Cos(halfA2);
- real_t sinA2 = Mathf.Sin(halfA2);
- real_t cosA3 = Mathf.Cos(halfA3);
- real_t sinA3 = Mathf.Sin(halfA3);
-
- x = (sinA1 * cosA2 * sinA3) + (cosA1 * sinA2 * cosA3);
- y = (sinA1 * cosA2 * cosA3) - (cosA1 * sinA2 * sinA3);
- z = (cosA1 * cosA2 * sinA3) - (sinA1 * sinA2 * cosA3);
- w = (sinA1 * sinA2 * sinA3) + (cosA1 * cosA2 * cosA3);
- }
-
- /// <summary>
/// Constructs a <see cref="Quaternion"/> that will rotate around the given axis
/// by the specified angle. The axis must be a normalized vector.
/// </summary>
@@ -572,6 +543,61 @@ namespace Godot
}
}
+ public Quaternion(Vector3 arcFrom, Vector3 arcTo)
+ {
+ Vector3 c = arcFrom.Cross(arcTo);
+ real_t d = arcFrom.Dot(arcTo);
+
+ if (d < -1.0f + Mathf.Epsilon)
+ {
+ x = 0f;
+ y = 1f;
+ z = 0f;
+ w = 0f;
+ }
+ else
+ {
+ real_t s = Mathf.Sqrt((1.0f + d) * 2.0f);
+ real_t rs = 1.0f / s;
+
+ x = c.x * rs;
+ y = c.y * rs;
+ z = c.z * rs;
+ w = s * 0.5f;
+ }
+ }
+
+ /// <summary>
+ /// Constructs a <see cref="Quaternion"/> that will perform a rotation specified by
+ /// Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last),
+ /// given in the vector format as (X angle, Y angle, Z angle).
+ /// </summary>
+ /// <param name="eulerYXZ">Euler angles that the quaternion will be rotated by.</param>
+ public static Quaternion FromEuler(Vector3 eulerYXZ)
+ {
+ real_t halfA1 = eulerYXZ.y * 0.5f;
+ real_t halfA2 = eulerYXZ.x * 0.5f;
+ real_t halfA3 = eulerYXZ.z * 0.5f;
+
+ // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
+ // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
+ // a3 is the angle of the first rotation, following the notation in this reference.
+
+ real_t cosA1 = Mathf.Cos(halfA1);
+ real_t sinA1 = Mathf.Sin(halfA1);
+ real_t cosA2 = Mathf.Cos(halfA2);
+ real_t sinA2 = Mathf.Sin(halfA2);
+ real_t cosA3 = Mathf.Cos(halfA3);
+ real_t sinA3 = Mathf.Sin(halfA3);
+
+ return new Quaternion(
+ (sinA1 * cosA2 * sinA3) + (cosA1 * sinA2 * cosA3),
+ (sinA1 * cosA2 * cosA3) - (cosA1 * sinA2 * sinA3),
+ (cosA1 * cosA2 * sinA3) - (sinA1 * sinA2 * cosA3),
+ (sinA1 * sinA2 * sinA3) + (cosA1 * cosA2 * cosA3)
+ );
+ }
+
/// <summary>
/// Composes these two quaternions by multiplying them together.
/// This has the effect of rotating the second quaternion
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index f310f46af9..155da3c67b 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -5072,6 +5072,8 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
p_sd->ascent = MAX(p_sd->ascent, get_hex_code_box_size(fs, gl.index).y);
} else {
gl.advance = get_hex_code_box_size(fs, gl.index).y;
+ gl.y_off = get_hex_code_box_size(fs, gl.index).y;
+ gl.x_off = -Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5);
p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5));
p_sd->descent = MAX(p_sd->descent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5));
}
diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp
index a6fc650414..8adde3c5d3 100644
--- a/modules/tga/image_loader_tga.cpp
+++ b/modules/tga/image_loader_tga.cpp
@@ -284,14 +284,21 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, Ref<FileAccess> f, BitField
err = FAILED;
}
+ uint64_t color_map_size;
if (has_color_map) {
if (tga_header.color_map_length > 256 || (tga_header.color_map_depth != 24) || tga_header.color_map_type != 1) {
err = FAILED;
}
+ color_map_size = tga_header.color_map_length * (tga_header.color_map_depth >> 3);
} else {
if (tga_header.color_map_type) {
err = FAILED;
}
+ color_map_size = 0;
+ }
+
+ if ((src_image_len - f->get_position()) < (tga_header.id_length + color_map_size)) {
+ err = FAILED; // TGA data appears to be truncated (fewer bytes than expected).
}
if (tga_header.image_width <= 0 || tga_header.image_height <= 0) {
@@ -308,7 +315,6 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, Ref<FileAccess> f, BitField
Vector<uint8_t> palette;
if (has_color_map) {
- size_t color_map_size = tga_header.color_map_length * (tga_header.color_map_depth >> 3);
err = palette.resize(color_map_size);
if (err == OK) {
uint8_t *palette_w = palette.ptrw();
diff --git a/modules/zip/zip_packer.cpp b/modules/zip/zip_packer.cpp
index c37fc0945e..e62700f191 100644
--- a/modules/zip/zip_packer.cpp
+++ b/modules/zip/zip_packer.cpp
@@ -50,7 +50,6 @@ Error ZIPPacker::close() {
}
Error ZIPPacker::start_file(String p_path) {
- ERR_FAIL_COND_V_MSG(zf != NULL, FAILED, "ZIPPacker is already in use.");
ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker must be opened before use.");
zip_fileinfo zipfi;