summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/core/input/test_input_event_key.h8
-rw-r--r--tests/core/io/test_config_file.h2
-rw-r--r--tests/core/io/test_image.h4
-rw-r--r--tests/core/io/test_pck_packer.h16
-rw-r--r--tests/core/io/test_resource.h4
-rw-r--r--tests/core/io/test_xml_parser.h164
-rw-r--r--tests/core/math/test_aabb.h17
-rw-r--r--tests/core/math/test_basis.h57
-rw-r--r--tests/core/math/test_geometry_3d.h2
-rw-r--r--tests/core/math/test_quaternion.h52
-rw-r--r--tests/core/math/test_rect2.h16
-rw-r--r--tests/core/math/test_rect2i.h16
-rw-r--r--tests/core/math/test_vector2.h83
-rw-r--r--tests/core/math/test_vector2i.h16
-rw-r--r--tests/core/math/test_vector3.h73
-rw-r--r--tests/core/math/test_vector3i.h8
-rw-r--r--tests/core/math/test_vector4.h8
-rw-r--r--tests/core/math/test_vector4i.h8
-rw-r--r--tests/core/object/test_class_db.h4
-rw-r--r--tests/core/string/test_string.h89
-rw-r--r--tests/core/variant/test_dictionary.h18
-rw-r--r--tests/scene/test_audio_stream_wav.h8
-rw-r--r--tests/scene/test_bit_map.h445
-rw-r--r--tests/scene/test_code_edit.h2
-rw-r--r--tests/scene/test_curve.h74
-rw-r--r--tests/scene/test_path_follow_2d.h94
-rw-r--r--tests/scene/test_path_follow_3d.h94
-rw-r--r--tests/scene/test_text_edit.h54
-rw-r--r--tests/test_macros.h7
-rw-r--r--tests/test_main.cpp18
-rw-r--r--tests/test_utils.cpp2
31 files changed, 1211 insertions, 252 deletions
diff --git a/tests/core/input/test_input_event_key.h b/tests/core/input/test_input_event_key.h
index 5d4ca55a35..ef0a656b18 100644
--- a/tests/core/input/test_input_event_key.h
+++ b/tests/core/input/test_input_event_key.h
@@ -118,7 +118,7 @@ TEST_CASE("[InputEventKey] Key correctly converts itself to text") {
InputEventKey none_key2;
- // Key is None without modifers with a physical key.
+ // Key is None without modifiers with a physical key.
none_key2.set_keycode(Key::NONE);
none_key2.set_physical_keycode(Key::ENTER);
@@ -148,7 +148,7 @@ TEST_CASE("[InputEventKey] Key correctly converts its state to a string represen
CHECK(none_key.to_string() == "InputEventKey: keycode=0 (), mods=none, physical=true, pressed=false, echo=false");
// Set physical key to Escape.
none_key.set_physical_keycode(Key::ESCAPE);
- CHECK(none_key.to_string() == "InputEventKey: keycode=16777217 (Escape), mods=none, physical=true, pressed=false, echo=false");
+ CHECK(none_key.to_string() == "InputEventKey: keycode=4194305 (Escape), mods=none, physical=true, pressed=false, echo=false");
InputEventKey key;
@@ -167,7 +167,11 @@ TEST_CASE("[InputEventKey] Key correctly converts its state to a string represen
// Press Ctrl and Alt.
key.set_ctrl_pressed(true);
key.set_alt_pressed(true);
+#ifdef MACOS_ENABLED
+ CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=Ctrl+Option, physical=false, pressed=true, echo=true");
+#else
CHECK(key.to_string() == "InputEventKey: keycode=32 (Space), mods=Ctrl+Alt, physical=false, pressed=true, echo=true");
+#endif
}
TEST_CASE("[InputEventKey] Key is correctly converted to reference") {
diff --git a/tests/core/io/test_config_file.h b/tests/core/io/test_config_file.h
index 355aca479e..666719febb 100644
--- a/tests/core/io/test_config_file.h
+++ b/tests/core/io/test_config_file.h
@@ -127,7 +127,7 @@ TEST_CASE("[ConfigFile] Saving file") {
config_file.set_value("quoted", "a=b", 7);
#ifdef WINDOWS_ENABLED
- const String config_path = OS::get_singleton()->get_environment("TEMP").plus_file("config.ini");
+ const String config_path = OS::get_singleton()->get_environment("TEMP").path_join("config.ini");
#else
const String config_path = "/tmp/config.ini";
#endif
diff --git a/tests/core/io/test_image.h b/tests/core/io/test_image.h
index 36e6b83bfd..38b616cda0 100644
--- a/tests/core/io/test_image.h
+++ b/tests/core/io/test_image.h
@@ -78,8 +78,8 @@ TEST_CASE("[Image] Instantiation") {
TEST_CASE("[Image] Saving and loading") {
Ref<Image> image = memnew(Image(4, 4, false, Image::FORMAT_RGBA8));
- const String save_path_png = OS::get_singleton()->get_cache_path().plus_file("image.png");
- const String save_path_exr = OS::get_singleton()->get_cache_path().plus_file("image.exr");
+ const String save_path_png = OS::get_singleton()->get_cache_path().path_join("image.png");
+ const String save_path_exr = OS::get_singleton()->get_cache_path().path_join("image.exr");
// Save PNG
Error err;
diff --git a/tests/core/io/test_pck_packer.h b/tests/core/io/test_pck_packer.h
index d21fbdaf50..8d0e5c402a 100644
--- a/tests/core/io/test_pck_packer.h
+++ b/tests/core/io/test_pck_packer.h
@@ -42,7 +42,7 @@ namespace TestPCKPacker {
TEST_CASE("[PCKPacker] Pack an empty PCK file") {
PCKPacker pck_packer;
- const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck");
+ const String output_pck_path = OS::get_singleton()->get_cache_path().path_join("output_empty.pck");
CHECK_MESSAGE(
pck_packer.pck_start(output_pck_path) == OK,
"Starting a PCK file should return an OK error code.");
@@ -66,7 +66,7 @@ TEST_CASE("[PCKPacker] Pack an empty PCK file") {
TEST_CASE("[PCKPacker] Pack empty with zero alignment invalid") {
PCKPacker pck_packer;
- const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck");
+ const String output_pck_path = OS::get_singleton()->get_cache_path().path_join("output_empty.pck");
ERR_PRINT_OFF;
CHECK_MESSAGE(pck_packer.pck_start(output_pck_path, 0) != OK, "PCK with zero alignment should fail.");
ERR_PRINT_ON;
@@ -74,7 +74,7 @@ TEST_CASE("[PCKPacker] Pack empty with zero alignment invalid") {
TEST_CASE("[PCKPacker] Pack empty with invalid key") {
PCKPacker pck_packer;
- const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_empty.pck");
+ const String output_pck_path = OS::get_singleton()->get_cache_path().path_join("output_empty.pck");
ERR_PRINT_OFF;
CHECK_MESSAGE(pck_packer.pck_start(output_pck_path, 32, "") != OK, "PCK with invalid key should fail.");
ERR_PRINT_ON;
@@ -82,7 +82,7 @@ TEST_CASE("[PCKPacker] Pack empty with invalid key") {
TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") {
PCKPacker pck_packer;
- const String output_pck_path = OS::get_singleton()->get_cache_path().plus_file("output_with_files.pck");
+ const String output_pck_path = OS::get_singleton()->get_cache_path().path_join("output_with_files.pck");
CHECK_MESSAGE(
pck_packer.pck_start(output_pck_path) == OK,
"Starting a PCK file should return an OK error code.");
@@ -90,16 +90,16 @@ TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") {
const String base_dir = OS::get_singleton()->get_executable_path().get_base_dir();
CHECK_MESSAGE(
- pck_packer.add_file("version.py", base_dir.plus_file("../version.py"), "version.py") == OK,
+ pck_packer.add_file("version.py", base_dir.path_join("../version.py"), "version.py") == OK,
"Adding a file to the PCK should return an OK error code.");
CHECK_MESSAGE(
- pck_packer.add_file("some/directories with spaces/to/create/icon.png", base_dir.plus_file("../icon.png")) == OK,
+ pck_packer.add_file("some/directories with spaces/to/create/icon.png", base_dir.path_join("../icon.png")) == OK,
"Adding a file to a new subdirectory in the PCK should return an OK error code.");
CHECK_MESSAGE(
- pck_packer.add_file("some/directories with spaces/to/create/icon.svg", base_dir.plus_file("../icon.svg")) == OK,
+ pck_packer.add_file("some/directories with spaces/to/create/icon.svg", base_dir.path_join("../icon.svg")) == OK,
"Adding a file to an existing subdirectory in the PCK should return an OK error code.");
CHECK_MESSAGE(
- pck_packer.add_file("some/directories with spaces/to/create/icon.png", base_dir.plus_file("../logo.png")) == OK,
+ pck_packer.add_file("some/directories with spaces/to/create/icon.png", base_dir.path_join("../logo.png")) == OK,
"Overriding a non-flushed file to an existing subdirectory in the PCK should return an OK error code.");
CHECK_MESSAGE(
pck_packer.flush() == OK,
diff --git a/tests/core/io/test_resource.h b/tests/core/io/test_resource.h
index c880ca7d2a..2457e06ade 100644
--- a/tests/core/io/test_resource.h
+++ b/tests/core/io/test_resource.h
@@ -74,8 +74,8 @@ TEST_CASE("[Resource] Saving and loading") {
Ref<Resource> child_resource = memnew(Resource);
child_resource->set_name("I'm a child resource");
resource->set_meta("other_resource", child_resource);
- const String save_path_binary = OS::get_singleton()->get_cache_path().plus_file("resource.res");
- const String save_path_text = OS::get_singleton()->get_cache_path().plus_file("resource.tres");
+ const String save_path_binary = OS::get_singleton()->get_cache_path().path_join("resource.res");
+ const String save_path_text = OS::get_singleton()->get_cache_path().path_join("resource.tres");
ResourceSaver::save(resource, save_path_binary);
ResourceSaver::save(resource, save_path_text);
diff --git a/tests/core/io/test_xml_parser.h b/tests/core/io/test_xml_parser.h
index 87592b56ce..35e86d8203 100644
--- a/tests/core/io/test_xml_parser.h
+++ b/tests/core/io/test_xml_parser.h
@@ -66,6 +66,170 @@ TEST_CASE("[XMLParser] End-to-end") {
parser.close();
}
+
+TEST_CASE("[XMLParser] Comments") {
+ XMLParser parser;
+
+ SUBCASE("Missing end of comment") {
+ const String input = "<first></first><!-- foo";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
+ CHECK_EQ(parser.get_node_name(), " foo");
+ }
+ SUBCASE("Bad start of comment") {
+ const String input = "<first></first><!-";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
+ CHECK_EQ(parser.get_node_name(), "-");
+ }
+ SUBCASE("Unblanced angle brackets in comment") {
+ const String input = "<!-- example << --><next-tag></next-tag>";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
+ CHECK_EQ(parser.get_node_name(), " example << ");
+ }
+ SUBCASE("Doctype") {
+ const String input = "<!DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]>";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
+ CHECK_EQ(parser.get_node_name(), "DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]");
+ }
+}
+
+TEST_CASE("[XMLParser] Premature endings") {
+ SUBCASE("Simple cases") {
+ String input;
+ String expected_name;
+ XMLParser::NodeType expected_type;
+
+ SUBCASE("Incomplete Unknown") {
+ input = "<first></first><?xml";
+ expected_type = XMLParser::NodeType::NODE_UNKNOWN;
+ expected_name = "?xml";
+ }
+ SUBCASE("Incomplete CDStart") {
+ input = "<first></first><![CD";
+ expected_type = XMLParser::NodeType::NODE_CDATA;
+ expected_name = "";
+ }
+ SUBCASE("Incomplete CData") {
+ input = "<first></first><![CDATA[example";
+ expected_type = XMLParser::NodeType::NODE_CDATA;
+ expected_name = "example";
+ }
+ SUBCASE("Incomplete CDEnd") {
+ input = "<first></first><![CDATA[example]]";
+ expected_type = XMLParser::NodeType::NODE_CDATA;
+ expected_name = "example]]";
+ }
+ SUBCASE("Incomplete start-tag name") {
+ input = "<first></first><second";
+ expected_type = XMLParser::NodeType::NODE_ELEMENT;
+ expected_name = "second";
+ }
+
+ XMLParser parser;
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), expected_type);
+ CHECK_EQ(parser.get_node_name(), expected_name);
+ }
+
+ SUBCASE("With attributes and texts") {
+ XMLParser parser;
+
+ SUBCASE("Incomplete start-tag attribute name") {
+ const String input = "<first></first><second attr1=\"foo\" attr2";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ CHECK_EQ(parser.get_node_name(), "second");
+ CHECK_EQ(parser.get_attribute_count(), 1);
+ CHECK_EQ(parser.get_attribute_name(0), "attr1");
+ CHECK_EQ(parser.get_attribute_value(0), "foo");
+ }
+
+ SUBCASE("Incomplete start-tag attribute unquoted value") {
+ const String input = "<first></first><second attr1=\"foo\" attr2=bar";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ CHECK_EQ(parser.get_node_name(), "second");
+ CHECK_EQ(parser.get_attribute_count(), 1);
+ CHECK_EQ(parser.get_attribute_name(0), "attr1");
+ CHECK_EQ(parser.get_attribute_value(0), "foo");
+ }
+
+ SUBCASE("Incomplete start-tag attribute quoted value") {
+ const String input = "<first></first><second attr1=\"foo\" attr2=\"bar";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ CHECK_EQ(parser.get_node_name(), "second");
+ CHECK_EQ(parser.get_attribute_count(), 2);
+ CHECK_EQ(parser.get_attribute_name(0), "attr1");
+ CHECK_EQ(parser.get_attribute_value(0), "foo");
+ CHECK_EQ(parser.get_attribute_name(1), "attr2");
+ CHECK_EQ(parser.get_attribute_value(1), "bar");
+ }
+
+ SUBCASE("Incomplete end-tag name") {
+ const String input = "<first></fir";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ CHECK_EQ(parser.get_node_name(), "fir");
+ }
+
+ SUBCASE("Trailing text") {
+ const String input = "<first></first>example";
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_TEXT);
+ CHECK_EQ(parser.get_node_data(), "example");
+ }
+ }
+}
+
+TEST_CASE("[XMLParser] CDATA") {
+ const String input = "<a><![CDATA[my cdata content goes here]]></a>";
+ XMLParser parser;
+ REQUIRE_EQ(parser.open_buffer(input.to_utf8_buffer()), OK);
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
+ CHECK_EQ(parser.get_node_name(), "a");
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_CDATA);
+ CHECK_EQ(parser.get_node_name(), "my cdata content goes here");
+ REQUIRE_EQ(parser.read(), OK);
+ CHECK_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
+ CHECK_EQ(parser.get_node_name(), "a");
+}
} // namespace TestXMLParser
#endif // TEST_XML_PARSER_H
diff --git a/tests/core/math/test_aabb.h b/tests/core/math/test_aabb.h
index 447420fc12..d5f54a139e 100644
--- a/tests/core/math/test_aabb.h
+++ b/tests/core/math/test_aabb.h
@@ -94,7 +94,7 @@ TEST_CASE("[AABB] Volume getters") {
Math::is_equal_approx(aabb.get_volume(), 120),
"get_volume() should return the expected value with positive size.");
CHECK_MESSAGE(
- !aabb.has_no_volume(),
+ aabb.has_volume(),
"Non-empty volumetric AABB should have a volume.");
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, 5, 6));
@@ -114,27 +114,32 @@ TEST_CASE("[AABB] Volume getters") {
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 0, 6));
CHECK_MESSAGE(
- aabb.has_no_volume(),
+ !aabb.has_volume(),
"Non-empty flat AABB should not have a volume.");
CHECK_MESSAGE(
- AABB().has_no_volume(),
+ !AABB().has_volume(),
"Empty AABB should not have a volume.");
}
TEST_CASE("[AABB] Surface getters") {
AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
- !aabb.has_no_surface(),
+ aabb.has_surface(),
"Non-empty volumetric AABB should have an surface.");
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 0, 6));
CHECK_MESSAGE(
- !aabb.has_no_surface(),
+ aabb.has_surface(),
"Non-empty flat AABB should have a surface.");
+ aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 0, 0));
CHECK_MESSAGE(
- AABB().has_no_surface(),
+ aabb.has_surface(),
+ "Non-empty linear AABB should have a surface.");
+
+ CHECK_MESSAGE(
+ !AABB().has_surface(),
"Empty AABB should not have an surface.");
}
diff --git a/tests/core/math/test_basis.h b/tests/core/math/test_basis.h
index ae8ca4acde..b6493c5726 100644
--- a/tests/core/math/test_basis.h
+++ b/tests/core/math/test_basis.h
@@ -47,7 +47,7 @@ enum RotOrder {
EulerZYX
};
-Vector3 deg2rad(const Vector3 &p_rotation) {
+Vector3 deg_to_rad(const Vector3 &p_rotation) {
return p_rotation / 180.0 * Math_PI;
}
@@ -155,7 +155,7 @@ void test_rotation(Vector3 deg_original_euler, RotOrder rot_order) {
// are correct.
// Euler to rotation
- const Vector3 original_euler = deg2rad(deg_original_euler);
+ const Vector3 original_euler = deg_to_rad(deg_original_euler);
const Basis to_rotation = EulerToBasis(rot_order, original_euler);
// Euler from rotation
@@ -281,6 +281,59 @@ TEST_CASE("[Stress][Basis] Euler conversions") {
}
}
}
+
+TEST_CASE("[Basis] Set axis angle") {
+ Vector3 axis;
+ real_t angle;
+ real_t pi = (real_t)Math_PI;
+
+ // Testing the singularity when the angle is 0°.
+ Basis identity(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ identity.get_axis_angle(axis, angle);
+ CHECK(angle == 0);
+
+ // Testing the singularity when the angle is 180°.
+ Basis singularityPi(-1, 0, 0, 0, 1, 0, 0, 0, -1);
+ singularityPi.get_axis_angle(axis, angle);
+ CHECK(Math::is_equal_approx(angle, pi));
+
+ // Testing reversing the an axis (of an 30° angle).
+ float cos30deg = Math::cos(Math::deg_to_rad((real_t)30.0));
+ Basis z_positive(cos30deg, -0.5, 0, 0.5, cos30deg, 0, 0, 0, 1);
+ Basis z_negative(cos30deg, 0.5, 0, -0.5, cos30deg, 0, 0, 0, 1);
+
+ z_positive.get_axis_angle(axis, angle);
+ CHECK(Math::is_equal_approx(angle, Math::deg_to_rad((real_t)30.0)));
+ CHECK(axis == Vector3(0, 0, 1));
+
+ z_negative.get_axis_angle(axis, angle);
+ CHECK(Math::is_equal_approx(angle, Math::deg_to_rad((real_t)30.0)));
+ CHECK(axis == Vector3(0, 0, -1));
+
+ // Testing a rotation of 90° on x-y-z.
+ Basis x90deg(1, 0, 0, 0, 0, -1, 0, 1, 0);
+ x90deg.get_axis_angle(axis, angle);
+ CHECK(Math::is_equal_approx(angle, pi / (real_t)2));
+ CHECK(axis == Vector3(1, 0, 0));
+
+ Basis y90deg(0, 0, 1, 0, 1, 0, -1, 0, 0);
+ y90deg.get_axis_angle(axis, angle);
+ CHECK(axis == Vector3(0, 1, 0));
+
+ Basis z90deg(0, -1, 0, 1, 0, 0, 0, 0, 1);
+ z90deg.get_axis_angle(axis, angle);
+ CHECK(axis == Vector3(0, 0, 1));
+
+ // Regression test: checks that the method returns a small angle (not 0).
+ Basis tiny(1, 0, 0, 0, 0.9999995, -0.001, 0, 001, 0.9999995); // The min angle possible with float is 0.001rad.
+ tiny.get_axis_angle(axis, angle);
+ CHECK(Math::is_equal_approx(angle, (real_t)0.001, (real_t)0.0001));
+
+ // Regression test: checks that the method returns an angle which is a number (not NaN)
+ Basis bugNan(1.00000024, 0, 0.000100001693, 0, 1, 0, -0.000100009143, 0, 1.00000024);
+ bugNan.get_axis_angle(axis, angle);
+ CHECK(!Math::is_nan(angle));
+}
} // namespace TestBasis
#endif // TEST_BASIS_H
diff --git a/tests/core/math/test_geometry_3d.h b/tests/core/math/test_geometry_3d.h
index 99a4ef2d46..23bbf1e183 100644
--- a/tests/core/math/test_geometry_3d.h
+++ b/tests/core/math/test_geometry_3d.h
@@ -63,7 +63,7 @@ TEST_CASE("[Geometry3D] Closest Distance Between Segments") {
p_1(p_p_1), p_2(p_p_2), p_3(p_p_3), p_4(p_p_4), want(p_want){};
};
Vector<Case> tt;
- tt.push_back(Case(Vector3(1, -2, 0), Vector3(1, 2, 0), Vector3(-1, 2, 0), Vector3(-1, -2, 0), 0.0f));
+ tt.push_back(Case(Vector3(1, -2, 0), Vector3(1, 2, 0), Vector3(-1, 2, 0), Vector3(-1, -2, 0), 2.0f));
for (int i = 0; i < tt.size(); ++i) {
Case current_case = tt[i];
float out = Geometry3D::get_closest_distance_between_segments(current_case.p_1, current_case.p_2, current_case.p_3, current_case.p_4);
diff --git a/tests/core/math/test_quaternion.h b/tests/core/math/test_quaternion.h
index 94eef6c463..63d30759bb 100644
--- a/tests/core/math/test_quaternion.h
+++ b/tests/core/math/test_quaternion.h
@@ -41,9 +41,9 @@
namespace TestQuaternion {
Quaternion quat_euler_yxz_deg(Vector3 angle) {
- double yaw = Math::deg2rad(angle[1]);
- double pitch = Math::deg2rad(angle[0]);
- double roll = Math::deg2rad(angle[2]);
+ double yaw = Math::deg_to_rad(angle[1]);
+ double pitch = Math::deg_to_rad(angle[0]);
+ double roll = Math::deg_to_rad(angle[2]);
// Generate YXZ (Z-then-X-then-Y) Quaternion using single-axis Euler
// constructor and quaternion product, both tested separately.
@@ -77,7 +77,7 @@ TEST_CASE("[Quaternion] Construct x,y,z,w") {
TEST_CASE("[Quaternion] Construct AxisAngle 1") {
// Easy to visualize: 120 deg about X-axis.
- Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0));
+ Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg_to_rad(120.0));
// 0.866 isn't close enough; doctest::Approx doesn't cut much slack!
CHECK(q[0] == doctest::Approx(0.866025)); // Sine of half the angle.
@@ -88,7 +88,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 1") {
TEST_CASE("[Quaternion] Construct AxisAngle 2") {
// Easy to visualize: 30 deg about Y-axis.
- Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0));
+ Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg_to_rad(30.0));
CHECK(q[0] == doctest::Approx(0.0));
CHECK(q[1] == doctest::Approx(0.258819)); // Sine of half the angle.
@@ -98,7 +98,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 2") {
TEST_CASE("[Quaternion] Construct AxisAngle 3") {
// Easy to visualize: 60 deg about Z-axis.
- Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0));
+ Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg_to_rad(60.0));
CHECK(q[0] == doctest::Approx(0.0));
CHECK(q[1] == doctest::Approx(0.0));
@@ -109,7 +109,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 3") {
TEST_CASE("[Quaternion] Construct AxisAngle 4") {
// More complex & hard to visualize, so test w/ data from online calculator.
Vector3 axis(1.0, 2.0, 0.5);
- Quaternion q(axis.normalized(), Math::deg2rad(35.0));
+ Quaternion q(axis.normalized(), Math::deg_to_rad(35.0));
CHECK(q[0] == doctest::Approx(0.131239));
CHECK(q[1] == doctest::Approx(0.262478));
@@ -119,7 +119,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 4") {
TEST_CASE("[Quaternion] Construct from Quaternion") {
Vector3 axis(1.0, 2.0, 0.5);
- Quaternion q_src(axis.normalized(), Math::deg2rad(35.0));
+ Quaternion q_src(axis.normalized(), Math::deg_to_rad(35.0));
Quaternion q(q_src);
CHECK(q[0] == doctest::Approx(0.131239));
@@ -129,9 +129,9 @@ TEST_CASE("[Quaternion] Construct from Quaternion") {
}
TEST_CASE("[Quaternion] Construct Euler SingleAxis") {
- double yaw = Math::deg2rad(45.0);
- double pitch = Math::deg2rad(30.0);
- double roll = Math::deg2rad(10.0);
+ double yaw = Math::deg_to_rad(45.0);
+ double pitch = Math::deg_to_rad(30.0);
+ double roll = Math::deg_to_rad(10.0);
Vector3 euler_y(0.0, yaw, 0.0);
Quaternion q_y(euler_y);
@@ -156,11 +156,11 @@ TEST_CASE("[Quaternion] Construct Euler SingleAxis") {
}
TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") {
- double yaw = Math::deg2rad(45.0);
- double pitch = Math::deg2rad(30.0);
- double roll = Math::deg2rad(10.0);
+ double yaw = Math::deg_to_rad(45.0);
+ double pitch = Math::deg_to_rad(30.0);
+ double roll = Math::deg_to_rad(10.0);
- // Generate YXZ comparision data (Z-then-X-then-Y) using single-axis Euler
+ // Generate YXZ comparison data (Z-then-X-then-Y) using single-axis Euler
// constructor and quaternion product, both tested separately.
Vector3 euler_y(0.0, yaw, 0.0);
Quaternion q_y(euler_y);
@@ -187,9 +187,9 @@ TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") {
}
TEST_CASE("[Quaternion] Construct Basis Euler") {
- double yaw = Math::deg2rad(45.0);
- double pitch = Math::deg2rad(30.0);
- double roll = Math::deg2rad(10.0);
+ double yaw = Math::deg_to_rad(45.0);
+ double pitch = Math::deg_to_rad(30.0);
+ double roll = Math::deg_to_rad(10.0);
Vector3 euler_yxz(pitch, yaw, roll);
Quaternion q_yxz(euler_yxz);
Basis basis_axes(euler_yxz);
@@ -199,7 +199,7 @@ TEST_CASE("[Quaternion] Construct Basis Euler") {
TEST_CASE("[Quaternion] Construct Basis Axes") {
// Arbitrary Euler angles.
- Vector3 euler_yxz(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34));
+ Vector3 euler_yxz(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
// Basis vectors from online calculation of rotation matrix.
Vector3 i_unit(0.5545787, 0.1823950, 0.8118957);
Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555);
@@ -248,9 +248,9 @@ TEST_CASE("[Quaternion] Product (book)") {
}
TEST_CASE("[Quaternion] Product") {
- double yaw = Math::deg2rad(45.0);
- double pitch = Math::deg2rad(30.0);
- double roll = Math::deg2rad(10.0);
+ double yaw = Math::deg_to_rad(45.0);
+ double pitch = Math::deg_to_rad(30.0);
+ double roll = Math::deg_to_rad(10.0);
Vector3 euler_y(0.0, yaw, 0.0);
Quaternion q_y(euler_y);
@@ -292,7 +292,7 @@ TEST_CASE("[Quaternion] Product") {
TEST_CASE("[Quaternion] xform unit vectors") {
// Easy to visualize: 120 deg about X-axis.
// Transform the i, j, & k unit vectors.
- Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0));
+ Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg_to_rad(120.0));
Vector3 i_t = q.xform(Vector3(1.0, 0.0, 0.0));
Vector3 j_t = q.xform(Vector3(0.0, 1.0, 0.0));
Vector3 k_t = q.xform(Vector3(0.0, 0.0, 1.0));
@@ -305,7 +305,7 @@ TEST_CASE("[Quaternion] xform unit vectors") {
CHECK(k_t.length_squared() == doctest::Approx(1.0));
// Easy to visualize: 30 deg about Y-axis.
- q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0));
+ q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg_to_rad(30.0));
i_t = q.xform(Vector3(1.0, 0.0, 0.0));
j_t = q.xform(Vector3(0.0, 1.0, 0.0));
k_t = q.xform(Vector3(0.0, 0.0, 1.0));
@@ -318,7 +318,7 @@ TEST_CASE("[Quaternion] xform unit vectors") {
CHECK(k_t.length_squared() == doctest::Approx(1.0));
// Easy to visualize: 60 deg about Z-axis.
- q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0));
+ q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg_to_rad(60.0));
i_t = q.xform(Vector3(1.0, 0.0, 0.0));
j_t = q.xform(Vector3(0.0, 1.0, 0.0));
k_t = q.xform(Vector3(0.0, 0.0, 1.0));
@@ -333,7 +333,7 @@ TEST_CASE("[Quaternion] xform unit vectors") {
TEST_CASE("[Quaternion] xform vector") {
// Arbitrary quaternion rotates an arbitrary vector.
- Vector3 euler_yzx(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34));
+ Vector3 euler_yzx(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
Basis basis_axes(euler_yzx);
Quaternion q(basis_axes);
diff --git a/tests/core/math/test_rect2.h b/tests/core/math/test_rect2.h
index 0b1106ac3c..6323b214db 100644
--- a/tests/core/math/test_rect2.h
+++ b/tests/core/math/test_rect2.h
@@ -118,17 +118,17 @@ TEST_CASE("[Rect2] Area getters") {
"get_area() should return the expected value.");
CHECK_MESSAGE(
- !Rect2(0, 100, 1280, 720).has_no_area(),
- "has_no_area() should return the expected value on Rect2 with an area.");
+ Rect2(0, 100, 1280, 720).has_area(),
+ "has_area() should return the expected value on Rect2 with an area.");
CHECK_MESSAGE(
- Rect2(0, 100, 0, 500).has_no_area(),
- "has_no_area() should return the expected value on Rect2 with no area.");
+ !Rect2(0, 100, 0, 500).has_area(),
+ "has_area() should return the expected value on Rect2 with no area.");
CHECK_MESSAGE(
- Rect2(0, 100, 500, 0).has_no_area(),
- "has_no_area() should return the expected value on Rect2 with no area.");
+ !Rect2(0, 100, 500, 0).has_area(),
+ "has_area() should return the expected value on Rect2 with no area.");
CHECK_MESSAGE(
- Rect2(0, 100, 0, 0).has_no_area(),
- "has_no_area() should return the expected value on Rect2 with no area.");
+ !Rect2(0, 100, 0, 0).has_area(),
+ "has_area() should return the expected value on Rect2 with no area.");
}
TEST_CASE("[Rect2] Absolute coordinates") {
diff --git a/tests/core/math/test_rect2i.h b/tests/core/math/test_rect2i.h
index 0d1a088a66..4005300e1f 100644
--- a/tests/core/math/test_rect2i.h
+++ b/tests/core/math/test_rect2i.h
@@ -118,17 +118,17 @@ TEST_CASE("[Rect2i] Area getters") {
"get_area() should return the expected value.");
CHECK_MESSAGE(
- !Rect2i(0, 100, 1280, 720).has_no_area(),
- "has_no_area() should return the expected value on Rect2i with an area.");
+ Rect2i(0, 100, 1280, 720).has_area(),
+ "has_area() should return the expected value on Rect2i with an area.");
CHECK_MESSAGE(
- Rect2i(0, 100, 0, 500).has_no_area(),
- "has_no_area() should return the expected value on Rect2i with no area.");
+ !Rect2i(0, 100, 0, 500).has_area(),
+ "has_area() should return the expected value on Rect2i with no area.");
CHECK_MESSAGE(
- Rect2i(0, 100, 500, 0).has_no_area(),
- "has_no_area() should return the expected value on Rect2i with no area.");
+ !Rect2i(0, 100, 500, 0).has_area(),
+ "has_area() should return the expected value on Rect2i with no area.");
CHECK_MESSAGE(
- Rect2i(0, 100, 0, 0).has_no_area(),
- "has_no_area() should return the expected value on Rect2i with no area.");
+ !Rect2i(0, 100, 0, 0).has_area(),
+ "has_area() should return the expected value on Rect2i with no area.");
}
TEST_CASE("[Rect2i] Absolute coordinates") {
diff --git a/tests/core/math/test_vector2.h b/tests/core/math/test_vector2.h
index 9b7800164a..0d7f1163e4 100644
--- a/tests/core/math/test_vector2.h
+++ b/tests/core/math/test_vector2.h
@@ -37,6 +37,14 @@
namespace TestVector2 {
+TEST_CASE("[Vector2] Constructor methods") {
+ const Vector2 vector_empty = Vector2();
+ const Vector2 vector_zero = Vector2(0.0, 0.0);
+ CHECK_MESSAGE(
+ vector_empty == vector_zero,
+ "Vector2 Constructor with no inputs should return a zero Vector2.");
+}
+
TEST_CASE("[Vector2] Angle methods") {
const Vector2 vector_x = Vector2(1, 0);
const Vector2 vector_y = Vector2(0, 1);
@@ -102,6 +110,9 @@ TEST_CASE("[Vector2] Interpolation methods") {
Vector2(1, 1).slerp(Vector2(), 0.5) == Vector2(0.5, 0.5),
"Vector2 slerp with one input as zero should behave like a regular lerp.");
CHECK_MESSAGE(
+ Vector2(4, 6).slerp(Vector2(8, 10), 0.5).is_equal_approx(Vector2(5.9076470794008017626, 8.07918879020090480697)),
+ "Vector2 slerp should work as expected.");
+ CHECK_MESSAGE(
Math::is_equal_approx(vector1.slerp(vector2, 0.5).length(), (real_t)4.31959610746631919),
"Vector2 slerp with different length input should return a vector with an interpolated length.");
CHECK_MESSAGE(
@@ -171,6 +182,15 @@ TEST_CASE("[Vector2] Normalization methods") {
CHECK_MESSAGE(
Vector2(1, 1).normalized().is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)),
"Vector2 normalized should work as expected.");
+
+ Vector2 vector = Vector2(3.2, -5.4);
+ vector.normalize();
+ CHECK_MESSAGE(
+ vector == Vector2(3.2, -5.4).normalized(),
+ "Vector2 normalize should convert same way as Vector2 normalized.");
+ CHECK_MESSAGE(
+ vector.is_equal_approx(Vector2(0.509802390301732898898, -0.860291533634174266891)),
+ "Vector2 normalize should work as expected.");
}
TEST_CASE("[Vector2] Operators") {
@@ -276,12 +296,14 @@ TEST_CASE("[Vector2] Other methods") {
CHECK_MESSAGE(
Math::is_equal_approx(vector.aspect(), (real_t)1.2 / (real_t)3.4),
"Vector2 aspect should work as expected.");
+
CHECK_MESSAGE(
vector.direction_to(Vector2()).is_equal_approx(-vector.normalized()),
"Vector2 direction_to should work as expected.");
CHECK_MESSAGE(
Vector2(1, 1).direction_to(Vector2(2, 2)).is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)),
"Vector2 direction_to should work as expected.");
+
CHECK_MESSAGE(
vector.posmod(2).is_equal_approx(Vector2(1.2, 1.4)),
"Vector2 posmod should work as expected.");
@@ -294,10 +316,21 @@ TEST_CASE("[Vector2] Other methods") {
CHECK_MESSAGE(
(-vector).posmodv(Vector2(2, 3)).is_equal_approx(Vector2(0.8, 2.6)),
"Vector2 posmodv should work as expected.");
+
+ CHECK_MESSAGE(
+ vector.rotated(Math_TAU).is_equal_approx(Vector2(1.2, 3.4)),
+ "Vector2 rotated should work as expected.");
CHECK_MESSAGE(
vector.rotated(Math_TAU / 4).is_equal_approx(Vector2(-3.4, 1.2)),
"Vector2 rotated should work as expected.");
CHECK_MESSAGE(
+ vector.rotated(Math_TAU / 3).is_equal_approx(Vector2(-3.544486372867091398996, -0.660769515458673623883)),
+ "Vector2 rotated should work as expected.");
+ CHECK_MESSAGE(
+ vector.rotated(Math_TAU / 2).is_equal_approx(vector.rotated(Math_TAU / -2)),
+ "Vector2 rotated should work as expected.");
+
+ CHECK_MESSAGE(
vector.snapped(Vector2(1, 1)) == Vector2(1, 3),
"Vector2 snapped to integers should be the same as rounding.");
CHECK_MESSAGE(
@@ -306,23 +339,57 @@ TEST_CASE("[Vector2] Other methods") {
CHECK_MESSAGE(
vector.snapped(Vector2(0.25, 0.25)) == Vector2(1.25, 3.5),
"Vector2 snapped to 0.25 should give exact results.");
+
+ CHECK_MESSAGE(
+ Vector2(1.2, 2.5).is_equal_approx(vector.min(Vector2(3.0, 2.5))),
+ "Vector2 min should return expected value.");
+
+ CHECK_MESSAGE(
+ Vector2(5.3, 3.4).is_equal_approx(vector.max(Vector2(5.3, 2.0))),
+ "Vector2 max should return expected value.");
}
TEST_CASE("[Vector2] Plane methods") {
const Vector2 vector = Vector2(1.2, 3.4);
const Vector2 vector_y = Vector2(0, 1);
+ const Vector2 vector_normal = Vector2(0.95879811270838721622267, 0.2840883296913739899919);
+ const Vector2 vector_non_normal = Vector2(5.4, 1.6);
CHECK_MESSAGE(
vector.bounce(vector_y) == Vector2(1.2, -3.4),
"Vector2 bounce on a plane with normal of the Y axis should.");
CHECK_MESSAGE(
+ vector.bounce(vector_normal).is_equal_approx(Vector2(-2.85851197982345523329, 2.197477931904161412358)),
+ "Vector2 bounce with normal should return expected value.");
+ CHECK_MESSAGE(
vector.reflect(vector_y) == Vector2(-1.2, 3.4),
"Vector2 reflect on a plane with normal of the Y axis should.");
CHECK_MESSAGE(
+ vector.reflect(vector_normal).is_equal_approx(Vector2(2.85851197982345523329, -2.197477931904161412358)),
+ "Vector2 reflect with normal should return expected value.");
+ CHECK_MESSAGE(
vector.project(vector_y) == Vector2(0, 3.4),
- "Vector2 projected on the X axis should only give the Y component.");
+ "Vector2 projected on the Y axis should only give the Y component.");
+ CHECK_MESSAGE(
+ vector.project(vector_normal).is_equal_approx(Vector2(2.0292559899117276166, 0.60126103404791929382)),
+ "Vector2 projected on a normal should return expected value.");
CHECK_MESSAGE(
vector.slide(vector_y) == Vector2(1.2, 0),
"Vector2 slide on a plane with normal of the Y axis should set the Y to zero.");
+ CHECK_MESSAGE(
+ vector.slide(vector_normal).is_equal_approx(Vector2(-0.8292559899117276166456, 2.798738965952080706179)),
+ "Vector2 slide with normal should return expected value.");
+ // There's probably a better way to test these ones?
+ ERR_PRINT_OFF;
+ CHECK_MESSAGE(
+ vector.bounce(vector_non_normal).is_equal_approx(Vector2()),
+ "Vector2 bounce should return empty Vector2 with non-normalised input.");
+ CHECK_MESSAGE(
+ vector.reflect(vector_non_normal).is_equal_approx(Vector2()),
+ "Vector2 reflect should return empty Vector2 with non-normalised input.");
+ CHECK_MESSAGE(
+ vector.slide(vector_non_normal).is_equal_approx(Vector2()),
+ "Vector2 slide should return empty Vector2 with non-normalised input.");
+ ERR_PRINT_ON;
}
TEST_CASE("[Vector2] Rounding methods") {
@@ -367,12 +434,20 @@ TEST_CASE("[Vector2] Rounding methods") {
TEST_CASE("[Vector2] Linear algebra methods") {
const Vector2 vector_x = Vector2(1, 0);
const Vector2 vector_y = Vector2(0, 1);
+ const Vector2 a = Vector2(3.5, 8.5);
+ const Vector2 b = Vector2(5.2, 4.6);
CHECK_MESSAGE(
vector_x.cross(vector_y) == 1,
"Vector2 cross product of X and Y should give 1.");
CHECK_MESSAGE(
vector_y.cross(vector_x) == -1,
"Vector2 cross product of Y and X should give negative 1.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(a.cross(b), (real_t)-28.1),
+ "Vector2 cross should return expected value.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(Vector2(-a.x, a.y).cross(Vector2(b.x, -b.y)), (real_t)-28.1),
+ "Vector2 cross should return expected value.");
CHECK_MESSAGE(
vector_x.dot(vector_y) == 0.0,
@@ -383,6 +458,12 @@ TEST_CASE("[Vector2] Linear algebra methods") {
CHECK_MESSAGE(
(vector_x * 10).dot(vector_x * 10) == 100.0,
"Vector2 dot product of same direction vectors should behave as expected.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(a.dot(b), (real_t)57.3),
+ "Vector2 dot should return expected value.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(Vector2(-a.x, a.y).dot(Vector2(b.x, -b.y)), (real_t)-57.3),
+ "Vector2 dot should return expected value.");
}
} // namespace TestVector2
diff --git a/tests/core/math/test_vector2i.h b/tests/core/math/test_vector2i.h
index 841bb793a4..49b0632e3c 100644
--- a/tests/core/math/test_vector2i.h
+++ b/tests/core/math/test_vector2i.h
@@ -37,6 +37,14 @@
namespace TestVector2i {
+TEST_CASE("[Vector2i] Constructor methods") {
+ const Vector2i vector_empty = Vector2i();
+ const Vector2i vector_zero = Vector2i(0, 0);
+ CHECK_MESSAGE(
+ vector_empty == vector_zero,
+ "Vector2i Constructor with no inputs should return a zero Vector2i.");
+}
+
TEST_CASE("[Vector2i] Axis methods") {
Vector2i vector = Vector2i(2, 3);
CHECK_MESSAGE(
@@ -121,6 +129,14 @@ TEST_CASE("[Vector2i] Other methods") {
CHECK_MESSAGE(
Math::is_equal_approx(vector.aspect(), (real_t)1.0 / (real_t)3.0),
"Vector2i aspect should work as expected.");
+
+ CHECK_MESSAGE(
+ Vector2i(1, 2) == vector.min(Vector2i(3, 2)),
+ "Vector2i min should return expected value.");
+
+ CHECK_MESSAGE(
+ Vector2i(5, 3) == vector.max(Vector2i(5, 2)),
+ "Vector2i max should return expected value.");
}
TEST_CASE("[Vector2i] Abs and sign methods") {
diff --git a/tests/core/math/test_vector3.h b/tests/core/math/test_vector3.h
index 6f99fada2b..52118fa943 100644
--- a/tests/core/math/test_vector3.h
+++ b/tests/core/math/test_vector3.h
@@ -39,6 +39,14 @@
namespace TestVector3 {
+TEST_CASE("[Vector3] Constructor methods") {
+ const Vector3 vector_empty = Vector3();
+ const Vector3 vector_zero = Vector3(0.0, 0.0, 0.0);
+ CHECK_MESSAGE(
+ vector_empty == vector_zero,
+ "Vector3 Constructor with no inputs should return a zero Vector3.");
+}
+
TEST_CASE("[Vector3] Angle methods") {
const Vector3 vector_x = Vector3(1, 0, 0);
const Vector3 vector_y = Vector3(0, 1, 0);
@@ -123,6 +131,9 @@ TEST_CASE("[Vector3] Interpolation methods") {
Vector3(1, 1, 1).slerp(Vector3(), 0.5) == Vector3(0.5, 0.5, 0.5),
"Vector3 slerp with one input as zero should behave like a regular lerp.");
CHECK_MESSAGE(
+ Vector3(4, 6, 2).slerp(Vector3(8, 10, 3), 0.5).is_equal_approx(Vector3(5.90194219811429941053, 8.06758688849378394534, 2.558307894718317120038)),
+ "Vector3 slerp should work as expected.");
+ CHECK_MESSAGE(
Math::is_equal_approx(vector1.slerp(vector2, 0.5).length(), (real_t)6.25831088708303172),
"Vector3 slerp with different length input should return a vector with an interpolated length.");
CHECK_MESSAGE(
@@ -195,6 +206,15 @@ TEST_CASE("[Vector3] Normalization methods") {
CHECK_MESSAGE(
Vector3(1, 1, 1).normalized().is_equal_approx(Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)),
"Vector3 normalized should work as expected.");
+
+ Vector3 vector = Vector3(3.2, -5.4, 6);
+ vector.normalize();
+ CHECK_MESSAGE(
+ vector == Vector3(3.2, -5.4, 6).normalized(),
+ "Vector3 normalize should convert same way as Vector3 normalized.");
+ CHECK_MESSAGE(
+ vector.is_equal_approx(Vector3(0.368522751763902980457, -0.621882143601586279522, 0.6909801595573180883585)),
+ "Vector3 normalize should work as expected.");
}
TEST_CASE("[Vector3] Operators") {
@@ -318,10 +338,21 @@ TEST_CASE("[Vector3] Other methods") {
CHECK_MESSAGE(
(-vector).posmodv(Vector3(2, 3, 4)).is_equal_approx(Vector3(0.8, 2.6, 2.4)),
"Vector3 posmodv should work as expected.");
+
+ CHECK_MESSAGE(
+ vector.rotated(Vector3(0, 1, 0), Math_TAU).is_equal_approx(vector),
+ "Vector3 rotated should work as expected.");
CHECK_MESSAGE(
vector.rotated(Vector3(0, 1, 0), Math_TAU / 4).is_equal_approx(Vector3(5.6, 3.4, -1.2)),
"Vector3 rotated should work as expected.");
CHECK_MESSAGE(
+ vector.rotated(Vector3(1, 0, 0), Math_TAU / 3).is_equal_approx(Vector3(1.2, -6.54974226119285642, 0.1444863728670914)),
+ "Vector3 rotated should work as expected.");
+ CHECK_MESSAGE(
+ vector.rotated(Vector3(0, 0, 1), Math_TAU / 2).is_equal_approx(vector.rotated(Vector3(0, 0, 1), Math_TAU / -2)),
+ "Vector3 rotated should work as expected.");
+
+ CHECK_MESSAGE(
vector.snapped(Vector3(1, 1, 1)) == Vector3(1, 3, 6),
"Vector3 snapped to integers should be the same as rounding.");
CHECK_MESSAGE(
@@ -332,18 +363,44 @@ TEST_CASE("[Vector3] Other methods") {
TEST_CASE("[Vector3] Plane methods") {
const Vector3 vector = Vector3(1.2, 3.4, 5.6);
const Vector3 vector_y = Vector3(0, 1, 0);
+ const Vector3 vector_normal = Vector3(0.88763458893247992491, 0.26300284116517923701, 0.37806658417494515320);
+ const Vector3 vector_non_normal = Vector3(5.4, 1.6, 2.3);
CHECK_MESSAGE(
vector.bounce(vector_y) == Vector3(1.2, -3.4, 5.6),
"Vector3 bounce on a plane with normal of the Y axis should.");
CHECK_MESSAGE(
+ vector.bounce(vector_normal).is_equal_approx(Vector3(-6.0369629829775736287, 1.25571467171034855444, 2.517589840583626047)),
+ "Vector3 bounce with normal should return expected value.");
+ CHECK_MESSAGE(
vector.reflect(vector_y) == Vector3(-1.2, 3.4, -5.6),
"Vector3 reflect on a plane with normal of the Y axis should.");
CHECK_MESSAGE(
+ vector.reflect(vector_normal).is_equal_approx(Vector3(6.0369629829775736287, -1.25571467171034855444, -2.517589840583626047)),
+ "Vector3 reflect with normal should return expected value.");
+ CHECK_MESSAGE(
vector.project(vector_y) == Vector3(0, 3.4, 0),
- "Vector3 projected on the X axis should only give the Y component.");
+ "Vector3 projected on the Y axis should only give the Y component.");
+ CHECK_MESSAGE(
+ vector.project(vector_normal).is_equal_approx(Vector3(3.61848149148878681437, 1.0721426641448257227776, 1.54120507970818697649)),
+ "Vector3 projected on a normal should return expected value.");
CHECK_MESSAGE(
vector.slide(vector_y) == Vector3(1.2, 0, 5.6),
"Vector3 slide on a plane with normal of the Y axis should set the Y to zero.");
+ CHECK_MESSAGE(
+ vector.slide(vector_normal).is_equal_approx(Vector3(-2.41848149148878681437, 2.32785733585517427722237, 4.0587949202918130235)),
+ "Vector3 slide with normal should return expected value.");
+ // There's probably a better way to test these ones?
+ ERR_PRINT_OFF;
+ CHECK_MESSAGE(
+ vector.bounce(vector_non_normal).is_equal_approx(Vector3()),
+ "Vector3 bounce should return empty Vector3 with non-normalised input.");
+ CHECK_MESSAGE(
+ vector.reflect(vector_non_normal).is_equal_approx(Vector3()),
+ "Vector3 reflect should return empty Vector3 with non-normalised input.");
+ CHECK_MESSAGE(
+ vector.slide(vector_non_normal).is_equal_approx(Vector3()),
+ "Vector3 slide should return empty Vector3 with non-normalised input.");
+ ERR_PRINT_ON;
}
TEST_CASE("[Vector3] Rounding methods") {
@@ -389,6 +446,8 @@ TEST_CASE("[Vector3] Linear algebra methods") {
const Vector3 vector_x = Vector3(1, 0, 0);
const Vector3 vector_y = Vector3(0, 1, 0);
const Vector3 vector_z = Vector3(0, 0, 1);
+ const Vector3 a = Vector3(3.5, 8.5, 2.3);
+ const Vector3 b = Vector3(5.2, 4.6, 7.8);
CHECK_MESSAGE(
vector_x.cross(vector_y) == vector_z,
"Vector3 cross product of X and Y should give Z.");
@@ -401,6 +460,12 @@ TEST_CASE("[Vector3] Linear algebra methods") {
CHECK_MESSAGE(
vector_z.cross(vector_x) == vector_y,
"Vector3 cross product of Z and X should give Y.");
+ CHECK_MESSAGE(
+ a.cross(b).is_equal_approx(Vector3(55.72, -15.34, -28.1)),
+ "Vector3 cross should return expected value.");
+ CHECK_MESSAGE(
+ Vector3(-a.x, a.y, -a.z).cross(Vector3(b.x, -b.y, b.z)).is_equal_approx(Vector3(55.72, 15.34, -28.1)),
+ "Vector2 cross should return expected value.");
CHECK_MESSAGE(
vector_x.dot(vector_y) == 0.0,
@@ -411,6 +476,12 @@ TEST_CASE("[Vector3] Linear algebra methods") {
CHECK_MESSAGE(
(vector_x * 10).dot(vector_x * 10) == 100.0,
"Vector3 dot product of same direction vectors should behave as expected.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(a.dot(b), (real_t)75.24),
+ "Vector3 dot should return expected value.");
+ CHECK_MESSAGE(
+ Math::is_equal_approx(Vector3(-a.x, a.y, -a.z).dot(Vector3(b.x, -b.y, b.z)), (real_t)-75.24),
+ "Vector3 dot should return expected value.");
}
} // namespace TestVector3
diff --git a/tests/core/math/test_vector3i.h b/tests/core/math/test_vector3i.h
index b1c6944eba..6c52781556 100644
--- a/tests/core/math/test_vector3i.h
+++ b/tests/core/math/test_vector3i.h
@@ -36,6 +36,14 @@
namespace TestVector3i {
+TEST_CASE("[Vector3i] Constructor methods") {
+ const Vector3i vector_empty = Vector3i();
+ const Vector3i vector_zero = Vector3i(0, 0, 0);
+ CHECK_MESSAGE(
+ vector_empty == vector_zero,
+ "Vector3i Constructor with no inputs should return a zero Vector3i.");
+}
+
TEST_CASE("[Vector3i] Axis methods") {
Vector3i vector = Vector3i(1, 2, 3);
CHECK_MESSAGE(
diff --git a/tests/core/math/test_vector4.h b/tests/core/math/test_vector4.h
index ccf991401b..25ec8929b8 100644
--- a/tests/core/math/test_vector4.h
+++ b/tests/core/math/test_vector4.h
@@ -38,6 +38,14 @@
namespace TestVector4 {
+TEST_CASE("[Vector4] Constructor methods") {
+ const Vector4 vector_empty = Vector4();
+ const Vector4 vector_zero = Vector4(0.0, 0.0, 0.0, 0.0);
+ CHECK_MESSAGE(
+ vector_empty == vector_zero,
+ "Vector4 Constructor with no inputs should return a zero Vector4.");
+}
+
TEST_CASE("[Vector4] Axis methods") {
Vector4 vector = Vector4(1.2, 3.4, 5.6, -0.9);
CHECK_MESSAGE(
diff --git a/tests/core/math/test_vector4i.h b/tests/core/math/test_vector4i.h
index ac63001b24..e106099914 100644
--- a/tests/core/math/test_vector4i.h
+++ b/tests/core/math/test_vector4i.h
@@ -36,6 +36,14 @@
namespace TestVector4i {
+TEST_CASE("[Vector4i] Constructor methods") {
+ const Vector4i vector_empty = Vector4i();
+ const Vector4i vector_zero = Vector4i(0, 0, 0, 0);
+ CHECK_MESSAGE(
+ vector_empty == vector_zero,
+ "Vector4i Constructor with no inputs should return a zero Vector4i.");
+}
+
TEST_CASE("[Vector4i] Axis methods") {
Vector4i vector = Vector4i(1, 2, 3, 4);
CHECK_MESSAGE(
diff --git a/tests/core/object/test_class_db.h b/tests/core/object/test_class_db.h
index 208923edb9..b0375c63b9 100644
--- a/tests/core/object/test_class_db.h
+++ b/tests/core/object/test_class_db.h
@@ -666,6 +666,10 @@ void add_exposed_classes(Context &r_context) {
} else {
exposed_class.methods.push_back(method);
}
+
+ if (method.is_virtual) {
+ TEST_COND(String(method.name)[0] != '_', "Virtual method ", String(method.name), " does not start with underscore.");
+ }
}
// Add signals
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 5000a5da67..969f5fc096 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -466,11 +466,6 @@ TEST_CASE("[String] String to float") {
}
}
-TEST_CASE("[String] CamelCase to underscore") {
- CHECK(String("TestTestStringGD").camelcase_to_underscore(false) == String("Test_Test_String_GD"));
- CHECK(String("TestTestStringGD").camelcase_to_underscore(true) == String("test_test_string_gd"));
-}
-
TEST_CASE("[String] Slicing") {
String s = "Mars,Jupiter,Saturn,Uranus";
@@ -1112,8 +1107,36 @@ TEST_CASE("[String] IPVX address to string") {
}
TEST_CASE("[String] Capitalize against many strings") {
- String input = "bytes2var";
- String output = "Bytes 2 Var";
+ String input = "2D";
+ String output = "2d";
+ CHECK(input.capitalize() == output);
+
+ input = "2d";
+ output = "2d";
+ CHECK(input.capitalize() == output);
+
+ input = "2db";
+ output = "2 Db";
+ CHECK(input.capitalize() == output);
+
+ input = "HTML5 Html5 html5 html_5";
+ output = "Html 5 Html 5 Html 5 Html 5";
+ CHECK(input.capitalize() == output);
+
+ input = "Node2D Node2d NODE2D NODE_2D node_2d";
+ output = "Node 2d Node 2d Node 2d Node 2d Node 2d";
+ CHECK(input.capitalize() == output);
+
+ input = "Node2DPosition";
+ output = "Node 2d Position";
+ CHECK(input.capitalize() == output);
+
+ input = "Number2Digits";
+ output = "Number 2 Digits";
+ CHECK(input.capitalize() == output);
+
+ input = "bytes2var";
+ output = "Bytes 2 Var";
CHECK(input.capitalize() == output);
input = "linear2db";
@@ -1128,10 +1151,6 @@ TEST_CASE("[String] Capitalize against many strings") {
output = "Sha 256";
CHECK(input.capitalize() == output);
- input = "2db";
- output = "2 Db";
- CHECK(input.capitalize() == output);
-
input = "PascalCase";
output = "Pascal Case";
CHECK(input.capitalize() == output);
@@ -1169,6 +1188,50 @@ TEST_CASE("[String] Capitalize against many strings") {
CHECK(input.capitalize() == output);
}
+struct StringCasesTestCase {
+ const char *input;
+ const char *camel_case;
+ const char *pascal_case;
+ const char *snake_case;
+};
+
+TEST_CASE("[String] Checking case conversion methods") {
+ StringCasesTestCase test_cases[] = {
+ /* clang-format off */
+ { "2D", "2d", "2d", "2d" },
+ { "2d", "2d", "2d", "2d" },
+ { "2db", "2Db", "2Db", "2_db" },
+ { "Vector3", "vector3", "Vector3", "vector_3" },
+ { "sha256", "sha256", "Sha256", "sha_256" },
+ { "Node2D", "node2d", "Node2d", "node_2d" },
+ { "RichTextLabel", "richTextLabel", "RichTextLabel", "rich_text_label" },
+ { "HTML5", "html5", "Html5", "html_5" },
+ { "Node2DPosition", "node2dPosition", "Node2dPosition", "node_2d_position" },
+ { "Number2Digits", "number2Digits", "Number2Digits", "number_2_digits" },
+ { "get_property_list", "getPropertyList", "GetPropertyList", "get_property_list" },
+ { "get_camera_2d", "getCamera2d", "GetCamera2d", "get_camera_2d" },
+ { "_physics_process", "physicsProcess", "PhysicsProcess", "_physics_process" },
+ { "bytes2var", "bytes2Var", "Bytes2Var", "bytes_2_var" },
+ { "linear2db", "linear2Db", "Linear2Db", "linear_2_db" },
+ { "sha256sum", "sha256Sum", "Sha256Sum", "sha_256_sum" },
+ { "camelCase", "camelCase", "CamelCase", "camel_case" },
+ { "PascalCase", "pascalCase", "PascalCase", "pascal_case" },
+ { "snake_case", "snakeCase", "SnakeCase", "snake_case" },
+ { "Test TEST test", "testTestTest", "TestTestTest", "test_test_test" },
+ { nullptr, nullptr, nullptr, nullptr },
+ /* clang-format on */
+ };
+
+ int idx = 0;
+ while (test_cases[idx].input != nullptr) {
+ String input = test_cases[idx].input;
+ CHECK(input.to_camel_case() == test_cases[idx].camel_case);
+ CHECK(input.to_pascal_case() == test_cases[idx].pascal_case);
+ CHECK(input.to_snake_case() == test_cases[idx].snake_case);
+ idx++;
+ }
+}
+
TEST_CASE("[String] Checking string is empty when it should be") {
bool state = true;
bool success;
@@ -1375,7 +1438,7 @@ TEST_CASE("[String] Path functions") {
CHECK(String(path[i]).get_file() == file[i]);
CHECK(String(path[i]).is_absolute_path() == abs[i]);
CHECK(String(path[i]).is_relative_path() != abs[i]);
- CHECK(String(path[i]).simplify_path().get_base_dir().plus_file(file[i]) == String(path[i]).simplify_path());
+ CHECK(String(path[i]).simplify_path().get_base_dir().path_join(file[i]) == String(path[i]).simplify_path());
}
static const char *file_name[3] = { "test.tscn", "test://.xscn", "?tes*t.scn" };
@@ -1679,7 +1742,7 @@ TEST_CASE("[String] Variant ptr indexed set") {
TEST_CASE("[Stress][String] Empty via ' == String()'") {
for (int i = 0; i < 100000; ++i) {
String str = "Hello World!";
- if (str.is_empty()) {
+ if (str == String()) {
continue;
}
}
diff --git a/tests/core/variant/test_dictionary.h b/tests/core/variant/test_dictionary.h
index 729035919d..c98434d42c 100644
--- a/tests/core/variant/test_dictionary.h
+++ b/tests/core/variant/test_dictionary.h
@@ -500,6 +500,24 @@ TEST_CASE("[Dictionary] Recursive self comparison") {
d2.clear();
}
+TEST_CASE("[Dictionary] Order and find") {
+ Dictionary d;
+ d[4] = "four";
+ d[8] = "eight";
+ d[12] = "twelve";
+ d["4"] = "four";
+
+ Array keys;
+ keys.append(4);
+ keys.append(8);
+ keys.append(12);
+ keys.append("4");
+
+ CHECK_EQ(d.keys(), keys);
+ CHECK_EQ(d.find_key("four"), Variant(4));
+ CHECK_EQ(d.find_key("does not exist"), Variant());
+}
+
} // namespace TestDictionary
#endif // TEST_DICTIONARY_H
diff --git a/tests/scene/test_audio_stream_wav.h b/tests/scene/test_audio_stream_wav.h
index 92c524525c..4ba431dfc2 100644
--- a/tests/scene/test_audio_stream_wav.h
+++ b/tests/scene/test_audio_stream_wav.h
@@ -115,7 +115,7 @@ Vector<uint8_t> gen_pcm16_test(float wav_rate, int wav_count, bool stereo) {
}
void run_test(String file_name, AudioStreamWAV::Format data_format, bool stereo, float wav_rate, float wav_count) {
- String save_path = OS::get_singleton()->get_cache_path().plus_file(file_name);
+ String save_path = OS::get_singleton()->get_cache_path().path_join(file_name);
Vector<uint8_t> test_data;
if (data_format == AudioStreamWAV::FORMAT_8_BITS) {
@@ -138,7 +138,7 @@ void run_test(String file_name, AudioStreamWAV::Format data_format, bool stereo,
CHECK(stream->get_data() == test_data);
SUBCASE("Stream length is computed properly") {
- CHECK(Math::is_equal_approx(stream->get_length(), wav_count / wav_rate));
+ CHECK(Math::is_equal_approx(stream->get_length(), double(wav_count / wav_rate)));
}
SUBCASE("Stream can be saved as .wav") {
@@ -200,7 +200,7 @@ TEST_CASE("[AudioStreamWAV] Alternate mix rate") {
}
TEST_CASE("[AudioStreamWAV] save_to_wav() adds '.wav' file extension automatically") {
- String save_path = OS::get_singleton()->get_cache_path().plus_file("test_wav_extension");
+ String save_path = OS::get_singleton()->get_cache_path().path_join("test_wav_extension");
Vector<uint8_t> test_data = gen_pcm8_test(WAV_RATE, WAV_COUNT, false);
Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV);
stream->set_data(test_data);
@@ -230,7 +230,7 @@ TEST_CASE("[AudioStreamWAV] Save empty file") {
}
TEST_CASE("[AudioStreamWAV] Saving IMA ADPCM is not supported") {
- String save_path = OS::get_singleton()->get_cache_path().plus_file("test_adpcm.wav");
+ String save_path = OS::get_singleton()->get_cache_path().path_join("test_adpcm.wav");
Ref<AudioStreamWAV> stream = memnew(AudioStreamWAV);
stream->set_format(AudioStreamWAV::FORMAT_IMA_ADPCM);
ERR_PRINT_OFF;
diff --git a/tests/scene/test_bit_map.h b/tests/scene/test_bit_map.h
new file mode 100644
index 0000000000..635449181e
--- /dev/null
+++ b/tests/scene/test_bit_map.h
@@ -0,0 +1,445 @@
+/*************************************************************************/
+/* test_bit_map.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 TEST_BIT_MAP_H
+#define TEST_BIT_MAP_H
+
+#include "core/os/memory.h"
+#include "scene/resources/bit_map.h"
+#include "tests/test_macros.h"
+
+namespace TestBitmap {
+
+void reset_bit_map(BitMap &p_bm) {
+ Size2i size = p_bm.get_size();
+ p_bm.set_bit_rect(Rect2i(0, 0, size.width, size.height), false);
+}
+
+TEST_CASE("[BitMap] Create bit map") {
+ Size2i dim{ 256, 512 };
+ BitMap bit_map{};
+ bit_map.create(dim);
+ CHECK(bit_map.get_size() == Size2i(256, 512));
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "This will go through the entire bitmask inside of bitmap, thus hopefully checking if the bitmask was correctly set up.");
+
+ dim = Size2i(0, 256);
+ bit_map.create(dim);
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 512), "We should still have the same dimensions as before, because the new dimension is invalid.");
+
+ dim = Size2i(512, 0);
+ bit_map.create(dim);
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 512), "We should still have the same dimensions as before, because the new dimension is invalid.");
+
+ dim = Size2i(46341, 46341);
+ bit_map.create(dim);
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 512), "We should still have the same dimensions as before, because the new dimension is too large (46341*46341=2147488281).");
+}
+
+TEST_CASE("[BitMap] Create bit map from image alpha") {
+ const Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+ bit_map.create(dim);
+
+ const Ref<Image> null_img = nullptr;
+ bit_map.create_from_image_alpha(null_img);
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because bitmap creation from a nullptr should fail.");
+
+ Ref<Image> empty_img;
+ empty_img.instantiate();
+ bit_map.create_from_image_alpha(empty_img);
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because bitmap creation from an empty image should fail.");
+
+ Ref<Image> wrong_format_img;
+ wrong_format_img.instantiate();
+ wrong_format_img->create(3, 3, false, Image::Format::FORMAT_DXT1);
+ bit_map.create_from_image_alpha(wrong_format_img);
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Bitmap should have its old values because converting from a compressed image should fail.");
+
+ Ref<Image> img;
+ img.instantiate();
+ img->create(3, 3, false, Image::Format::FORMAT_RGBA8);
+ img->set_pixel(0, 0, Color(0, 0, 0, 0));
+ img->set_pixel(0, 1, Color(0, 0, 0, 0.09f));
+ img->set_pixel(0, 2, Color(0, 0, 0, 0.25f));
+ img->set_pixel(1, 0, Color(0, 0, 0, 0.5f));
+ img->set_pixel(1, 1, Color(0, 0, 0, 0.75f));
+ img->set_pixel(1, 2, Color(0, 0, 0, 0.99f));
+ img->set_pixel(2, 0, Color(0, 0, 0, 1.f));
+
+ // Check different threshold values.
+ bit_map.create_from_image_alpha(img);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 5, "There are 5 values in the image that are smaller than the default threshold of 0.1.");
+
+ bit_map.create_from_image_alpha(img, 0.08f);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 6, "There are 6 values in the image that are smaller than the threshold of 0.08.");
+
+ bit_map.create_from_image_alpha(img, 1);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "There are no values in the image that are smaller than the threshold of 1, there is one value equal to 1, but we check for inequality only.");
+}
+
+TEST_CASE("[BitMap] Set bit") {
+ Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+
+ // Setting a point before a bit map is created should not crash, because there are checks to see if we are out of bounds.
+ bit_map.set_bitv(Point2i(128, 128), true);
+
+ bit_map.create(dim);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "All values should be initialized to false.");
+ bit_map.set_bitv(Point2i(128, 128), true);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 1, "One bit should be set to true.");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 128)) == true, "The bit at (128,128) should be set to true");
+
+ bit_map.set_bitv(Point2i(128, 128), false);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "The bit should now be set to false again");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 128)) == false, "The bit at (128,128) should now be set to false again");
+
+ bit_map.create(dim);
+ bit_map.set_bitv(Point2i(512, 512), true);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "Nothing should change as we were trying to edit a bit outside of the correct range.");
+}
+
+TEST_CASE("[BitMap] Get bit") {
+ const Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 128)) == false, "Trying to access a bit outside of the BitMap's range should always return false");
+
+ bit_map.create(dim);
+ CHECK(bit_map.get_bitv(Point2i(128, 128)) == false);
+
+ bit_map.set_bit_rect(Rect2i(-1, -1, 257, 257), true);
+
+ // Checking that range is [0, 256).
+ CHECK(bit_map.get_bitv(Point2i(-1, 0)) == false);
+ CHECK(bit_map.get_bitv(Point2i(0, 0)) == true);
+ CHECK(bit_map.get_bitv(Point2i(128, 128)) == true);
+ CHECK(bit_map.get_bitv(Point2i(255, 255)) == true);
+ CHECK(bit_map.get_bitv(Point2i(256, 256)) == false);
+ CHECK(bit_map.get_bitv(Point2i(257, 257)) == false);
+}
+
+TEST_CASE("[BitMap] Set bit rect") {
+ const Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+
+ // Although we have not setup the BitMap yet, this should not crash because we get an empty intersection inside of the method.
+ bit_map.set_bit_rect(Rect2i{ 0, 0, 128, 128 }, true);
+
+ bit_map.create(dim);
+ CHECK(bit_map.get_true_bit_count() == 0);
+
+ bit_map.set_bit_rect(Rect2i{ 0, 0, 256, 256 }, true);
+ CHECK(bit_map.get_true_bit_count() == 65536);
+
+ reset_bit_map(bit_map);
+
+ // Checking out of bounds handling.
+ bit_map.set_bit_rect(Rect2i{ 128, 128, 256, 256 }, true);
+ CHECK(bit_map.get_true_bit_count() == 16384);
+
+ reset_bit_map(bit_map);
+
+ bit_map.set_bit_rect(Rect2i{ -128, -128, 256, 256 }, true);
+ CHECK(bit_map.get_true_bit_count() == 16384);
+
+ reset_bit_map(bit_map);
+
+ bit_map.set_bit_rect(Rect2i{ -128, -128, 512, 512 }, true);
+ CHECK(bit_map.get_true_bit_count() == 65536);
+}
+
+TEST_CASE("[BitMap] Get true bit count") {
+ const Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+
+ CHECK(bit_map.get_true_bit_count() == 0);
+
+ bit_map.create(dim);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "Uninitialized bit map should have no true bits");
+ bit_map.set_bit_rect(Rect2i{ 0, 0, 256, 256 }, true);
+ CHECK(bit_map.get_true_bit_count() == 65536);
+ bit_map.set_bitv(Point2i{ 0, 0 }, false);
+ CHECK(bit_map.get_true_bit_count() == 65535);
+ bit_map.set_bit_rect(Rect2i{ 0, 0, 256, 256 }, false);
+ CHECK(bit_map.get_true_bit_count() == 0);
+}
+
+TEST_CASE("[BitMap] Get size") {
+ const Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(0, 0), "Uninitialized bit map should have a size of 0x0");
+
+ bit_map.create(dim);
+ CHECK(bit_map.get_size() == Size2i(256, 256));
+
+ bit_map.create(Size2i(-1, 0));
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "Invalid size should not be accepted by create");
+
+ bit_map.create(Size2i(256, 128));
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 128), "Bitmap should have updated size");
+}
+
+TEST_CASE("[BitMap] Resize") {
+ const Size2i dim{ 128, 128 };
+ BitMap bit_map{};
+
+ bit_map.resize(dim);
+ CHECK(bit_map.get_size() == dim);
+
+ bit_map.create(dim);
+ bit_map.set_bit_rect(Rect2i(0, 0, 10, 10), true);
+ bit_map.set_bit_rect(Rect2i(118, 118, 10, 10), true);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 200, "There should be 100 bits in the top left corner, and 100 bits in the bottom right corner");
+ bit_map.resize(Size2i(64, 64));
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 50, "There should be 25 bits in the top left corner, and 25 bits in the bottom right corner");
+
+ bit_map.create(dim);
+ bit_map.resize(Size2i(-1, 128));
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(128, 128), "When an invalid size is given the bit map will keep its size");
+
+ bit_map.create(dim);
+ bit_map.set_bit_rect(Rect2i(0, 0, 10, 10), true);
+ bit_map.set_bit_rect(Rect2i(118, 118, 10, 10), true);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 200, "There should be 100 bits in the top left corner, and 100 bits in the bottom right corner");
+ bit_map.resize(Size2i(256, 256));
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 800, "There should still be 100 bits in the bottom right corner, and all new bits should be initialized to false");
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(256, 256), "The bitmap should now be 256x256");
+}
+
+TEST_CASE("[BitMap] Grow and shrink mask") {
+ const Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+ bit_map.grow_mask(100, Rect2i(0, 0, 128, 128)); // Check if method does not crash when working with an uninitialised bit map.
+ CHECK_MESSAGE(bit_map.get_size() == Size2i(0, 0), "Size should still be equal to 0x0");
+
+ bit_map.create(dim);
+
+ bit_map.set_bit_rect(Rect2i(96, 96, 64, 64), true);
+
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 4096, "Creating a square of 64x64 should be 4096 bits");
+ bit_map.grow_mask(0, Rect2i(0, 0, 256, 256));
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 4096, "Growing with size of 0 should not change any bits");
+
+ reset_bit_map(bit_map);
+
+ bit_map.set_bit_rect(Rect2i(96, 96, 64, 64), true);
+
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(95, 128)) == false, "Bits just outside of the square should not be set");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(160, 128)) == false, "Bits just outside of the square should not be set");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 95)) == false, "Bits just outside of the square should not be set");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 160)) == false, "Bits just outside of the square should not be set");
+ bit_map.grow_mask(1, Rect2i(0, 0, 256, 256));
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 4352, "We should have 4*64 (perimeter of square) more bits set to true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(95, 128)) == true, "Bits that were just outside of the square should now be set to true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(160, 128)) == true, "Bits that were just outside of the square should now be set to true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 95)) == true, "Bits that were just outside of the square should now be set to true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(128, 160)) == true, "Bits that were just outside of the square should now be set to true");
+
+ reset_bit_map(bit_map);
+
+ bit_map.set_bit_rect(Rect2i(127, 127, 1, 1), true);
+
+ CHECK(bit_map.get_true_bit_count() == 1);
+ bit_map.grow_mask(32, Rect2i(0, 0, 256, 256));
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 3209, "Creates a circle around the initial bit with a radius of 32 bits. Any bit that has a distance within this radius will be set to true");
+
+ reset_bit_map(bit_map);
+
+ bit_map.set_bit_rect(Rect2i(127, 127, 1, 1), true);
+ for (int i = 0; i < 32; i++) {
+ bit_map.grow_mask(1, Rect2i(0, 0, 256, 256));
+ }
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 2113, "Creates a diamond around the initial bit with diagonals that are 65 bits long.");
+
+ reset_bit_map(bit_map);
+
+ bit_map.set_bit_rect(Rect2i(123, 123, 10, 10), true);
+
+ CHECK(bit_map.get_true_bit_count() == 100);
+ bit_map.grow_mask(-11, Rect2i(0, 0, 256, 256));
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 0, "Shrinking by more than the width of the square should totally remove it.");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(96, 96, 64, 64), true);
+
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(96, 129)) == true, "Bits on the edge of the square should be true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(159, 129)) == true, "Bits on the edge of the square should be true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(129, 96)) == true, "Bits on the edge of the square should be true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(129, 159)) == true, "Bits on the edge of the square should be true");
+ bit_map.grow_mask(-1, Rect2i(0, 0, 256, 256));
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 3844, "Shrinking by 1 should set 4*63=252 bits to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(96, 129)) == false, "Bits that were on the edge of the square should now be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(159, 129)) == false, "Bits that were on the edge of the square should now be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(129, 96)) == false, "Bits that were on the edge of the square should now be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(129, 159)) == false, "Bits that were on the edge of the square should now be set to false");
+
+ reset_bit_map(bit_map);
+
+ bit_map.set_bit_rect(Rect2i(125, 125, 1, 6), true);
+ bit_map.set_bit_rect(Rect2i(130, 125, 1, 6), true);
+ bit_map.set_bit_rect(Rect2i(125, 130, 6, 1), true);
+
+ CHECK(bit_map.get_true_bit_count() == 16);
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(125, 131)) == false, "Bits that are on the edge of the shape should be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(131, 131)) == false, "Bits that are on the edge of the shape should be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(125, 124)) == false, "Bits that are on the edge of the shape should be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(130, 124)) == false, "Bits that are on the edge of the shape should be set to false");
+ bit_map.grow_mask(1, Rect2i(0, 0, 256, 256));
+ CHECK(bit_map.get_true_bit_count() == 48);
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(125, 131)) == true, "Bits that were on the edge of the shape should now be set to true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(131, 130)) == true, "Bits that were on the edge of the shape should now be set to true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(125, 124)) == true, "Bits that were on the edge of the shape should now be set to true");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(130, 124)) == true, "Bits that were on the edge of the shape should now be set to true");
+
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(124, 124)) == false, "Bits that are on the edge of the shape should be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(126, 124)) == false, "Bits that are on the edge of the shape should be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(124, 131)) == false, "Bits that are on the edge of the shape should be set to false");
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(131, 131)) == false, "Bits that are on the edge of the shape should be set to false");
+}
+
+TEST_CASE("[BitMap] Blit") {
+ Point2i blit_pos{ 128, 128 };
+ Point2i bit_map_size{ 256, 256 };
+ Point2i blit_size{ 32, 32 };
+
+ BitMap bit_map{};
+ Ref<BitMap> blit_bit_map{};
+
+ // Testing null reference to blit bit map.
+ bit_map.blit(blit_pos, blit_bit_map);
+
+ blit_bit_map.instantiate();
+
+ // Testing if uninitialised blit bit map and uninitialised bit map does not crash
+ bit_map.blit(blit_pos, blit_bit_map);
+
+ // Testing if uninitialised bit map does not crash
+ blit_bit_map->create(blit_size);
+ bit_map.blit(blit_pos, blit_bit_map);
+
+ // Testing if uninitialised bit map does not crash
+ blit_bit_map.unref();
+ blit_bit_map.instantiate();
+ CHECK_MESSAGE(blit_bit_map->get_size() == Point2i(0, 0), "Size should be cleared by unref and instance calls.");
+ bit_map.create(bit_map_size);
+ bit_map.blit(Point2i(128, 128), blit_bit_map);
+
+ // Testing if both initialised does not crash.
+ blit_bit_map->create(blit_size);
+ bit_map.blit(blit_pos, blit_bit_map);
+
+ bit_map.set_bit_rect(Rect2i{ 127, 127, 3, 3 }, true);
+ CHECK(bit_map.get_true_bit_count() == 9);
+ bit_map.blit(Point2i(112, 112), blit_bit_map);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 9, "No bits should have been changed, as the blit bit map only contains falses");
+
+ bit_map.create(bit_map_size);
+ blit_bit_map->create(blit_size);
+ blit_bit_map->set_bit_rect(Rect2i(15, 15, 3, 3), true);
+ CHECK(blit_bit_map->get_true_bit_count() == 9);
+
+ CHECK(bit_map.get_true_bit_count() == 0);
+ bit_map.blit(Point2i(112, 112), blit_bit_map);
+ CHECK_MESSAGE(bit_map.get_true_bit_count() == 9, "All true bits should have been moved to the bit map");
+ for (int x = 127; x < 129; ++x) {
+ for (int y = 127; y < 129; ++y) {
+ CHECK_MESSAGE(bit_map.get_bitv(Point2i(x, y)) == true, "All true bits should have been moved to the bit map");
+ }
+ }
+}
+
+TEST_CASE("[BitMap] Convert to image") {
+ const Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+ Ref<Image> img;
+
+ img = bit_map.convert_to_image();
+ CHECK_MESSAGE(img.is_valid(), "We should receive a valid Image Object even if BitMap is not created yet");
+ CHECK_MESSAGE(img->get_format() == Image::FORMAT_L8, "We should receive a valid Image Object even if BitMap is not created yet");
+ CHECK_MESSAGE(img->get_size() == (Size2i(0, 0)), "Image should have no width or height, because BitMap has not yet been created");
+
+ bit_map.create(dim);
+ img = bit_map.convert_to_image();
+ CHECK_MESSAGE(img->get_size() == dim, "Image should have the same dimensions as the BitMap");
+ CHECK_MESSAGE(img->get_pixel(0, 0).is_equal_approx(Color(0, 0, 0)), "BitMap is initialized to all 0's, so Image should be all black");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(0, 0, 128, 128), true);
+ img = bit_map.convert_to_image();
+ CHECK_MESSAGE(img->get_pixel(0, 0).is_equal_approx(Color(1, 1, 1)), "BitMap's top-left quadrant is all 1's, so Image should be white");
+ CHECK_MESSAGE(img->get_pixel(256, 256).is_equal_approx(Color(0, 0, 0)), "All other quadrants were 0's, so these should be black");
+}
+
+TEST_CASE("[BitMap] Clip to polygon") {
+ const Size2i dim{ 256, 256 };
+ BitMap bit_map{};
+ Vector<Vector<Vector2>> polygons;
+
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
+ CHECK_MESSAGE(polygons.size() == 0, "We should have no polygons, because the BitMap was not initialized");
+
+ bit_map.create(dim);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
+ CHECK_MESSAGE(polygons.size() == 0, "We should have no polygons, because the BitMap was all 0's");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(0, 0, 64, 64), true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
+ CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
+ CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(0, 0, 32, 32), true);
+ bit_map.set_bit_rect(Rect2i(64, 64, 32, 32), true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
+ CHECK_MESSAGE(polygons.size() == 2, "We should have exactly 2 polygons");
+ CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(124, 112, 8, 32), true);
+ bit_map.set_bit_rect(Rect2i(112, 124, 32, 8), true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 256, 256));
+ CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
+ CHECK_MESSAGE(polygons[0].size() == 12, "The polygon should have exactly 12 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(124, 112, 8, 32), true);
+ bit_map.set_bit_rect(Rect2i(112, 124, 32, 8), true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
+ CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
+ CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points");
+}
+
+} // namespace TestBitmap
+
+#endif // TEST_BIT_MAP_H
diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h
index 4fc88f398f..3940bdb37a 100644
--- a/tests/scene/test_code_edit.h
+++ b/tests/scene/test_code_edit.h
@@ -3245,7 +3245,7 @@ TEST_CASE("[SceneTree][CodeEdit] symbol lookup") {
code_edit->set_text("this is some text");
Point2 caret_pos = code_edit->get_caret_draw_pos();
- caret_pos.x += 58;
+ caret_pos.x += 60;
SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, caret_pos, MouseButton::NONE, MouseButton::NONE, Key::NONE);
CHECK(code_edit->get_text_for_symbol_lookup() == "this is s" + String::chr(0xFFFF) + "ome text");
diff --git a/tests/scene/test_curve.h b/tests/scene/test_curve.h
index 0370ab15fd..ad7625ddc5 100644
--- a/tests/scene/test_curve.h
+++ b/tests/scene/test_curve.h
@@ -44,13 +44,13 @@ TEST_CASE("[Curve] Default curve") {
curve->get_point_count() == 0,
"Default curve should contain the expected number of points.");
CHECK_MESSAGE(
- Math::is_zero_approx(curve->interpolate(0)),
+ Math::is_zero_approx(curve->sample(0)),
"Default curve should return the expected value at offset 0.0.");
CHECK_MESSAGE(
- Math::is_zero_approx(curve->interpolate(0.5)),
+ Math::is_zero_approx(curve->sample(0.5)),
"Default curve should return the expected value at offset 0.5.");
CHECK_MESSAGE(
- Math::is_zero_approx(curve->interpolate(1)),
+ Math::is_zero_approx(curve->sample(1)),
"Default curve should return the expected value at offset 1.0.");
}
@@ -80,57 +80,57 @@ TEST_CASE("[Curve] Custom curve with free tangents") {
"Custom free curve should contain the expected number of points.");
CHECK_MESSAGE(
- Math::is_zero_approx(curve->interpolate(-0.1)),
+ Math::is_zero_approx(curve->sample(-0.1)),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.352),
+ Math::is_equal_approx(curve->sample(0.1), (real_t)0.352),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.352),
+ Math::is_equal_approx(curve->sample(0.4), (real_t)0.352),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.896),
+ Math::is_equal_approx(curve->sample(0.7), (real_t)0.896),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(1), 1),
+ Math::is_equal_approx(curve->sample(1), 1),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(2), 1),
+ Math::is_equal_approx(curve->sample(2), 1),
"Custom free curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_zero_approx(curve->interpolate_baked(-0.1)),
+ Math::is_zero_approx(curve->sample_baked(-0.1)),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.352),
+ Math::is_equal_approx(curve->sample_baked(0.1), (real_t)0.352),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.352),
+ Math::is_equal_approx(curve->sample_baked(0.4), (real_t)0.352),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.896),
+ Math::is_equal_approx(curve->sample_baked(0.7), (real_t)0.896),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(1), 1),
+ Math::is_equal_approx(curve->sample_baked(1), 1),
"Custom free curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(2), 1),
+ Math::is_equal_approx(curve->sample_baked(2), 1),
"Custom free curve should return the expected baked value at offset 0.1.");
curve->remove_point(1);
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.1), 0),
+ Math::is_equal_approx(curve->sample(0.1), 0),
"Custom free curve should return the expected value at offset 0.1 after removing point at index 1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.1), 0),
+ Math::is_equal_approx(curve->sample_baked(0.1), 0),
"Custom free curve should return the expected baked value at offset 0.1 after removing point at index 1.");
curve->clear_points();
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.6), 0),
+ Math::is_equal_approx(curve->sample(0.6), 0),
"Custom free curve should return the expected value at offset 0.6 after clearing all points.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.6), 0),
+ Math::is_equal_approx(curve->sample_baked(0.6), 0),
"Custom free curve should return the expected baked value at offset 0.6 after clearing all points.");
}
@@ -169,51 +169,51 @@ TEST_CASE("[Curve] Custom curve with linear tangents") {
"Custom linear curve should contain the expected number of points.");
CHECK_MESSAGE(
- Math::is_zero_approx(curve->interpolate(-0.1)),
+ Math::is_zero_approx(curve->sample(-0.1)),
"Custom linear curve should return the expected value at offset -0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.4),
+ Math::is_equal_approx(curve->sample(0.1), (real_t)0.4),
"Custom linear curve should return the expected value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.4),
+ Math::is_equal_approx(curve->sample(0.4), (real_t)0.4),
"Custom linear curve should return the expected value at offset 0.4.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8),
+ Math::is_equal_approx(curve->sample(0.7), (real_t)0.8),
"Custom linear curve should return the expected value at offset 0.7.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(1), 1),
+ Math::is_equal_approx(curve->sample(1), 1),
"Custom linear curve should return the expected value at offset 1.0.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(2), 1),
+ Math::is_equal_approx(curve->sample(2), 1),
"Custom linear curve should return the expected value at offset 2.0.");
CHECK_MESSAGE(
- Math::is_zero_approx(curve->interpolate_baked(-0.1)),
+ Math::is_zero_approx(curve->sample_baked(-0.1)),
"Custom linear curve should return the expected baked value at offset -0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.4),
+ Math::is_equal_approx(curve->sample_baked(0.1), (real_t)0.4),
"Custom linear curve should return the expected baked value at offset 0.1.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.4),
+ Math::is_equal_approx(curve->sample_baked(0.4), (real_t)0.4),
"Custom linear curve should return the expected baked value at offset 0.4.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8),
+ Math::is_equal_approx(curve->sample_baked(0.7), (real_t)0.8),
"Custom linear curve should return the expected baked value at offset 0.7.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(1), 1),
+ Math::is_equal_approx(curve->sample_baked(1), 1),
"Custom linear curve should return the expected baked value at offset 1.0.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(2), 1),
+ Math::is_equal_approx(curve->sample_baked(2), 1),
"Custom linear curve should return the expected baked value at offset 2.0.");
ERR_PRINT_OFF;
curve->remove_point(10);
ERR_PRINT_ON;
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8),
+ Math::is_equal_approx(curve->sample(0.7), (real_t)0.8),
"Custom free curve should return the expected value at offset 0.7 after removing point at invalid index 10.");
CHECK_MESSAGE(
- Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8),
+ Math::is_equal_approx(curve->sample_baked(0.7), (real_t)0.8),
"Custom free curve should return the expected baked value at offset 0.7 after removing point at invalid index 10.");
}
@@ -228,8 +228,8 @@ TEST_CASE("[Curve2D] Linear sampling should return exact value") {
CHECK(len == baked_length);
for (int i = 0; i < len; i++) {
- Vector2 pos = curve->interpolate_baked(i);
- CHECK_MESSAGE(pos.x == i, "interpolate_baked should return exact value");
+ Vector2 pos = curve->sample_baked(i);
+ CHECK_MESSAGE(pos.x == i, "sample_baked should return exact value");
}
}
@@ -244,8 +244,8 @@ TEST_CASE("[Curve3D] Linear sampling should return exact value") {
CHECK(len == baked_length);
for (int i = 0; i < len; i++) {
- Vector3 pos = curve->interpolate_baked(i);
- CHECK_MESSAGE(pos.x == i, "interpolate_baked should return exact value");
+ Vector3 pos = curve->sample_baked(i);
+ CHECK_MESSAGE(pos.x == i, "sample_baked should return exact value");
}
}
diff --git a/tests/scene/test_path_follow_2d.h b/tests/scene/test_path_follow_2d.h
index abd12fe862..57261116a2 100644
--- a/tests/scene/test_path_follow_2d.h
+++ b/tests/scene/test_path_follow_2d.h
@@ -37,7 +37,7 @@
namespace TestPathFollow2D {
-TEST_CASE("[PathFollow2D] Sampling with unit offset") {
+TEST_CASE("[PathFollow2D] Sampling with progress ratio") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@@ -49,37 +49,37 @@ TEST_CASE("[PathFollow2D] Sampling with unit offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
- path_follow_2d->set_unit_offset(0);
+ path_follow_2d->set_progress_ratio(0);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
- path_follow_2d->set_unit_offset(0.125);
+ path_follow_2d->set_progress_ratio(0.125);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
- path_follow_2d->set_unit_offset(0.25);
+ path_follow_2d->set_progress_ratio(0.25);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
- path_follow_2d->set_unit_offset(0.375);
+ path_follow_2d->set_progress_ratio(0.375);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50)));
- path_follow_2d->set_unit_offset(0.5);
+ path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100)));
- path_follow_2d->set_unit_offset(0.625);
+ path_follow_2d->set_progress_ratio(0.625);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100)));
- path_follow_2d->set_unit_offset(0.75);
+ path_follow_2d->set_progress_ratio(0.75);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100)));
- path_follow_2d->set_unit_offset(0.875);
+ path_follow_2d->set_progress_ratio(0.875);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50)));
- path_follow_2d->set_unit_offset(1);
+ path_follow_2d->set_progress_ratio(1);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
memdelete(path);
}
-TEST_CASE("[PathFollow2D] Sampling with offset") {
+TEST_CASE("[PathFollow2D] Sampling with progress") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@@ -91,31 +91,31 @@ TEST_CASE("[PathFollow2D] Sampling with offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
- path_follow_2d->set_offset(0);
+ path_follow_2d->set_progress(0);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
- path_follow_2d->set_offset(50);
+ path_follow_2d->set_progress(50);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
- path_follow_2d->set_offset(100);
+ path_follow_2d->set_progress(100);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
- path_follow_2d->set_offset(150);
+ path_follow_2d->set_progress(150);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 50)));
- path_follow_2d->set_offset(200);
+ path_follow_2d->set_progress(200);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 100)));
- path_follow_2d->set_offset(250);
+ path_follow_2d->set_progress(250);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 100)));
- path_follow_2d->set_offset(300);
+ path_follow_2d->set_progress(300);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 100)));
- path_follow_2d->set_offset(350);
+ path_follow_2d->set_progress(350);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 50)));
- path_follow_2d->set_offset(400);
+ path_follow_2d->set_progress(400);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(0, 0)));
memdelete(path);
@@ -131,7 +131,7 @@ TEST_CASE("[PathFollow2D] Removal of a point in curve") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
- path_follow_2d->set_unit_offset(0.5);
+ path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(100, 0)));
curve->remove_point(1);
@@ -152,7 +152,7 @@ TEST_CASE("[PathFollow2D] Setting h_offset and v_offset") {
const PathFollow2D *path_follow_2d = memnew(PathFollow2D);
path->add_child(path_follow_2d);
- path_follow_2d->set_unit_offset(0.5);
+ path_follow_2d->set_progress_ratio(0.5);
CHECK(path_follow_2d->get_transform().get_origin().is_equal_approx(Vector2(50, 0)));
path_follow_2d->set_h_offset(25);
@@ -175,32 +175,32 @@ TEST_CASE("[PathFollow2D] Unit offset out of range") {
path_follow_2d->set_loop(true);
- path_follow_2d->set_unit_offset(-0.3);
+ path_follow_2d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
- path_follow_2d->get_unit_offset() == 0.7,
- "Unit Offset should loop back from the end in the opposite direction");
+ path_follow_2d->get_progress_ratio() == 0.7,
+ "Progress Ratio should loop back from the end in the opposite direction");
- path_follow_2d->set_unit_offset(1.3);
+ path_follow_2d->set_progress_ratio(1.3);
CHECK_MESSAGE(
- path_follow_2d->get_unit_offset() == 0.3,
- "Unit Offset should loop back from the end in the opposite direction");
+ path_follow_2d->get_progress_ratio() == 0.3,
+ "Progress Ratio should loop back from the end in the opposite direction");
path_follow_2d->set_loop(false);
- path_follow_2d->set_unit_offset(-0.3);
+ path_follow_2d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
- path_follow_2d->get_unit_offset() == 0,
- "Unit Offset should be clamped at 0");
+ path_follow_2d->get_progress_ratio() == 0,
+ "Progress Ratio should be clamped at 0");
- path_follow_2d->set_unit_offset(1.3);
+ path_follow_2d->set_progress_ratio(1.3);
CHECK_MESSAGE(
- path_follow_2d->get_unit_offset() == 1,
- "Unit Offset should be clamped at 1");
+ path_follow_2d->get_progress_ratio() == 1,
+ "Progress Ratio should be clamped at 1");
memdelete(path);
}
-TEST_CASE("[PathFollow2D] Offset out of range") {
+TEST_CASE("[PathFollow2D] Progress out of range") {
const Ref<Curve2D> &curve = memnew(Curve2D());
curve->add_point(Vector2(0, 0));
curve->add_point(Vector2(100, 0));
@@ -211,27 +211,27 @@ TEST_CASE("[PathFollow2D] Offset out of range") {
path_follow_2d->set_loop(true);
- path_follow_2d->set_offset(-50);
+ path_follow_2d->set_progress(-50);
CHECK_MESSAGE(
- path_follow_2d->get_offset() == 50,
- "Offset should loop back from the end in the opposite direction");
+ path_follow_2d->get_progress() == 50,
+ "Progress should loop back from the end in the opposite direction");
- path_follow_2d->set_offset(150);
+ path_follow_2d->set_progress(150);
CHECK_MESSAGE(
- path_follow_2d->get_offset() == 50,
- "Offset should loop back from the end in the opposite direction");
+ path_follow_2d->get_progress() == 50,
+ "Progress should loop back from the end in the opposite direction");
path_follow_2d->set_loop(false);
- path_follow_2d->set_offset(-50);
+ path_follow_2d->set_progress(-50);
CHECK_MESSAGE(
- path_follow_2d->get_offset() == 0,
- "Offset should be clamped at 0");
+ path_follow_2d->get_progress() == 0,
+ "Progress should be clamped at 0");
- path_follow_2d->set_offset(150);
+ path_follow_2d->set_progress(150);
CHECK_MESSAGE(
- path_follow_2d->get_offset() == 100,
- "Offset should be clamped at 1");
+ path_follow_2d->get_progress() == 100,
+ "Progress should be clamped at 1");
memdelete(path);
}
diff --git a/tests/scene/test_path_follow_3d.h b/tests/scene/test_path_follow_3d.h
index 9ffe49e3d6..6334fa56de 100644
--- a/tests/scene/test_path_follow_3d.h
+++ b/tests/scene/test_path_follow_3d.h
@@ -37,7 +37,7 @@
namespace TestPathFollow3D {
-TEST_CASE("[PathFollow3D] Sampling with unit offset") {
+TEST_CASE("[PathFollow3D] Sampling with progress ratio") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@@ -49,37 +49,37 @@ TEST_CASE("[PathFollow3D] Sampling with unit offset") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
- path_follow_3d->set_unit_offset(0);
+ path_follow_3d->set_progress_ratio(0);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0));
- path_follow_3d->set_unit_offset(0.125);
+ path_follow_3d->set_progress_ratio(0.125);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0));
- path_follow_3d->set_unit_offset(0.25);
+ path_follow_3d->set_progress_ratio(0.25);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0);
- path_follow_3d->set_unit_offset(0.375);
+ path_follow_3d->set_progress_ratio(0.375);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0)));
- path_follow_3d->set_unit_offset(0.5);
+ path_follow_3d->set_progress_ratio(0.5);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0)));
- path_follow_3d->set_unit_offset(0.625);
+ path_follow_3d->set_progress_ratio(0.625);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50)));
- path_follow_3d->set_unit_offset(0.75);
+ path_follow_3d->set_progress_ratio(0.75);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100)));
- path_follow_3d->set_unit_offset(0.875);
+ path_follow_3d->set_progress_ratio(0.875);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100)));
- path_follow_3d->set_unit_offset(1);
+ path_follow_3d->set_progress_ratio(1);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100)));
memdelete(path);
}
-TEST_CASE("[PathFollow3D] Sampling with offset") {
+TEST_CASE("[PathFollow3D] Sampling with progress") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@@ -91,31 +91,31 @@ TEST_CASE("[PathFollow3D] Sampling with offset") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
- path_follow_3d->set_offset(0);
+ path_follow_3d->set_progress(0);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(0, 0, 0));
- path_follow_3d->set_offset(50);
+ path_follow_3d->set_progress(50);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(50, 0, 0));
- path_follow_3d->set_offset(100);
+ path_follow_3d->set_progress(100);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 0);
- path_follow_3d->set_offset(150);
+ path_follow_3d->set_progress(150);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 0)));
- path_follow_3d->set_offset(200);
+ path_follow_3d->set_progress(200);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 0)));
- path_follow_3d->set_offset(250);
+ path_follow_3d->set_progress(250);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 50)));
- path_follow_3d->set_offset(300);
+ path_follow_3d->set_progress(300);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 100, 100)));
- path_follow_3d->set_offset(350);
+ path_follow_3d->set_progress(350);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 50, 100)));
- path_follow_3d->set_offset(400);
+ path_follow_3d->set_progress(400);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector3(100, 0, 100)));
memdelete(path);
@@ -131,7 +131,7 @@ TEST_CASE("[PathFollow3D] Removal of a point in curve") {
const PathFollow3D *path_follow_3d = memnew(PathFollow3D);
path->add_child(path_follow_3d);
- path_follow_3d->set_unit_offset(0.5);
+ path_follow_3d->set_progress_ratio(0.5);
CHECK(path_follow_3d->get_transform().get_origin().is_equal_approx(Vector2(100, 0, 0)));
curve->remove_point(1);
@@ -143,7 +143,7 @@ TEST_CASE("[PathFollow3D] Removal of a point in curve") {
memdelete(path);
}
-TEST_CASE("[PathFollow3D] Unit offset out of range") {
+TEST_CASE("[PathFollow3D] Progress ratio out of range") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@@ -154,32 +154,32 @@ TEST_CASE("[PathFollow3D] Unit offset out of range") {
path_follow_3d->set_loop(true);
- path_follow_3d->set_unit_offset(-0.3);
+ path_follow_3d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
- path_follow_3d->get_unit_offset() == 0.7,
- "Unit Offset should loop back from the end in the opposite direction");
+ path_follow_3d->get_progress_ratio() == 0.7,
+ "Progress Ratio should loop back from the end in the opposite direction");
- path_follow_3d->set_unit_offset(1.3);
+ path_follow_3d->set_progress_ratio(1.3);
CHECK_MESSAGE(
- path_follow_3d->get_unit_offset() == 0.3,
- "Unit Offset should loop back from the end in the opposite direction");
+ path_follow_3d->get_progress_ratio() == 0.3,
+ "Progress Ratio should loop back from the end in the opposite direction");
path_follow_3d->set_loop(false);
- path_follow_3d->set_unit_offset(-0.3);
+ path_follow_3d->set_progress_ratio(-0.3);
CHECK_MESSAGE(
- path_follow_3d->get_unit_offset() == 0,
- "Unit Offset should be clamped at 0");
+ path_follow_3d->get_progress_ratio() == 0,
+ "Progress Ratio should be clamped at 0");
- path_follow_3d->set_unit_offset(1.3);
+ path_follow_3d->set_progress_ratio(1.3);
CHECK_MESSAGE(
- path_follow_3d->get_unit_offset() == 1,
- "Unit Offset should be clamped at 1");
+ path_follow_3d->get_progress_ratio() == 1,
+ "Progress Ratio should be clamped at 1");
memdelete(path);
}
-TEST_CASE("[PathFollow3D] Offset out of range") {
+TEST_CASE("[PathFollow3D] Progress out of range") {
const Ref<Curve3D> &curve = memnew(Curve3D());
curve->add_point(Vector3(0, 0, 0));
curve->add_point(Vector3(100, 0, 0));
@@ -190,27 +190,27 @@ TEST_CASE("[PathFollow3D] Offset out of range") {
path_follow_3d->set_loop(true);
- path_follow_3d->set_offset(-50);
+ path_follow_3d->set_progress(-50);
CHECK_MESSAGE(
- path_follow_3d->get_offset() == 50,
- "Offset should loop back from the end in the opposite direction");
+ path_follow_3d->get_progress() == 50,
+ "Progress should loop back from the end in the opposite direction");
- path_follow_3d->set_offset(150);
+ path_follow_3d->set_progress(150);
CHECK_MESSAGE(
- path_follow_3d->get_offset() == 50,
- "Offset should loop back from the end in the opposite direction");
+ path_follow_3d->get_progress() == 50,
+ "Progress should loop back from the end in the opposite direction");
path_follow_3d->set_loop(false);
- path_follow_3d->set_offset(-50);
+ path_follow_3d->set_progress(-50);
CHECK_MESSAGE(
- path_follow_3d->get_offset() == 0,
- "Offset should be clamped at 0");
+ path_follow_3d->get_progress() == 0,
+ "Progress should be clamped at 0");
- path_follow_3d->set_offset(150);
+ path_follow_3d->set_progress(150);
CHECK_MESSAGE(
- path_follow_3d->get_offset() == 100,
- "Offset should be clamped at max value of curve");
+ path_follow_3d->get_progress() == 100,
+ "Progress should be clamped at max value of curve");
memdelete(path);
}
diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h
index 0fce359c5a..225316b293 100644
--- a/tests/scene/test_text_edit.h
+++ b/tests/scene/test_text_edit.h
@@ -727,7 +727,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::SHIFT | KeyModifierMask::ALT)
#else
- SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::SHIFT | KeyModifierMask::CMD)
+ SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::SHIFT | KeyModifierMask::CMD_OR_CTRL)
#endif
CHECK(text_edit->has_selection());
CHECK(text_edit->get_selected_text() == "test");
@@ -739,7 +739,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::SHIFT | KeyModifierMask::ALT)
#else
- SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::SHIFT | KeyModifierMask::CMD)
+ SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::SHIFT | KeyModifierMask::CMD_OR_CTRL)
#endif
CHECK_FALSE(text_edit->has_selection());
CHECK(text_edit->get_selected_text() == "");
@@ -1387,7 +1387,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
text_edit->set_caret_column(4);
MessageQueue::get_singleton()->flush();
- Ref<InputEvent> tmpevent = InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::ALT | KeyModifierMask::CMD);
+ Ref<InputEvent> tmpevent = InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::ALT | KeyModifierMask::CMD_OR_CTRL);
InputMap::get_singleton()->action_add_event("ui_text_backspace_all_to_left", tmpevent);
SIGNAL_DISCARD("text_set");
@@ -1624,7 +1624,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
}
SUBCASE("[TextEdit] ui_text_delete_all_to_right") {
- Ref<InputEvent> tmpevent = InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::ALT | KeyModifierMask::CMD);
+ Ref<InputEvent> tmpevent = InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::ALT | KeyModifierMask::CMD_OR_CTRL);
InputMap::get_singleton()->action_add_event("ui_text_delete_all_to_right", tmpevent);
text_edit->set_text("this is some test text.\n");
@@ -1905,7 +1905,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::ALT | KeyModifierMask::SHIFT);
#else
- SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
+ SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT);
#endif
CHECK(text_edit->get_viewport()->is_input_handled());
CHECK(text_edit->get_text() == "\nthis is some test text.");
@@ -2016,7 +2016,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
#ifdef MACOS_ENABLED
SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::ALT | KeyModifierMask::SHIFT);
#else
- SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
+ SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT);
#endif
CHECK(text_edit->get_viewport()->is_input_handled());
CHECK(text_edit->get_text() == "this is some test text\n");
@@ -2245,9 +2245,9 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("caret_changed");
#ifdef MACOS_ENABLED
- SEND_GUI_KEY_EVENT(text_edit, Key::UP | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
+ SEND_GUI_KEY_EVENT(text_edit, Key::UP | KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT);
#else
- SEND_GUI_KEY_EVENT(text_edit, Key::HOME | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
+ SEND_GUI_KEY_EVENT(text_edit, Key::HOME | KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT);
#endif
CHECK(text_edit->get_viewport()->is_input_handled());
CHECK(text_edit->get_text() == "this is some\nother test\nlines\ngo here");
@@ -2286,9 +2286,9 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("caret_changed");
#ifdef MACOS_ENABLED
- SEND_GUI_KEY_EVENT(text_edit, Key::DOWN | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
+ SEND_GUI_KEY_EVENT(text_edit, Key::DOWN | KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT);
#else
- SEND_GUI_KEY_EVENT(text_edit, Key::END | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
+ SEND_GUI_KEY_EVENT(text_edit, Key::END | KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT);
#endif
CHECK(text_edit->get_viewport()->is_input_handled());
CHECK(text_edit->get_text() == "go here\nlines\nother test\nthis is some");
@@ -2327,7 +2327,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("caret_changed");
#ifdef MACOS_ENABLED
- SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
+ SEND_GUI_KEY_EVENT(text_edit, Key::LEFT | KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT);
#else
SEND_GUI_KEY_EVENT(text_edit, Key::HOME | KeyModifierMask::SHIFT);
#endif
@@ -2384,7 +2384,7 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_DISCARD("caret_changed");
#ifdef MACOS_ENABLED
- SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::CMD | KeyModifierMask::SHIFT);
+ SEND_GUI_KEY_EVENT(text_edit, Key::RIGHT | KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT);
#else
SEND_GUI_KEY_EVENT(text_edit, Key::END | KeyModifierMask::SHIFT);
#endif
@@ -2714,15 +2714,15 @@ TEST_CASE("[SceneTree][TextEdit] caret") {
text_edit->set_caret_blink_enabled(true);
CHECK(text_edit->is_caret_blink_enabled());
- text_edit->set_caret_blink_speed(10);
- CHECK(text_edit->get_caret_blink_speed() == 10);
+ text_edit->set_caret_blink_interval(10);
+ CHECK(text_edit->get_caret_blink_interval() == 10);
ERR_PRINT_OFF;
- text_edit->set_caret_blink_speed(-1);
- CHECK(text_edit->get_caret_blink_speed() == 10);
+ text_edit->set_caret_blink_interval(-1);
+ CHECK(text_edit->get_caret_blink_interval() == 10);
- text_edit->set_caret_blink_speed(0);
- CHECK(text_edit->get_caret_blink_speed() == 10);
+ text_edit->set_caret_blink_interval(0);
+ CHECK(text_edit->get_caret_blink_interval() == 10);
ERR_PRINT_ON;
text_edit->set_caret_type(TextEdit::CaretType::CARET_TYPE_LINE);
@@ -3388,6 +3388,8 @@ TEST_CASE("[SceneTree][TextEdit] gutters") {
SUBCASE("[TextEdit] gutter add and remove") {
text_edit->add_gutter();
CHECK(text_edit->get_gutter_count() == 1);
+ CHECK(text_edit->get_gutter_width(0) == 24);
+ CHECK(text_edit->get_total_gutter_width() == 24 + 2);
SIGNAL_CHECK("gutter_added", empty_signal_args);
text_edit->set_gutter_name(0, "test_gutter");
@@ -3395,39 +3397,43 @@ TEST_CASE("[SceneTree][TextEdit] gutters") {
text_edit->set_gutter_width(0, 10);
CHECK(text_edit->get_gutter_width(0) == 10);
- CHECK(text_edit->get_total_gutter_width() > 10);
- CHECK(text_edit->get_total_gutter_width() < 20);
+ CHECK(text_edit->get_total_gutter_width() == 10 + 2);
text_edit->add_gutter(-100);
text_edit->set_gutter_width(1, 10);
- CHECK(text_edit->get_total_gutter_width() > 20);
- CHECK(text_edit->get_total_gutter_width() < 30);
+ CHECK(text_edit->get_gutter_width(1) == 10);
+ CHECK(text_edit->get_total_gutter_width() == 20 + 2);
CHECK(text_edit->get_gutter_count() == 2);
CHECK(text_edit->get_gutter_name(0) == "test_gutter");
SIGNAL_CHECK("gutter_added", empty_signal_args);
text_edit->set_gutter_draw(1, false);
- CHECK(text_edit->get_total_gutter_width() > 10);
- CHECK(text_edit->get_total_gutter_width() < 20);
+ CHECK(text_edit->get_total_gutter_width() == 10 + 2);
text_edit->add_gutter(100);
CHECK(text_edit->get_gutter_count() == 3);
+ CHECK(text_edit->get_gutter_width(2) == 24);
+ CHECK(text_edit->get_total_gutter_width() == 34 + 2);
CHECK(text_edit->get_gutter_name(0) == "test_gutter");
SIGNAL_CHECK("gutter_added", empty_signal_args);
text_edit->add_gutter(0);
CHECK(text_edit->get_gutter_count() == 4);
+ CHECK(text_edit->get_gutter_width(0) == 24);
+ CHECK(text_edit->get_total_gutter_width() == 58 + 2);
CHECK(text_edit->get_gutter_name(1) == "test_gutter");
SIGNAL_CHECK("gutter_added", empty_signal_args);
text_edit->remove_gutter(2);
CHECK(text_edit->get_gutter_name(1) == "test_gutter");
CHECK(text_edit->get_gutter_count() == 3);
+ CHECK(text_edit->get_total_gutter_width() == 58 + 2);
SIGNAL_CHECK("gutter_removed", empty_signal_args);
text_edit->remove_gutter(0);
CHECK(text_edit->get_gutter_name(0) == "test_gutter");
CHECK(text_edit->get_gutter_count() == 2);
+ CHECK(text_edit->get_total_gutter_width() == 34 + 2);
SIGNAL_CHECK("gutter_removed", empty_signal_args);
ERR_PRINT_OFF;
diff --git a/tests/test_macros.h b/tests/test_macros.h
index 69ae0d3124..3b734b9699 100644
--- a/tests/test_macros.h
+++ b/tests/test_macros.h
@@ -133,11 +133,11 @@ int register_test_command(String p_command, TestFunc p_function);
// Utility macros to send an event actions to a given object
// Requires Message Queue and InputMap to be setup.
// SEND_GUI_ACTION - takes an object and a input map key. e.g SEND_GUI_ACTION(code_edit, "ui_text_newline").
-// SEND_GUI_KEY_EVENT - takes an object and a keycode set. e.g SEND_GUI_KEY_EVENT(code_edit, Key::A | KeyModifierMask::CMD).
+// SEND_GUI_KEY_EVENT - takes an object and a keycode set. e.g SEND_GUI_KEY_EVENT(code_edit, Key::A | KeyModifierMask::META).
// SEND_GUI_MOUSE_BUTTON_EVENT - takes an object, position, mouse button, mouse mask and modifiers e.g SEND_GUI_MOUSE_BUTTON_EVENT(code_edit, Vector2(50, 50), MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE, Key::None);
// SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT - takes an object, position, mouse button, mouse mask and modifiers e.g SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(code_edit, Vector2(50, 50), MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE, Key::None);
-// SEND_GUI_MOUSE_MOTION_EVENT - takes an object, position, mouse mask and modifiers e.g SEND_GUI_MOUSE_MOTION_EVENT(code_edit, Vector2(50, 50), MouseButton::MASK_LEFT, KeyModifierMask::CMD);
-// SEND_GUI_DOUBLE_CLICK - takes an object, position and modifiers. e.g SEND_GUI_DOUBLE_CLICK(code_edit, Vector2(50, 50), KeyModifierMask::CMD);
+// SEND_GUI_MOUSE_MOTION_EVENT - takes an object, position, mouse mask and modifiers e.g SEND_GUI_MOUSE_MOTION_EVENT(code_edit, Vector2(50, 50), MouseButton::MASK_LEFT, KeyModifierMask::META);
+// SEND_GUI_DOUBLE_CLICK - takes an object, position and modifiers. e.g SEND_GUI_DOUBLE_CLICK(code_edit, Vector2(50, 50), KeyModifierMask::META);
#define SEND_GUI_ACTION(m_object, m_action) \
{ \
@@ -161,7 +161,6 @@ int register_test_command(String p_command, TestFunc p_function);
m_event->set_shift_pressed(((m_modifers)&KeyModifierMask::SHIFT) != Key::NONE); \
m_event->set_alt_pressed(((m_modifers)&KeyModifierMask::ALT) != Key::NONE); \
m_event->set_ctrl_pressed(((m_modifers)&KeyModifierMask::CTRL) != Key::NONE); \
- m_event->set_command_pressed(((m_modifers)&KeyModifierMask::CMD) != Key::NONE); \
m_event->set_meta_pressed(((m_modifers)&KeyModifierMask::META) != Key::NONE);
#define _CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, m_input, m_mask, m_modifers) \
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index 3d186711cb..4c861eacba 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -85,6 +85,7 @@
#include "tests/core/variant/test_variant.h"
#include "tests/scene/test_animation.h"
#include "tests/scene/test_audio_stream_wav.h"
+#include "tests/scene/test_bit_map.h"
#include "tests/scene/test_code_edit.h"
#include "tests/scene/test_curve.h"
#include "tests/scene/test_gradient.h"
@@ -99,7 +100,7 @@
#include "tests/test_macros.h"
-#include "scene/resources/default_theme/default_theme.h"
+#include "scene/theme/theme_db.h"
#include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h"
#include "servers/physics_server_2d.h"
@@ -179,6 +180,7 @@ struct GodotTestCaseListener : public doctest::IReporter {
PhysicsServer2D *physics_server_2d = nullptr;
NavigationServer3D *navigation_server_3d = nullptr;
NavigationServer2D *navigation_server_2d = nullptr;
+ ThemeDB *theme_db = nullptr;
void test_case_start(const doctest::TestCaseData &p_in) override {
SignalWatcher::get_singleton()->_clear_signals();
@@ -205,10 +207,10 @@ struct GodotTestCaseListener : public doctest::IReporter {
RenderingServerDefault::get_singleton()->init();
RenderingServerDefault::get_singleton()->set_render_loop_enabled(false);
- physics_server_3d = PhysicsServer3DManager::new_default_server();
+ physics_server_3d = PhysicsServer3DManager::get_singleton()->new_default_server();
physics_server_3d->init();
- physics_server_2d = PhysicsServer2DManager::new_default_server();
+ physics_server_2d = PhysicsServer2DManager::get_singleton()->new_default_server();
physics_server_2d->init();
navigation_server_3d = NavigationServer3DManager::new_default_server();
@@ -217,7 +219,8 @@ struct GodotTestCaseListener : public doctest::IReporter {
memnew(InputMap);
InputMap::get_singleton()->load_default();
- make_default_theme(1.0, Ref<Font>());
+ theme_db = memnew(ThemeDB);
+ theme_db->initialize_theme_noproject();
memnew(SceneTree);
SceneTree::get_singleton()->initialize();
@@ -247,7 +250,10 @@ struct GodotTestCaseListener : public doctest::IReporter {
memdelete(SceneTree::get_singleton());
}
- clear_default_theme();
+ if (theme_db) {
+ memdelete(theme_db);
+ theme_db = nullptr;
+ }
if (navigation_server_3d) {
memdelete(navigation_server_3d);
@@ -277,7 +283,7 @@ struct GodotTestCaseListener : public doctest::IReporter {
if (RenderingServer::get_singleton()) {
RenderingServer::get_singleton()->sync();
- RenderingServer::get_singleton()->global_shader_uniforms_clear();
+ RenderingServer::get_singleton()->global_shader_parameters_clear();
RenderingServer::get_singleton()->finish();
memdelete(RenderingServer::get_singleton());
}
diff --git a/tests/test_utils.cpp b/tests/test_utils.cpp
index 11cb6398aa..ce12a30381 100644
--- a/tests/test_utils.cpp
+++ b/tests/test_utils.cpp
@@ -34,7 +34,7 @@
String TestUtils::get_data_path(const String &p_file) {
String data_path = "../tests/data";
- return get_executable_dir().plus_file(data_path.plus_file(p_file));
+ return get_executable_dir().path_join(data_path.path_join(p_file));
}
String TestUtils::get_executable_dir() {