Removed tests.

This commit is contained in:
Relintai 2023-12-14 23:03:36 +01:00
parent fb1cf5ff2a
commit 900620569f
37 changed files with 0 additions and 7886 deletions

View File

@ -54,7 +54,6 @@
#include "main/main_timer_sync.h"
#include "main/performance.h"
#include "main/splash.gen.h"
#include "main/tests/test_main.h"
#include "modules/register_module_types.h"
#include "platform/register_platform_apis.h"
#include "scene/debugger/script_debugger_remote.h"

View File

@ -1,9 +0,0 @@
#!/usr/bin/python
Import("env")
env.tests_sources = []
env.add_source_files(env.tests_sources, "*.cpp")
lib = env.add_library("tests", env.tests_sources)
env.Prepend(LIBS=[lib])

View File

@ -1,409 +0,0 @@
/*************************************************************************/
/* test_astar.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_astar.h"
#include "core/math/a_star.h"
#include "core/math/math_funcs.h"
#include "core/os/os.h"
#include <math.h>
#include <stdio.h>
namespace TestAStar {
class ABCX : public AStar {
public:
enum { A,
B,
C,
X };
ABCX() {
add_point(A, Vector3(0, 0, 0));
add_point(B, Vector3(1, 0, 0));
add_point(C, Vector3(0, 1, 0));
add_point(X, Vector3(0, 0, 1));
connect_points(A, B);
connect_points(A, C);
connect_points(B, C);
connect_points(X, A);
}
// Disable heuristic completely
float _compute_cost(int p_from, int p_to) {
if (p_from == A && p_to == C) {
return 1000;
}
return 100;
}
};
bool test_abc() {
ABCX abcx;
PoolVector<int> path = abcx.get_id_path(ABCX::A, ABCX::C);
bool ok = path.size() == 3;
int i = 0;
ok = ok && path[i++] == ABCX::A;
ok = ok && path[i++] == ABCX::B;
ok = ok && path[i++] == ABCX::C;
return ok;
}
bool test_abcx() {
ABCX abcx;
PoolVector<int> path = abcx.get_id_path(ABCX::X, ABCX::C);
bool ok = path.size() == 4;
int i = 0;
ok = ok && path[i++] == ABCX::X;
ok = ok && path[i++] == ABCX::A;
ok = ok && path[i++] == ABCX::B;
ok = ok && path[i++] == ABCX::C;
return ok;
}
bool test_add_remove() {
AStar a;
bool ok = true;
// Manual tests
a.add_point(1, Vector3(0, 0, 0));
a.add_point(2, Vector3(0, 1, 0));
a.add_point(3, Vector3(1, 1, 0));
a.add_point(4, Vector3(2, 0, 0));
a.connect_points(1, 2, true);
a.connect_points(1, 3, true);
a.connect_points(1, 4, false);
ok = ok && (a.are_points_connected(2, 1));
ok = ok && (a.are_points_connected(4, 1));
ok = ok && (a.are_points_connected(2, 1, false));
ok = ok && (a.are_points_connected(4, 1, false) == false);
a.disconnect_points(1, 2, true);
ok = ok && (a.get_point_connections(1).size() == 2); // 3, 4
ok = ok && (a.get_point_connections(2).size() == 0);
a.disconnect_points(4, 1, false);
ok = ok && (a.get_point_connections(1).size() == 2); // 3, 4
ok = ok && (a.get_point_connections(4).size() == 0);
a.disconnect_points(4, 1, true);
ok = ok && (a.get_point_connections(1).size() == 1); // 3
ok = ok && (a.get_point_connections(4).size() == 0);
a.connect_points(2, 3, false);
ok = ok && (a.get_point_connections(2).size() == 1); // 3
ok = ok && (a.get_point_connections(3).size() == 1); // 1
a.connect_points(2, 3, true);
ok = ok && (a.get_point_connections(2).size() == 1); // 3
ok = ok && (a.get_point_connections(3).size() == 2); // 1, 2
a.disconnect_points(2, 3, false);
ok = ok && (a.get_point_connections(2).size() == 0);
ok = ok && (a.get_point_connections(3).size() == 2); // 1, 2
a.connect_points(4, 3, true);
ok = ok && (a.get_point_connections(3).size() == 3); // 1, 2, 4
ok = ok && (a.get_point_connections(4).size() == 1); // 3
a.disconnect_points(3, 4, false);
ok = ok && (a.get_point_connections(3).size() == 2); // 1, 2
ok = ok && (a.get_point_connections(4).size() == 1); // 3
a.remove_point(3);
ok = ok && (a.get_point_connections(1).size() == 0);
ok = ok && (a.get_point_connections(2).size() == 0);
ok = ok && (a.get_point_connections(4).size() == 0);
a.add_point(0, Vector3(0, -1, 0));
a.add_point(3, Vector3(2, 1, 0));
// 0: (0, -1)
// 1: (0, 0)
// 2: (0, 1)
// 3: (2, 1)
// 4: (2, 0)
// Tests for get_closest_position_in_segment
a.connect_points(2, 3);
ok = ok && (a.get_closest_position_in_segment(Vector3(0.5, 0.5, 0)) == Vector3(0.5, 1, 0));
a.connect_points(3, 4);
a.connect_points(0, 3);
a.connect_points(1, 4);
a.disconnect_points(1, 4, false);
a.disconnect_points(4, 3, false);
a.disconnect_points(3, 4, false);
// Remaining edges: <2, 3>, <0, 3>, <1, 4> (directed)
ok = ok && (a.get_closest_position_in_segment(Vector3(2, 0.5, 0)) == Vector3(1.75, 0.75, 0));
ok = ok && (a.get_closest_position_in_segment(Vector3(-1, 0.2, 0)) == Vector3(0, 0, 0));
ok = ok && (a.get_closest_position_in_segment(Vector3(3, 2, 0)) == Vector3(2, 1, 0));
Math::seed(0);
// Random tests for connectivity checks
for (int i = 0; i < 20000; i++) {
int u = Math::rand() % 5;
int v = Math::rand() % 4;
if (u == v) {
v = 4;
}
if (Math::rand() % 2 == 1) {
// Add a (possibly existing) directed edge and confirm connectivity
a.connect_points(u, v, false);
ok = ok && (a.are_points_connected(u, v, false));
} else {
// Remove a (possibly nonexistent) directed edge and confirm disconnectivity
a.disconnect_points(u, v, false);
ok = ok && (a.are_points_connected(u, v, false) == false);
}
}
// Random tests for point removal
for (int i = 0; i < 20000; i++) {
a.clear();
for (int j = 0; j < 5; j++) {
a.add_point(j, Vector3(0, 0, 0));
}
// Add or remove random edges
for (int j = 0; j < 10; j++) {
int u = Math::rand() % 5;
int v = Math::rand() % 4;
if (u == v) {
v = 4;
}
if (Math::rand() % 2 == 1) {
a.connect_points(u, v, false);
} else {
a.disconnect_points(u, v, false);
}
}
// Remove point 0
a.remove_point(0);
// White box: this will check all edges remaining in the segments set
for (int j = 1; j < 5; j++) {
ok = ok && (a.are_points_connected(0, j, true) == false);
}
}
// It's been great work, cheers \(^ ^)/
return ok;
}
bool test_solutions() {
// Random stress tests with Floyd-Warshall
const int N = 30;
Math::seed(0);
for (int test = 0; test < 1000; test++) {
AStar a;
Vector3 p[N];
bool adj[N][N] = { { false } };
// Assign initial coordinates
for (int u = 0; u < N; u++) {
p[u].x = Math::rand() % 100;
p[u].y = Math::rand() % 100;
p[u].z = Math::rand() % 100;
a.add_point(u, p[u]);
}
// Generate a random sequence of operations
for (int i = 0; i < 1000; i++) {
// Pick two different vertices
int u, v;
u = Math::rand() % N;
v = Math::rand() % (N - 1);
if (u == v) {
v = N - 1;
}
// Pick a random operation
int op = Math::rand();
switch (op % 9) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
// Add edge (u, v); possibly bidirectional
a.connect_points(u, v, op % 2);
adj[u][v] = true;
if (op % 2) {
adj[v][u] = true;
}
break;
case 6:
case 7:
// Remove edge (u, v); possibly bidirectional
a.disconnect_points(u, v, op % 2);
adj[u][v] = false;
if (op % 2) {
adj[v][u] = false;
}
break;
case 8:
// Remove point u and add it back; clears adjacent edges and changes coordinates
a.remove_point(u);
p[u].x = Math::rand() % 100;
p[u].y = Math::rand() % 100;
p[u].z = Math::rand() % 100;
a.add_point(u, p[u]);
for (v = 0; v < N; v++) {
adj[u][v] = adj[v][u] = false;
}
break;
}
}
// Floyd-Warshall
float d[N][N];
for (int u = 0; u < N; u++) {
for (int v = 0; v < N; v++) {
d[u][v] = (u == v || adj[u][v]) ? p[u].distance_to(p[v]) : INFINITY;
}
}
for (int w = 0; w < N; w++) {
for (int u = 0; u < N; u++) {
for (int v = 0; v < N; v++) {
if (d[u][v] > d[u][w] + d[w][v]) {
d[u][v] = d[u][w] + d[w][v];
}
}
}
}
// Display statistics
int count = 0;
for (int u = 0; u < N; u++) {
for (int v = 0; v < N; v++) {
if (adj[u][v]) {
count++;
}
}
}
printf("Test #%4d: %3d edges, ", test + 1, count);
count = 0;
for (int u = 0; u < N; u++) {
for (int v = 0; v < N; v++) {
if (!Math::is_inf(d[u][v])) {
count++;
}
}
}
printf("%3d/%d pairs of reachable points\n", count - N, N * (N - 1));
// Check A*'s output
bool match = true;
for (int u = 0; u < N; u++) {
for (int v = 0; v < N; v++) {
if (u != v) {
PoolVector<int> route = a.get_id_path(u, v);
if (!Math::is_inf(d[u][v])) {
// Reachable
if (route.size() == 0) {
printf("From %d to %d: A* did not find a path\n", u, v);
match = false;
goto exit;
}
float astar_dist = 0;
for (int i = 1; i < route.size(); i++) {
if (!adj[route[i - 1]][route[i]]) {
printf("From %d to %d: edge (%d, %d) does not exist\n",
u, v, route[i - 1], route[i]);
match = false;
goto exit;
}
astar_dist += p[route[i - 1]].distance_to(p[route[i]]);
}
if (!Math::is_equal_approx(astar_dist, d[u][v])) {
printf("From %d to %d: Floyd-Warshall gives %.6f, A* gives %.6f\n",
u, v, d[u][v], astar_dist);
match = false;
goto exit;
}
} else {
// Unreachable
if (route.size() > 0) {
printf("From %d to %d: A* somehow found a nonexistent path\n", u, v);
match = false;
goto exit;
}
}
}
}
}
exit:
if (!match) {
return false;
}
}
return true;
}
typedef bool (*TestFunc)();
TestFunc test_funcs[] = {
test_abc,
test_abcx,
test_add_remove,
test_solutions,
nullptr
};
MainLoop *test() {
int count = 0;
int passed = 0;
while (true) {
if (!test_funcs[count]) {
break;
}
bool pass = test_funcs[count]();
if (pass) {
passed++;
}
OS::get_singleton()->print("\t%s\n", pass ? "PASS" : "FAILED");
count++;
}
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Passed %i of %i tests\n", passed, count);
return nullptr;
}
} // namespace TestAStar

View File

@ -1,40 +0,0 @@
#ifndef TEST_ASTAR_H
#define TEST_ASTAR_H
/*************************************************************************/
/* test_astar.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestAStar {
MainLoop *test();
}
#endif

View File

@ -1,390 +0,0 @@
/*************************************************************************/
/* test_basis.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_basis.h"
#include "core/math/random_number_generator.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
namespace TestBasis {
enum RotOrder {
EulerXYZ,
EulerXZY,
EulerYZX,
EulerYXZ,
EulerZXY,
EulerZYX
};
Vector3 deg2rad(const Vector3 &p_rotation) {
return p_rotation / 180.0 * Math_PI;
}
Vector3 rad2deg(const Vector3 &p_rotation) {
return p_rotation / Math_PI * 180.0;
}
Basis EulerToBasis(RotOrder mode, const Vector3 &p_rotation) {
Basis ret;
switch (mode) {
case EulerXYZ:
ret.set_euler_xyz(p_rotation);
break;
case EulerXZY:
ret.set_euler_xzy(p_rotation);
break;
case EulerYZX:
ret.set_euler_yzx(p_rotation);
break;
case EulerYXZ:
ret.set_euler_yxz(p_rotation);
break;
case EulerZXY:
ret.set_euler_zxy(p_rotation);
break;
case EulerZYX:
ret.set_euler_zyx(p_rotation);
break;
default:
// If you land here, Please integrate all rotation orders.
CRASH_NOW_MSG("This is not unreachable.");
}
return ret;
}
Vector3 BasisToEuler(RotOrder mode, const Basis &p_rotation) {
switch (mode) {
case EulerXYZ:
return p_rotation.get_euler_xyz();
case EulerXZY:
return p_rotation.get_euler_xzy();
case EulerYZX:
return p_rotation.get_euler_yzx();
case EulerYXZ:
return p_rotation.get_euler_yxz();
case EulerZXY:
return p_rotation.get_euler_zxy();
case EulerZYX:
return p_rotation.get_euler_zyx();
default:
// If you land here, Please integrate all rotation orders.
CRASH_NOW_MSG("This is not unreachable.");
return Vector3();
}
}
String get_rot_order_name(RotOrder ro) {
switch (ro) {
case EulerXYZ:
return "XYZ";
case EulerXZY:
return "XZY";
case EulerYZX:
return "YZX";
case EulerYXZ:
return "YXZ";
case EulerZXY:
return "ZXY";
case EulerZYX:
return "ZYX";
default:
return "[Not supported]";
}
}
bool test_rotation(Vector3 deg_original_euler, RotOrder rot_order) {
// This test:
// 1. Converts the rotation vector from deg to rad.
// 2. Converts euler to basis.
// 3. Converts the above basis back into euler.
// 4. Converts the above euler into basis again.
// 5. Compares the basis obtained in step 2 with the basis of step 4
//
// The conversion "basis to euler", done in the step 3, may be different from
// the original euler, even if the final rotation are the same.
// This happens because there are more ways to represents the same rotation,
// both valid, using eulers.
// For this reason is necessary to convert that euler back to basis and finally
// compares it.
//
// In this way we can assert that both functions: basis to euler / euler to basis
// are correct.
bool pass = true;
// Euler to rotation
const Vector3 original_euler = deg2rad(deg_original_euler);
const Basis to_rotation = EulerToBasis(rot_order, original_euler);
// Euler from rotation
const Vector3 euler_from_rotation = BasisToEuler(rot_order, to_rotation);
const Basis rotation_from_computed_euler = EulerToBasis(rot_order, euler_from_rotation);
Basis res = to_rotation.inverse() * rotation_from_computed_euler;
if ((res.get_axis(0) - Vector3(1.0, 0.0, 0.0)).length() > 0.1) {
OS::get_singleton()->print("Fail due to X %s\n", String(res.get_axis(0)).utf8().get_data());
pass = false;
}
if ((res.get_axis(1) - Vector3(0.0, 1.0, 0.0)).length() > 0.1) {
OS::get_singleton()->print("Fail due to Y %s\n", String(res.get_axis(1)).utf8().get_data());
pass = false;
}
if ((res.get_axis(2) - Vector3(0.0, 0.0, 1.0)).length() > 0.1) {
OS::get_singleton()->print("Fail due to Z %s\n", String(res.get_axis(2)).utf8().get_data());
pass = false;
}
if (pass) {
// Double check `to_rotation` decomposing with XYZ rotation order.
const Vector3 euler_xyz_from_rotation = to_rotation.get_euler_xyz();
Basis rotation_from_xyz_computed_euler;
rotation_from_xyz_computed_euler.set_euler_xyz(euler_xyz_from_rotation);
res = to_rotation.inverse() * rotation_from_xyz_computed_euler;
if ((res.get_axis(0) - Vector3(1.0, 0.0, 0.0)).length() > 0.1) {
OS::get_singleton()->print("Double check with XYZ rot order failed, due to X %s\n", String(res.get_axis(0)).utf8().get_data());
pass = false;
}
if ((res.get_axis(1) - Vector3(0.0, 1.0, 0.0)).length() > 0.1) {
OS::get_singleton()->print("Double check with XYZ rot order failed, due to Y %s\n", String(res.get_axis(1)).utf8().get_data());
pass = false;
}
if ((res.get_axis(2) - Vector3(0.0, 0.0, 1.0)).length() > 0.1) {
OS::get_singleton()->print("Double check with XYZ rot order failed, due to Z %s\n", String(res.get_axis(2)).utf8().get_data());
pass = false;
}
}
if (pass == false) {
// Print phase only if not pass.
OS *os = OS::get_singleton();
os->print("Rotation order: %s\n.", get_rot_order_name(rot_order).utf8().get_data());
os->print("Original Rotation: %s\n", String(deg_original_euler).utf8().get_data());
os->print("Quaternion to rotation order: %s\n", String(rad2deg(euler_from_rotation)).utf8().get_data());
}
return pass;
}
void test_euler_conversion() {
Vector<RotOrder> rotorder_to_test;
rotorder_to_test.push_back(EulerXYZ);
rotorder_to_test.push_back(EulerXZY);
rotorder_to_test.push_back(EulerYZX);
rotorder_to_test.push_back(EulerYXZ);
rotorder_to_test.push_back(EulerZXY);
rotorder_to_test.push_back(EulerZYX);
Vector<Vector3> vectors_to_test;
// Test the special cases.
vectors_to_test.push_back(Vector3(0.0, 0.0, 0.0));
vectors_to_test.push_back(Vector3(0.5, 0.5, 0.5));
vectors_to_test.push_back(Vector3(-0.5, -0.5, -0.5));
vectors_to_test.push_back(Vector3(40.0, 40.0, 40.0));
vectors_to_test.push_back(Vector3(-40.0, -40.0, -40.0));
vectors_to_test.push_back(Vector3(0.0, 0.0, -90.0));
vectors_to_test.push_back(Vector3(0.0, -90.0, 0.0));
vectors_to_test.push_back(Vector3(-90.0, 0.0, 0.0));
vectors_to_test.push_back(Vector3(0.0, 0.0, 90.0));
vectors_to_test.push_back(Vector3(0.0, 90.0, 0.0));
vectors_to_test.push_back(Vector3(90.0, 0.0, 0.0));
vectors_to_test.push_back(Vector3(0.0, 0.0, -30.0));
vectors_to_test.push_back(Vector3(0.0, -30.0, 0.0));
vectors_to_test.push_back(Vector3(-30.0, 0.0, 0.0));
vectors_to_test.push_back(Vector3(0.0, 0.0, 30.0));
vectors_to_test.push_back(Vector3(0.0, 30.0, 0.0));
vectors_to_test.push_back(Vector3(30.0, 0.0, 0.0));
vectors_to_test.push_back(Vector3(0.5, 50.0, 20.0));
vectors_to_test.push_back(Vector3(-0.5, -50.0, -20.0));
vectors_to_test.push_back(Vector3(0.5, 0.0, 90.0));
vectors_to_test.push_back(Vector3(0.5, 0.0, -90.0));
vectors_to_test.push_back(Vector3(360.0, 360.0, 360.0));
vectors_to_test.push_back(Vector3(-360.0, -360.0, -360.0));
vectors_to_test.push_back(Vector3(-90.0, 60.0, -90.0));
vectors_to_test.push_back(Vector3(90.0, 60.0, -90.0));
vectors_to_test.push_back(Vector3(90.0, -60.0, -90.0));
vectors_to_test.push_back(Vector3(-90.0, -60.0, -90.0));
vectors_to_test.push_back(Vector3(-90.0, 60.0, 90.0));
vectors_to_test.push_back(Vector3(90.0, 60.0, 90.0));
vectors_to_test.push_back(Vector3(90.0, -60.0, 90.0));
vectors_to_test.push_back(Vector3(-90.0, -60.0, 90.0));
vectors_to_test.push_back(Vector3(60.0, 90.0, -40.0));
vectors_to_test.push_back(Vector3(60.0, -90.0, -40.0));
vectors_to_test.push_back(Vector3(-60.0, -90.0, -40.0));
vectors_to_test.push_back(Vector3(-60.0, 90.0, 40.0));
vectors_to_test.push_back(Vector3(60.0, 90.0, 40.0));
vectors_to_test.push_back(Vector3(60.0, -90.0, 40.0));
vectors_to_test.push_back(Vector3(-60.0, -90.0, 40.0));
vectors_to_test.push_back(Vector3(-90.0, 90.0, -90.0));
vectors_to_test.push_back(Vector3(90.0, 90.0, -90.0));
vectors_to_test.push_back(Vector3(90.0, -90.0, -90.0));
vectors_to_test.push_back(Vector3(-90.0, -90.0, -90.0));
vectors_to_test.push_back(Vector3(-90.0, 90.0, 90.0));
vectors_to_test.push_back(Vector3(90.0, 90.0, 90.0));
vectors_to_test.push_back(Vector3(90.0, -90.0, 90.0));
vectors_to_test.push_back(Vector3(20.0, 150.0, 30.0));
vectors_to_test.push_back(Vector3(20.0, -150.0, 30.0));
vectors_to_test.push_back(Vector3(-120.0, -150.0, 30.0));
vectors_to_test.push_back(Vector3(-120.0, -150.0, -130.0));
vectors_to_test.push_back(Vector3(120.0, -150.0, -130.0));
vectors_to_test.push_back(Vector3(120.0, 150.0, -130.0));
vectors_to_test.push_back(Vector3(120.0, 150.0, 130.0));
// Add 1000 random vectors with weirds numbers.
RandomNumberGenerator rng;
for (int _ = 0; _ < 1000; _ += 1) {
vectors_to_test.push_back(Vector3(
rng.randf_range(-1800, 1800),
rng.randf_range(-1800, 1800),
rng.randf_range(-1800, 1800)));
}
bool success = true;
for (int h = 0; h < rotorder_to_test.size(); h += 1) {
int passed = 0;
int failed = 0;
for (int i = 0; i < vectors_to_test.size(); i += 1) {
if (test_rotation(vectors_to_test[i], rotorder_to_test[h])) {
//OS::get_singleton()->print("Success. \n\n");
passed += 1;
} else {
OS::get_singleton()->print("FAILED FAILED FAILED. \n\n");
OS::get_singleton()->print("------------>\n");
OS::get_singleton()->print("------------>\n");
failed += 1;
success = false;
}
}
if (failed == 0) {
OS::get_singleton()->print("%i passed tests for rotation order: %s.\n", passed, get_rot_order_name(rotorder_to_test[h]).utf8().get_data());
} else {
OS::get_singleton()->print("%i FAILED tests for rotation order: %s.\n", failed, get_rot_order_name(rotorder_to_test[h]).utf8().get_data());
}
}
if (success) {
OS::get_singleton()->print("Euler conversion checks passed.\n");
} else {
OS::get_singleton()->print("Euler conversion checks FAILED.\n");
}
}
void check_test(const char *test_case_name, bool condition) {
if (!condition) {
OS::get_singleton()->print("FAILED - %s\n", test_case_name);
} else {
OS::get_singleton()->print("PASSED - %s\n", test_case_name);
}
}
void test_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_test("Testing the singularity when the angle is 0.", 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_test("Testing the singularity when the angle is 180.", Math::is_equal_approx(angle, pi));
// Testing reversing the an axis (of an 30° angle).
float cos30deg = Math::cos(Math::deg2rad((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_test("Testing reversing the an axis (of an 30 angle).", Math::is_equal_approx(angle, Math::deg2rad((real_t)30.0)));
check_test("Testing reversing the an axis (of an 30 angle).", axis == Vector3(0, 0, 1));
z_negative.get_axis_angle(axis, angle);
check_test("Testing reversing the an axis (of an 30 angle).", Math::is_equal_approx(angle, Math::deg2rad((real_t)30.0)));
check_test("Testing reversing the an axis (of an 30 angle).", 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_test("Testing a rotation of 90 on x-y-z.", Math::is_equal_approx(angle, pi / (real_t)2));
check_test("Testing a rotation of 90 on x-y-z.", axis == Vector3(1, 0, 0));
Basis y90deg(0, 0, 1, 0, 1, 0, -1, 0, 0);
y90deg.get_axis_angle(axis, angle);
check_test("Testing a rotation of 90 on x-y-z.", axis == Vector3(0, 1, 0));
Basis z90deg(0, -1, 0, 1, 0, 0, 0, 0, 1);
z90deg.get_axis_angle(axis, angle);
check_test("Testing a rotation of 90 on x-y-z.", 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_test("Regression test: checks that the method returns a small angle (not 0).", 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_test("Regression test: checks that the method returns an angle which is a number (not NaN)", !Math::is_nan(angle));
}
MainLoop *test() {
OS::get_singleton()->print("Start euler conversion checks.\n");
test_euler_conversion();
OS::get_singleton()->print("\n---------------\n");
OS::get_singleton()->print("Start set axis angle checks.\n");
test_set_axis_angle();
return nullptr;
}
} // namespace TestBasis

View File

@ -1,39 +0,0 @@
#ifndef TEST_BASIS_H
#define TEST_BASIS_H
/*************************************************************************/
/* test_basis.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestBasis {
MainLoop *test();
}
#endif

View File

@ -1,99 +0,0 @@
/*************************************************************************/
/* test_crypto.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "core/crypto/crypto.h"
#include "core/os/os.h"
namespace TestCrypto {
class _MockCrypto : public Crypto {
virtual PoolByteArray generate_random_bytes(int p_bytes) { return PoolByteArray(); }
virtual Ref<CryptoKey> generate_rsa(int p_bytes) { return nullptr; }
virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) { return nullptr; }
virtual Vector<uint8_t> sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key) { return Vector<uint8_t>(); }
virtual bool verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key) { return false; }
virtual Vector<uint8_t> encrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_plaintext) { return Vector<uint8_t>(); }
virtual Vector<uint8_t> decrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_ciphertext) { return Vector<uint8_t>(); }
virtual PoolByteArray hmac_digest(HashingContext::HashType p_hash_type, PoolByteArray p_key, PoolByteArray p_msg) { return PoolByteArray(); }
};
PoolByteArray raw_to_pba(const uint8_t *arr, size_t len) {
PoolByteArray pba;
pba.resize(len);
for (size_t i = 0; i < len; i++) {
pba.set(i, arr[i]);
}
return pba;
}
bool test_PoolByteArray_constant_time_compare() {
const uint8_t hm1[] = { 144, 140, 176, 38, 88, 113, 101, 45, 71, 105, 10, 91, 248, 16, 117, 244, 189, 30, 238, 29, 219, 134, 82, 130, 212, 114, 161, 166, 188, 169, 200, 106 };
const uint8_t hm2[] = { 80, 30, 144, 228, 108, 38, 188, 125, 150, 64, 165, 127, 221, 118, 144, 232, 45, 100, 15, 248, 193, 244, 245, 34, 116, 147, 132, 200, 110, 27, 38, 75 };
PoolByteArray p1 = raw_to_pba(hm1, sizeof(hm1) / sizeof(hm1[0]));
PoolByteArray p2 = raw_to_pba(hm2, sizeof(hm2) / sizeof(hm2[0]));
_MockCrypto crypto;
bool equal = crypto.constant_time_compare(p1, p1);
bool ok = true;
ok = ok && equal;
equal = crypto.constant_time_compare(p1, p2);
ok = ok && !equal;
return ok;
}
typedef bool (*TestFunc)();
TestFunc test_funcs[] = {
test_PoolByteArray_constant_time_compare,
nullptr
};
MainLoop *test() {
int count = 0;
int passed = 0;
while (true) {
if (!test_funcs[count]) {
break;
}
bool pass = test_funcs[count]();
if (pass) {
passed++;
}
OS::get_singleton()->print("\t%s\n", pass ? "PASS" : "FAILED");
count++;
}
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Passed %i of %i tests\n", passed, count);
return nullptr;
}
} // namespace TestCrypto

View File

@ -1,40 +0,0 @@
#ifndef TEST_CRYPTO_H
#define TEST_CRYPTO_H
/*************************************************************************/
/* test_crypto.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestCrypto {
MainLoop *test();
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +0,0 @@
#ifndef TEST_GDSCRIPT_H
#define TEST_GDSCRIPT_H
/*************************************************************************/
/* test_gdscript.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestGDScript {
enum TestType {
TEST_TOKENIZER,
TEST_PARSER,
TEST_COMPILER,
TEST_BYTECODE,
};
MainLoop *test(TestType p_type);
} // namespace TestGDScript
#endif // TEST_GDSCRIPT_H

View File

@ -1,271 +0,0 @@
/*************************************************************************/
/* test_gui.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef _3D_DISABLED
#include "test_gui.h"
#include "core/io/image_loader.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "scene/2d/sprite.h"
#include "scene/gui/button.h"
#include "scene/main/control.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/option_button.h"
#include "scene/gui/panel.h"
#include "scene/gui/popup_menu.h"
#include "scene/gui/progress_bar.h"
#include "scene/gui/rich_text_label.h"
#include "scene/gui/scroll_bar.h"
#include "core/input/shortcut.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tree.h"
#include "scene/main/scene_tree.h"
#include "scene/3d/camera.h"
#include "scene/main/viewport.h"
namespace TestGUI {
class TestMainLoop : public SceneTree {
public:
virtual void request_quit() {
quit();
}
virtual void init() {
SceneTree::init();
Panel *frame = memnew(Panel);
frame->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END);
frame->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END);
frame->set_end(Point2(0, 0));
Ref<Theme> t = memnew(Theme);
frame->set_theme(t);
get_root()->add_child(frame);
Label *label = memnew(Label);
label->set_position(Point2(80, 90));
label->set_size(Point2(170, 80));
label->set_align(Label::ALIGN_FILL);
label->set_text("There was once upon a time a beautiful unicorn that loved to play with little girls...");
frame->add_child(label);
Button *button = memnew(Button);
button->set_position(Point2(20, 20));
button->set_size(Point2(1, 1));
button->set_text("This is a biggie button");
frame->add_child(button);
Tree *tree = memnew(Tree);
tree->set_columns(2);
tree->set_position(Point2(230, 210));
tree->set_size(Point2(150, 250));
TreeItem *item = tree->create_item();
item->set_editable(0, true);
item->set_text(0, "root");
item = tree->create_item(tree->get_root());
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
item->set_editable(0, true);
item->set_text(0, "check");
item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK);
item->set_editable(1, true);
item->set_text(1, "check2");
item = tree->create_item(tree->get_root());
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
item->set_editable(0, true);
item->set_range_config(0, 0, 20, 0.1);
item->set_range(0, 2);
item->add_button(0, Theme::get_default()->get_icon("folder", "FileDialog"));
item->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
item->set_editable(1, true);
item->set_range_config(1, 0, 20, 0.1);
item->set_range(1, 3);
item = tree->create_item(tree->get_root());
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
item->set_editable(0, true);
item->set_text(0, "Have,Many,Several,Options!");
item->set_range(0, 2);
item = tree->create_item(item);
item->set_editable(0, true);
item->set_text(0, "Gershwin!");
frame->add_child(tree);
LineEdit *line_edit = memnew(LineEdit);
line_edit->set_position(Point2(30, 190));
line_edit->set_size(Point2(180, 1));
frame->add_child(line_edit);
HScrollBar *hscroll = memnew(HScrollBar);
hscroll->set_position(Point2(30, 290));
hscroll->set_size(Point2(180, 1));
hscroll->set_max(10);
hscroll->set_page(4);
frame->add_child(hscroll);
SpinBox *spin = memnew(SpinBox);
spin->set_position(Point2(30, 260));
spin->set_size(Point2(120, 1));
frame->add_child(spin);
hscroll->share(spin);
ProgressBar *progress = memnew(ProgressBar);
progress->set_position(Point2(30, 330));
progress->set_size(Point2(120, 1));
frame->add_child(progress);
hscroll->share(progress);
MenuButton *menu_button = memnew(MenuButton);
menu_button->set_text("I'm a menu!");
menu_button->set_position(Point2(30, 380));
menu_button->set_size(Point2(1, 1));
frame->add_child(menu_button);
PopupMenu *popup = menu_button->get_popup();
popup->add_item("Hello, testing");
popup->add_item("My Dearest");
popup->add_separator();
popup->add_item("Popup");
popup->add_check_item("Check Popup");
popup->set_item_checked(4, true);
popup->add_separator();
popup->add_radio_check_item("Option A");
popup->set_item_checked(6, true);
popup->add_radio_check_item("Option B");
OptionButton *options = memnew(OptionButton);
options->add_item("Hello, testing");
options->add_item("My Dearest");
options->set_position(Point2(230, 180));
options->set_size(Point2(1, 1));
frame->add_child(options);
RichTextLabel *richtext = memnew(RichTextLabel);
richtext->set_position(Point2(600, 210));
richtext->set_size(Point2(180, 250));
richtext->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -20);
frame->add_child(richtext);
richtext->add_text("Hello, My Friends!\n\nWelcome to the amazing world of ");
richtext->add_newline();
richtext->add_newline();
richtext->push_color(Color(1, 0.5, 0.5));
richtext->add_text("leprechauns");
richtext->pop();
richtext->add_text(" and ");
richtext->push_color(Color(0, 1.0, 0.5));
richtext->add_text("faeries.\n");
richtext->pop();
richtext->add_text("In this new episode, we will attempt to ");
richtext->push_font(richtext->get_theme_font("mono_font", "Fonts"));
richtext->push_color(Color(0.7, 0.5, 1.0));
richtext->add_text("deliver something nice");
richtext->pop();
richtext->pop();
richtext->add_text(" to all the viewers! Unfortunately, I need to ");
richtext->push_underline();
richtext->add_text("keep writing a lot of text");
richtext->pop();
richtext->add_text(" so the label control overflows and the scrollbar appears.\n");
richtext->push_meta("http://www.scrollingcapabilities.xz");
richtext->add_text("This allows to test for the scrolling capabilities ");
richtext->pop();
richtext->add_text("of the rich text label for huge text (not like this text will really be huge but, you know).\nAs long as it is so long that it will work nicely for a test/demo, then it's welcomed in my book...\nChanging subject, the day is cloudy today and I'm wondering if I'll get che chance to travel somewhere nice. Sometimes, watching the clouds from satellite images may give a nice insight about how pressure zones in our planet work, although it also makes it pretty obvious to see why most weather forecasts get it wrong so often.\nClouds are so difficult to predict!\nBut it's pretty cool how our civilization has adapted to having water falling from the sky each time it rains...");
TabContainer *tabc = memnew(TabContainer);
Control *ctl = memnew(Control);
ctl->set_name("tab 1");
tabc->add_child(ctl);
ctl = memnew(Control);
ctl->set_name("tab 2");
tabc->add_child(ctl);
label = memnew(Label);
label->set_text("Some Label");
label->set_position(Point2(20, 20));
ctl->add_child(label);
ctl = memnew(Control);
ctl->set_name("tab 3");
button = memnew(Button);
button->set_text("Some Button");
button->set_position(Point2(30, 50));
ctl->add_child(button);
tabc->add_child(ctl);
frame->add_child(tabc);
tabc->set_position(Point2(400, 210));
tabc->set_size(Point2(180, 250));
}
};
MainLoop *test() {
return memnew(TestMainLoop);
}
} // namespace TestGUI
#endif

View File

@ -1,40 +0,0 @@
#ifndef TEST_GUI_H
#define TEST_GUI_H
/*************************************************************************/
/* test_gui.h */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestGUI {
MainLoop *test();
}
#endif

View File

@ -1,177 +0,0 @@
/*************************************************************************/
/* test_main.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_main.h"
#include "core/containers/list.h"
#ifdef DEBUG_ENABLED
#include "test_astar.h"
#include "test_basis.h"
#include "test_crypto.h"
#include "test_gdscript.h"
#include "test_gui.h"
#include "test_math.h"
#include "test_oa_hash_map.h"
#include "test_ordered_hash_map.h"
#include "test_physics.h"
#include "test_physics_2d.h"
#include "test_render.h"
#include "test_shader_lang.h"
#include "test_string.h"
#include "test_theme.h"
#include "test_transform.h"
#include "test_xml_parser.h"
const char **tests_get_names() {
static const char *test_names[] = {
//"string",
"math",
"basis",
"transform",
"physics",
"physics_2d",
"render",
"oa_hash_map",
"gui",
"shaderlang",
"gd_tokenizer",
"gd_parser",
"gd_compiler",
"gd_bytecode",
"ordered_hash_map",
"astar",
"xml_parser",
"theme",
nullptr
};
return test_names;
}
MainLoop *test_main(String p_test, const List<String> &p_args) {
//if (p_test == "string") {
// return TestString::test();
//}
if (p_test == "math") {
return TestMath::test();
}
if (p_test == "basis") {
return TestBasis::test();
}
if (p_test == "transform") {
return TestTransform::test();
}
if (p_test == "physics") {
return TestPhysics::test();
}
if (p_test == "physics_2d") {
return TestPhysics2D::test();
}
if (p_test == "render") {
return TestRender::test();
}
if (p_test == "oa_hash_map") {
return TestOAHashMap::test();
}
#ifndef _3D_DISABLED
if (p_test == "gui") {
return TestGUI::test();
}
#endif
if (p_test == "shaderlang") {
return TestShaderLang::test();
}
if (p_test == "crypto") {
return TestCrypto::test();
}
if (p_test == "gd_tokenizer") {
return TestGDScript::test(TestGDScript::TEST_TOKENIZER);
}
if (p_test == "gd_parser") {
return TestGDScript::test(TestGDScript::TEST_PARSER);
}
if (p_test == "gd_compiler") {
return TestGDScript::test(TestGDScript::TEST_COMPILER);
}
if (p_test == "gd_bytecode") {
return TestGDScript::test(TestGDScript::TEST_BYTECODE);
}
if (p_test == "ordered_hash_map") {
return TestOrderedHashMap::test();
}
if (p_test == "astar") {
return TestAStar::test();
}
if (p_test == "xml_parser") {
return TestXMLParser::test();
}
if (p_test == "theme") {
return TestTheme::test();
}
print_line("Unknown test: " + p_test);
return nullptr;
}
#else
const char **tests_get_names() {
static const char *test_names[] = {
NULL
};
return test_names;
}
MainLoop *test_main(String p_test, const List<String> &p_args) {
return NULL;
}
#endif

View File

@ -1,40 +0,0 @@
#ifndef TEST_MAIN_H
#define TEST_MAIN_H
/*************************************************************************/
/* test_main.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. */
/*************************************************************************/
#include "core/containers/list.h"
#include "core/os/main_loop.h"
#include "core/string/ustring.h"
const char **tests_get_names();
MainLoop *test_main(String p_test, const List<String> &p_args);
#endif // TEST_MAIN_H

View File

@ -1,660 +0,0 @@
/*************************************************************************/
/* test_math.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_math.h"
#include "core/math/basis.h"
#include "core/math/projection.h"
#include "core/math/math_funcs.h"
#include "core/math/transform.h"
#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "core/string/ustring.h"
#include "core/variant/variant.h"
#include "core/containers/vmap.h"
#include "scene/main/node.h"
#include "scene/resources/texture.h"
#include "servers/rendering/shader_language.h"
#include "core/variant/method_ptrcall.h"
namespace TestMath {
class GetClassAndNamespace {
String code;
int idx;
int line;
String error_str;
bool error;
Variant value;
String class_name;
enum Token {
TK_BRACKET_OPEN,
TK_BRACKET_CLOSE,
TK_CURLY_BRACKET_OPEN,
TK_CURLY_BRACKET_CLOSE,
TK_PERIOD,
TK_COLON,
TK_COMMA,
TK_SYMBOL,
TK_IDENTIFIER,
TK_STRING,
TK_NUMBER,
TK_EOF,
TK_ERROR
};
Token get_token() {
while (true) {
switch (code[idx]) {
case '\n': {
line++;
idx++;
break;
};
case 0: {
return TK_EOF;
} break;
case '{': {
idx++;
return TK_CURLY_BRACKET_OPEN;
};
case '}': {
idx++;
return TK_CURLY_BRACKET_CLOSE;
};
case '[': {
idx++;
return TK_BRACKET_OPEN;
};
case ']': {
idx++;
return TK_BRACKET_CLOSE;
};
case ':': {
idx++;
return TK_COLON;
};
case ',': {
idx++;
return TK_COMMA;
};
case '.': {
idx++;
return TK_PERIOD;
};
case '#': {
//compiler directive
while (code[idx] != '\n' && code[idx] != 0) {
idx++;
}
continue;
} break;
case '/': {
switch (code[idx + 1]) {
case '*': { // block comment
idx += 2;
while (true) {
if (code[idx] == 0) {
error_str = "Unterminated comment";
error = true;
return TK_ERROR;
} else if (code[idx] == '*' && code[idx + 1] == '/') {
idx += 2;
break;
} else if (code[idx] == '\n') {
line++;
}
idx++;
}
} break;
case '/': { // line comment skip
while (code[idx] != '\n' && code[idx] != 0) {
idx++;
}
} break;
default: {
value = "/";
idx++;
return TK_SYMBOL;
}
}
continue; // a comment
} break;
case '\'':
case '"': {
CharType begin_str = code[idx];
idx++;
String tk_string = String();
while (true) {
if (code[idx] == 0) {
error_str = "Unterminated String";
error = true;
return TK_ERROR;
} else if (code[idx] == begin_str) {
idx++;
break;
} else if (code[idx] == '\\') {
//escaped characters...
idx++;
CharType next = code[idx];
if (next == 0) {
error_str = "Unterminated String";
error = true;
return TK_ERROR;
}
CharType res = 0;
switch (next) {
case 'b':
res = 8;
break;
case 't':
res = 9;
break;
case 'n':
res = 10;
break;
case 'f':
res = 12;
break;
case 'r':
res = 13;
break;
case '\"':
res = '\"';
break;
case '\\':
res = '\\';
break;
default: {
res = next;
} break;
}
tk_string += res;
} else {
if (code[idx] == '\n') {
line++;
}
tk_string += code[idx];
}
idx++;
}
value = tk_string;
return TK_STRING;
} break;
default: {
if (code[idx] <= 32) {
idx++;
break;
}
if ((code[idx] >= 33 && code[idx] <= 47) || (code[idx] >= 58 && code[idx] <= 64) || (code[idx] >= 91 && code[idx] <= 96) || (code[idx] >= 123 && code[idx] <= 127)) {
value = String::chr(code[idx]);
idx++;
return TK_SYMBOL;
}
if (code[idx] == '-' || (code[idx] >= '0' && code[idx] <= '9')) {
//a number
const CharType *rptr;
double number = String::to_double(&code[idx], &rptr);
idx += (rptr - &code[idx]);
value = number;
return TK_NUMBER;
} else if ((code[idx] >= 'A' && code[idx] <= 'Z') || (code[idx] >= 'a' && code[idx] <= 'z') || code[idx] > 127) {
String id;
while ((code[idx] >= 'A' && code[idx] <= 'Z') || (code[idx] >= 'a' && code[idx] <= 'z') || code[idx] > 127) {
id += code[idx];
idx++;
}
value = id;
return TK_IDENTIFIER;
} else {
error_str = "Unexpected character.";
error = true;
return TK_ERROR;
}
}
}
}
}
public:
Error parse(const String &p_code, const String &p_known_class_name = String()) {
code = p_code;
idx = 0;
line = 0;
error_str = String();
error = false;
value = Variant();
class_name = String();
bool use_next_class = false;
Token tk = get_token();
RBMap<int, String> namespace_stack;
int curly_stack = 0;
while (!error || tk != TK_EOF) {
if (tk == TK_BRACKET_OPEN) {
tk = get_token();
if (tk == TK_IDENTIFIER && String(value) == "ScriptClass") {
if (get_token() == TK_BRACKET_CLOSE) {
use_next_class = true;
}
}
} else if (tk == TK_IDENTIFIER && String(value) == "class") {
tk = get_token();
if (tk == TK_IDENTIFIER) {
String name = value;
if (use_next_class || p_known_class_name == name) {
for (RBMap<int, String>::Element *E = namespace_stack.front(); E; E = E->next()) {
class_name += E->get() + ".";
}
class_name += String(value);
break;
}
}
} else if (tk == TK_IDENTIFIER && String(value) == "namespace") {
String name;
int at_level = curly_stack;
while (true) {
tk = get_token();
if (tk == TK_IDENTIFIER) {
name += String(value);
}
tk = get_token();
if (tk == TK_PERIOD) {
name += ".";
} else if (tk == TK_CURLY_BRACKET_OPEN) {
curly_stack++;
break;
} else {
break; //whatever else
}
}
if (name != String()) {
namespace_stack[at_level] = name;
}
} else if (tk == TK_CURLY_BRACKET_OPEN) {
curly_stack++;
} else if (tk == TK_CURLY_BRACKET_CLOSE) {
curly_stack--;
if (namespace_stack.has(curly_stack)) {
namespace_stack.erase(curly_stack);
}
}
tk = get_token();
}
if (error) {
return ERR_PARSE_ERROR;
}
return OK;
}
String get_error() {
return error_str;
}
String get_class() {
return class_name;
}
};
void test_vec(Plane p_vec) {
Projection cm;
cm.set_perspective(45, 1, 0, 100);
Plane v0 = cm.xform(p_vec);
print_line("out: " + v0);
v0.normal.z = (v0.d / 100.0 * 2.0 - 1.0) * v0.d;
print_line("out_F: " + v0);
}
uint32_t ihash(uint32_t a) {
a = (a + 0x7ed55d16) + (a << 12);
a = (a ^ 0xc761c23c) ^ (a >> 19);
a = (a + 0x165667b1) + (a << 5);
a = (a + 0xd3a2646c) ^ (a << 9);
a = (a + 0xfd7046c5) + (a << 3);
a = (a ^ 0xb55a4f09) ^ (a >> 16);
return a;
}
uint32_t ihash2(uint32_t a) {
a = (a ^ 61) ^ (a >> 16);
a = a + (a << 3);
a = a ^ (a >> 4);
a = a * 0x27d4eb2d;
a = a ^ (a >> 15);
return a;
}
uint32_t ihash3(uint32_t a) {
a = (a + 0x479ab41d) + (a << 8);
a = (a ^ 0xe4aa10ce) ^ (a >> 5);
a = (a + 0x9942f0a6) - (a << 14);
a = (a ^ 0x5aedd67d) ^ (a >> 3);
a = (a + 0x17bea992) + (a << 7);
return a;
}
MainLoop *test() {
{
float r = 1;
float g = 0.5;
float b = 0.1;
const float pow2to9 = 512.0f;
const float B = 15.0f;
const float N = 9.0f;
float sharedexp = 65408.000f;
float cRed = MAX(0.0f, MIN(sharedexp, r));
float cGreen = MAX(0.0f, MIN(sharedexp, g));
float cBlue = MAX(0.0f, MIN(sharedexp, b));
float cMax = MAX(cRed, MAX(cGreen, cBlue));
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
float exps = expp + 1.0f;
if (0.0 <= sMax && sMax < pow2to9) {
exps = expp;
}
float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
print_line("R: " + rtos(sRed) + " G: " + rtos(sGreen) + " B: " + rtos(sBlue) + " EXP: " + rtos(exps));
uint32_t rgbe = (Math::fast_ftoi(sRed) & 0x1FF) | ((Math::fast_ftoi(sGreen) & 0x1FF) << 9) | ((Math::fast_ftoi(sBlue) & 0x1FF) << 18) | ((Math::fast_ftoi(exps) & 0x1F) << 27);
float rb = rgbe & 0x1ff;
float gb = (rgbe >> 9) & 0x1ff;
float bb = (rgbe >> 18) & 0x1ff;
float eb = (rgbe >> 27);
float mb = Math::pow(2, eb - 15.0 - 9.0);
float rd = rb * mb;
float gd = gb * mb;
float bd = bb * mb;
print_line("RGBE: " + Color(rd, gd, bd));
}
print_line("Dvectors: " + itos(MemoryPool::allocs_used));
print_line("Mem used: " + itos(MemoryPool::total_memory));
print_line("MAx mem used: " + itos(MemoryPool::max_memory));
PoolVector<int> ints;
ints.resize(20);
{
PoolVector<int>::Write w;
w = ints.write();
for (int i = 0; i < ints.size(); i++) {
w[i] = i;
}
}
PoolVector<int> posho = ints;
{
PoolVector<int>::Read r = posho.read();
for (int i = 0; i < posho.size(); i++) {
print_line(itos(i) + " : " + itos(r[i]));
}
}
print_line("later Dvectors: " + itos(MemoryPool::allocs_used));
print_line("later Mem used: " + itos(MemoryPool::total_memory));
print_line("Mlater Ax mem used: " + itos(MemoryPool::max_memory));
List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
if (cmdlargs.empty()) {
//try editor!
return nullptr;
}
String test = cmdlargs.back()->get();
if (test == "math") {
// Not a file name but the test name, abort.
// FIXME: This test is ugly as heck, needs fixing :)
return nullptr;
}
FileAccess *fa = FileAccess::open(test, FileAccess::READ);
ERR_FAIL_COND_V_MSG(!fa, nullptr, "Could not open file: " + test);
Vector<uint8_t> buf;
uint64_t flen = fa->get_len();
buf.resize(fa->get_len() + 1);
fa->get_buffer(buf.ptrw(), flen);
buf.write[flen] = 0;
String code;
code.parse_utf8((const char *)&buf[0]);
GetClassAndNamespace getclass;
if (getclass.parse(code)) {
print_line("Parse error: " + getclass.get_error());
} else {
print_line("Found class: " + getclass.get_class());
}
{
Vector<int> hashes;
List<StringName> tl;
ClassDB::get_class_list(&tl);
for (List<StringName>::Element *E = tl.front(); E; E = E->next()) {
Vector<uint8_t> m5b = E->get().operator String().md5_buffer();
hashes.push_back(hashes.size());
}
for (int i = nearest_shift(hashes.size()); i < 20; i++) {
bool success = true;
for (int s = 0; s < 10000; s++) {
RBSet<uint32_t> existing;
success = true;
for (int j = 0; j < hashes.size(); j++) {
uint32_t eh = ihash2(ihash3(hashes[j] + ihash(s) + s)) & ((1 << i) - 1);
if (existing.has(eh)) {
success = false;
break;
}
existing.insert(eh);
}
if (success) {
print_line("success at " + itos(i) + "/" + itos(nearest_shift(hashes.size())) + " shift " + itos(s));
break;
}
}
if (success) {
break;
}
}
print_line("DONE");
}
{
print_line("NUM: " + itos(-128));
}
{
Vector3 v(1, 2, 3);
v.normalize();
float a = 0.3;
Basis m(v, a);
Vector3 v2(7, 3, 1);
v2.normalize();
float a2 = 0.8;
Basis m2(v2, a2);
Quaternion q = m;
Quaternion q2 = m2;
Basis m3 = m.inverse() * m2;
Quaternion q3 = (q.inverse() * q2); //.normalized();
print_line(Quaternion(m3));
print_line(q3);
print_line("before v: " + v + " a: " + rtos(a));
q.get_axis_angle(v, a);
print_line("after v: " + v + " a: " + rtos(a));
}
String ret;
List<String> args;
args.push_back("-l");
Error err = OS::get_singleton()->execute("/bin/ls", args, true, nullptr, &ret);
print_line("error: " + itos(err));
print_line(ret);
Basis m3;
m3.rotate(Vector3(1, 0, 0), 0.2);
m3.rotate(Vector3(0, 1, 0), 1.77);
m3.rotate(Vector3(0, 0, 1), 212);
Basis m32;
m32.set_euler(m3.get_euler());
print_line("ELEULEEEEEEEEEEEEEEEEEER: " + m3.get_euler() + " vs " + m32.get_euler());
{
Dictionary d;
d["momo"] = 1;
Dictionary b = d;
b["44"] = 4;
}
print_line("inters: " + rtos(Geometry::segment_intersects_circle(Vector2(-5, 0), Vector2(-2, 0), Vector2(), 1.0)));
print_line("cross: " + Vector3(1, 2, 3).cross(Vector3(4, 5, 7)));
print_line("dot: " + rtos(Vector3(1, 2, 3).dot(Vector3(4, 5, 7))));
print_line("abs: " + Vector3(-1, 2, -3).abs());
print_line("distance_to: " + rtos(Vector3(1, 2, 3).distance_to(Vector3(4, 5, 7))));
print_line("distance_squared_to: " + rtos(Vector3(1, 2, 3).distance_squared_to(Vector3(4, 5, 7))));
print_line("plus: " + (Vector3(1, 2, 3) + Vector3(Vector3(4, 5, 7))));
print_line("minus: " + (Vector3(1, 2, 3) - Vector3(Vector3(4, 5, 7))));
print_line("mul: " + (Vector3(1, 2, 3) * Vector3(Vector3(4, 5, 7))));
print_line("div: " + (Vector3(1, 2, 3) / Vector3(Vector3(4, 5, 7))));
print_line("mul scalar: " + (Vector3(1, 2, 3) * 2));
print_line("premul scalar: " + (2 * Vector3(1, 2, 3)));
print_line("div scalar: " + (Vector3(1, 2, 3) / 3.0));
print_line("length: " + rtos(Vector3(1, 2, 3).length()));
print_line("length squared: " + rtos(Vector3(1, 2, 3).length_squared()));
print_line("normalized: " + Vector3(1, 2, 3).normalized());
print_line("inverse: " + Vector3(1, 2, 3).inverse());
{
Vector3 v(4, 5, 7);
v.normalize();
print_line("normalize: " + v);
}
{
Vector3 v(4, 5, 7);
v += Vector3(1, 2, 3);
print_line("+=: " + v);
}
{
Vector3 v(4, 5, 7);
v -= Vector3(1, 2, 3);
print_line("-=: " + v);
}
{
Vector3 v(4, 5, 7);
v *= Vector3(1, 2, 3);
print_line("*=: " + v);
}
{
Vector3 v(4, 5, 7);
v /= Vector3(1, 2, 3);
print_line("/=: " + v);
}
{
Vector3 v(4, 5, 7);
v *= 2.0;
print_line("scalar *=: " + v);
}
{
Vector3 v(4, 5, 7);
v /= 2.0;
print_line("scalar /=: " + v);
}
return nullptr;
}
} // namespace TestMath

View File

@ -1,40 +0,0 @@
#ifndef TEST_MATH_H
#define TEST_MATH_H
/*************************************************************************/
/* test_math.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestMath {
MainLoop *test();
}
#endif

View File

@ -1,219 +0,0 @@
/*************************************************************************/
/* test_oa_hash_map.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_oa_hash_map.h"
#include "core/containers/oa_hash_map.h"
#include "core/os/os.h"
namespace TestOAHashMap {
struct CountedItem {
static int count;
int id;
bool destroyed;
CountedItem() :
id(-1),
destroyed(false) {
count++;
}
CountedItem(int p_id) :
id(p_id),
destroyed(false) {
count++;
}
CountedItem(const CountedItem &p_other) :
id(p_other.id),
destroyed(false) {
count++;
}
CountedItem &operator=(const CountedItem &p_other) = default;
~CountedItem() {
CRASH_COND(destroyed);
count--;
destroyed = true;
}
};
int CountedItem::count;
MainLoop *test() {
OS::get_singleton()->print("\n\n\nHello from test\n");
// test element tracking.
{
OAHashMap<int, int> map;
map.set(42, 1337);
map.set(1337, 21);
map.set(42, 11880);
int value = 0;
map.lookup(42, value);
OS::get_singleton()->print("capacity %d\n", map.get_capacity());
OS::get_singleton()->print("elements %d\n", map.get_num_elements());
OS::get_singleton()->print("map[42] = %d\n", value);
}
// rehashing and deletion
{
OAHashMap<int, int> map;
for (int i = 0; i < 500; i++) {
map.set(i, i * 2);
}
for (int i = 0; i < 500; i += 2) {
map.remove(i);
}
uint32_t num_elems = 0;
for (int i = 0; i < 500; i++) {
int tmp;
if (map.lookup(i, tmp) && tmp == i * 2) {
num_elems++;
}
}
OS::get_singleton()->print("elements %d == %d.\n", map.get_num_elements(), num_elems);
}
// iteration
{
OAHashMap<String, int> map;
map.set("Hello", 1);
map.set("World3D", 2);
map.set("Pandemonium rocks", 42);
for (OAHashMap<String, int>::Iterator it = map.iter(); it.valid; it = map.next_iter(it)) {
OS::get_singleton()->print("map[\"%s\"] = %d\n", it.key->utf8().get_data(), *it.value);
}
}
// stress test / test for issue #22928
{
OAHashMap<int, int> map;
int dummy = 0;
const int N = 1000;
uint32_t *keys = new uint32_t[N];
Math::seed(0);
// insert a couple of random keys (with a dummy value, which is ignored)
for (int i = 0; i < N; i++) {
keys[i] = Math::rand();
map.set(keys[i], dummy);
if (!map.lookup(keys[i], dummy)) {
OS::get_singleton()->print("could not find 0x%X despite it was just inserted!\n", unsigned(keys[i]));
}
}
// check whether the keys are still present
for (int i = 0; i < N; i++) {
if (!map.lookup(keys[i], dummy)) {
OS::get_singleton()->print("could not find 0x%X despite it has been inserted previously! (not checking the other keys, breaking...)\n", unsigned(keys[i]));
break;
}
}
delete[] keys;
}
// regression test / test for issue related to #31402
{
OS::get_singleton()->print("test for issue #31402 started...\n");
const int num_test_values = 12;
int test_values[num_test_values] = { 0, 24, 48, 72, 96, 120, 144, 168, 192, 216, 240, 264 };
int dummy = 0;
OAHashMap<int, int> map;
map.clear();
for (int i = 0; i < num_test_values; ++i) {
map.set(test_values[i], dummy);
}
OS::get_singleton()->print("test for issue #31402 passed.\n");
}
// test collision resolution, should not crash or run indefinitely
{
OAHashMap<int, int> map(4);
map.set(1, 1);
map.set(5, 1);
map.set(9, 1);
map.set(13, 1);
map.remove(5);
map.remove(9);
map.remove(13);
map.set(5, 1);
}
// test memory management of items, should not crash or leak items
{
// Exercise different patterns of removal
for (int i = 0; i < 4; ++i) {
{
OAHashMap<String, CountedItem> map;
int id = 0;
for (int j = 0; j < 100; ++j) {
map.insert(itos(j), CountedItem(id));
}
if (i <= 1) {
for (int j = 0; j < 100; ++j) {
map.remove(itos(j));
}
}
if (i % 2 == 0) {
map.clear();
}
}
if (CountedItem::count != 0) {
OS::get_singleton()->print("%d != 0 (not performing the other test sub-cases, breaking...)\n", CountedItem::count);
break;
}
}
}
return nullptr;
}
} // namespace TestOAHashMap

View File

@ -1,40 +0,0 @@
#ifndef TEST_OA_HASH_MAP_H
#define TEST_OA_HASH_MAP_H
/*************************************************************************/
/* test_oa_hash_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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestOAHashMap {
MainLoop *test();
}
#endif // TEST_OA_HASH_MAP_H

View File

@ -1,174 +0,0 @@
/*************************************************************************/
/* test_ordered_hash_map.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_ordered_hash_map.h"
#include "core/containers/ordered_hash_map.h"
#include "core/os/os.h"
#include "core/containers/pair.h"
#include "core/containers/vector.h"
namespace TestOrderedHashMap {
bool test_insert() {
OrderedHashMap<int, int> map;
OrderedHashMap<int, int>::Element e = map.insert(42, 84);
return e && e.key() == 42 && e.get() == 84 && e.value() == 84 && map[42] == 84 && map.has(42) && map.find(42);
}
bool test_insert_overwrite() {
OrderedHashMap<int, int> map;
map.insert(42, 84);
map.insert(42, 1234);
return map[42] == 1234;
}
bool test_erase_via_element() {
OrderedHashMap<int, int> map;
OrderedHashMap<int, int>::Element e = map.insert(42, 84);
map.erase(e);
return !e && !map.has(42) && !map.find(42);
}
bool test_erase_via_key() {
OrderedHashMap<int, int> map;
map.insert(42, 84);
map.erase(42);
return !map.has(42) && !map.find(42);
}
bool test_size() {
OrderedHashMap<int, int> map;
map.insert(42, 84);
map.insert(123, 84);
map.insert(123, 84);
map.insert(0, 84);
map.insert(123485, 84);
return map.size() == 4;
}
bool test_iteration() {
OrderedHashMap<int, int> map;
map.insert(42, 84);
map.insert(123, 12385);
map.insert(0, 12934);
map.insert(123485, 1238888);
map.insert(123, 111111);
Vector<Pair<int, int>> expected;
expected.push_back(Pair<int, int>(42, 84));
expected.push_back(Pair<int, int>(123, 111111));
expected.push_back(Pair<int, int>(0, 12934));
expected.push_back(Pair<int, int>(123485, 1238888));
int idx = 0;
for (OrderedHashMap<int, int>::Element E = map.front(); E; E = E.next()) {
if (expected[idx] != Pair<int, int>(E.key(), E.value())) {
return false;
}
++idx;
}
return true;
}
bool test_const_iteration(const OrderedHashMap<int, int> &map) {
Vector<Pair<int, int>> expected;
expected.push_back(Pair<int, int>(42, 84));
expected.push_back(Pair<int, int>(123, 111111));
expected.push_back(Pair<int, int>(0, 12934));
expected.push_back(Pair<int, int>(123485, 1238888));
int idx = 0;
for (OrderedHashMap<int, int>::ConstElement E = map.front(); E; E = E.next()) {
if (expected[idx] != Pair<int, int>(E.key(), E.value())) {
return false;
}
++idx;
}
return true;
}
bool test_const_iteration() {
OrderedHashMap<int, int> map;
map.insert(42, 84);
map.insert(123, 12385);
map.insert(0, 12934);
map.insert(123485, 1238888);
map.insert(123, 111111);
return test_const_iteration(map);
}
typedef bool (*TestFunc)();
TestFunc test_funcs[] = {
test_insert,
test_insert_overwrite,
test_erase_via_element,
test_erase_via_key,
test_size,
test_iteration,
test_const_iteration,
nullptr
};
MainLoop *test() {
int count = 0;
int passed = 0;
while (true) {
if (!test_funcs[count]) {
break;
}
bool pass = test_funcs[count]();
if (pass) {
passed++;
}
OS::get_singleton()->print("\t%s\n", pass ? "PASS" : "FAILED");
count++;
}
OS::get_singleton()->print("\n\n\n");
OS::get_singleton()->print("*************\n");
OS::get_singleton()->print("***TOTALS!***\n");
OS::get_singleton()->print("*************\n");
OS::get_singleton()->print("Passed %i of %i tests\n", passed, count);
return nullptr;
}
} // namespace TestOrderedHashMap

View File

@ -1,40 +0,0 @@
#ifndef TEST_ORDERED_HASH_MAP_H
#define TEST_ORDERED_HASH_MAP_H
/*************************************************************************/
/* test_ordered_hash_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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestOrderedHashMap {
MainLoop *test();
}
#endif // TEST_ORDERED_HASH_MAP_H

View File

@ -1,411 +0,0 @@
/*************************************************************************/
/* test_physics.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_physics.h"
#include "core/containers/rb_map.h"
#include "core/math/convex_hull.h"
#include "core/math/math_funcs.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "servers/physics_server.h"
#include "servers/rendering_server.h"
class TestPhysicsMainLoop : public MainLoop {
GDCLASS(TestPhysicsMainLoop, MainLoop);
enum {
LINK_COUNT = 20,
};
RID test_cube;
RID plane;
RID sphere;
RID light;
RID camera;
RID mover;
RID scenario;
RID space;
RID character;
float ofs_x, ofs_y;
Point2 joy_direction;
List<RID> bodies;
RBMap<PhysicsServer::ShapeType, RID> type_shape_map;
RBMap<PhysicsServer::ShapeType, RID> type_mesh_map;
void body_changed_transform(Object *p_state, RID p_visual_instance) {
PhysicsDirectBodyState *state = (PhysicsDirectBodyState *)p_state;
RenderingServer *vs = RenderingServer::get_singleton();
Transform t = state->get_transform();
vs->instance_set_transform(p_visual_instance, t);
}
bool quit;
protected:
static void _bind_methods() {
ClassDB::bind_method("body_changed_transform", &TestPhysicsMainLoop::body_changed_transform);
}
RID create_body(PhysicsServer::ShapeType p_shape, PhysicsServer::BodyMode p_body, const Transform p_location, bool p_active_default = true, const Transform &p_shape_xform = Transform()) {
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer *ps = PhysicsServer::get_singleton();
RID mesh_instance = vs->instance_create2(type_mesh_map[p_shape], scenario);
RID body = RID_PRIME(ps->body_create(p_body, !p_active_default));
ps->body_set_space(body, space);
ps->body_set_param(body, PhysicsServer::BODY_PARAM_BOUNCE, 0.0);
//todo set space
ps->body_add_shape(body, type_shape_map[p_shape]);
ps->body_set_force_integration_callback(body, this, "body_changed_transform", mesh_instance);
ps->body_set_state(body, PhysicsServer::BODY_STATE_TRANSFORM, p_location);
bodies.push_back(body);
if (p_body == PhysicsServer::BODY_MODE_STATIC) {
vs->instance_set_transform(mesh_instance, p_location);
}
return body;
}
RID create_static_plane(const Plane &p_plane) {
PhysicsServer *ps = PhysicsServer::get_singleton();
RID plane_shape = ps->shape_create(PhysicsServer::SHAPE_PLANE);
ps->shape_set_data(plane_shape, p_plane);
RID b = RID_PRIME(ps->body_create(PhysicsServer::BODY_MODE_STATIC));
ps->body_set_space(b, space);
//todo set space
ps->body_add_shape(b, plane_shape);
return b;
}
void configure_body(RID p_body, float p_mass, float p_friction, float p_bounce) {
PhysicsServer *ps = PhysicsServer::get_singleton();
ps->body_set_param(p_body, PhysicsServer::BODY_PARAM_MASS, p_mass);
ps->body_set_param(p_body, PhysicsServer::BODY_PARAM_FRICTION, p_friction);
ps->body_set_param(p_body, PhysicsServer::BODY_PARAM_BOUNCE, p_bounce);
}
void init_shapes() {
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer *ps = PhysicsServer::get_singleton();
/* SPHERE SHAPE */
RID sphere_mesh = vs->make_sphere_mesh(10, 20, 0.5);
type_mesh_map[PhysicsServer::SHAPE_SPHERE] = sphere_mesh;
RID sphere_shape = ps->shape_create(PhysicsServer::SHAPE_SPHERE);
ps->shape_set_data(sphere_shape, 0.5);
type_shape_map[PhysicsServer::SHAPE_SPHERE] = sphere_shape;
/* BOX SHAPE */
PoolVector<Plane> box_planes = Geometry::build_box_planes(Vector3(0.5, 0.5, 0.5));
RID box_mesh = RID_PRIME(vs->mesh_create());
Geometry::MeshData box_data = Geometry::build_convex_mesh(box_planes);
vs->mesh_add_surface_from_mesh_data(box_mesh, box_data);
type_mesh_map[PhysicsServer::SHAPE_BOX] = box_mesh;
RID box_shape = ps->shape_create(PhysicsServer::SHAPE_BOX);
ps->shape_set_data(box_shape, Vector3(0.5, 0.5, 0.5));
type_shape_map[PhysicsServer::SHAPE_BOX] = box_shape;
/* CAPSULE SHAPE */
PoolVector<Plane> capsule_planes = Geometry::build_capsule_planes(0.5, 0.7, 12, Vector3::AXIS_Z);
RID capsule_mesh = RID_PRIME(vs->mesh_create());
Geometry::MeshData capsule_data = Geometry::build_convex_mesh(capsule_planes);
vs->mesh_add_surface_from_mesh_data(capsule_mesh, capsule_data);
type_mesh_map[PhysicsServer::SHAPE_CAPSULE] = capsule_mesh;
RID capsule_shape = ps->shape_create(PhysicsServer::SHAPE_CAPSULE);
Dictionary capsule_params;
capsule_params["radius"] = 0.5;
capsule_params["height"] = 1.4;
ps->shape_set_data(capsule_shape, capsule_params);
type_shape_map[PhysicsServer::SHAPE_CAPSULE] = capsule_shape;
/* CONVEX SHAPE */
PoolVector<Plane> convex_planes = Geometry::build_cylinder_planes(0.5, 0.7, 5, Vector3::AXIS_Z);
RID convex_mesh = RID_PRIME(vs->mesh_create());
Geometry::MeshData convex_data = Geometry::build_convex_mesh(convex_planes);
ConvexHullComputer::convex_hull(convex_data.vertices, convex_data);
vs->mesh_add_surface_from_mesh_data(convex_mesh, convex_data);
type_mesh_map[PhysicsServer::SHAPE_CONVEX_POLYGON] = convex_mesh;
RID convex_shape = ps->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON);
ps->shape_set_data(convex_shape, convex_data.vertices);
type_shape_map[PhysicsServer::SHAPE_CONVEX_POLYGON] = convex_shape;
}
void make_trimesh(Vector<Vector3> p_faces, const Transform &p_xform = Transform()) {
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer *ps = PhysicsServer::get_singleton();
RID trimesh_shape = ps->shape_create(PhysicsServer::SHAPE_CONCAVE_POLYGON);
ps->shape_set_data(trimesh_shape, p_faces);
p_faces = ps->shape_get_data(trimesh_shape); // optimized one
Vector<Vector3> normals; // for drawing
for (int i = 0; i < p_faces.size() / 3; i++) {
Plane p(p_faces[i * 3 + 0], p_faces[i * 3 + 1], p_faces[i * 3 + 2]);
normals.push_back(p.normal);
normals.push_back(p.normal);
normals.push_back(p.normal);
}
RID trimesh_mesh = RID_PRIME(vs->mesh_create());
Array d;
d.resize(RS::ARRAY_MAX);
d[RS::ARRAY_VERTEX] = p_faces;
d[RS::ARRAY_NORMAL] = normals;
vs->mesh_add_surface_from_arrays(trimesh_mesh, RS::PRIMITIVE_TRIANGLES, d);
RID triins = vs->instance_create2(trimesh_mesh, scenario);
RID tribody = RID_PRIME(ps->body_create(PhysicsServer::BODY_MODE_STATIC));
ps->body_set_space(tribody, space);
//todo set space
ps->body_add_shape(tribody, trimesh_shape);
Transform tritrans = p_xform;
ps->body_set_state(tribody, PhysicsServer::BODY_STATE_TRANSFORM, tritrans);
vs->instance_set_transform(triins, tritrans);
}
void make_grid(int p_width, int p_height, float p_cellsize, float p_cellheight, const Transform &p_xform = Transform()) {
Vector<Vector<float>> grid;
grid.resize(p_width);
for (int i = 0; i < p_width; i++) {
grid.write[i].resize(p_height);
for (int j = 0; j < p_height; j++) {
grid.write[i].write[j] = 1.0 + Math::random(-p_cellheight, p_cellheight);
}
}
Vector<Vector3> faces;
for (int i = 1; i < p_width; i++) {
for (int j = 1; j < p_height; j++) {
#define MAKE_VERTEX(m_x, m_z) \
faces.push_back(Vector3((m_x - p_width / 2) * p_cellsize, grid[m_x][m_z], (m_z - p_height / 2) * p_cellsize))
MAKE_VERTEX(i, j - 1);
MAKE_VERTEX(i, j);
MAKE_VERTEX(i - 1, j);
MAKE_VERTEX(i - 1, j - 1);
MAKE_VERTEX(i, j - 1);
MAKE_VERTEX(i - 1, j);
}
}
make_trimesh(faces, p_xform);
}
public:
virtual void input_event(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid() && mm->get_button_mask() & 4) {
ofs_y -= mm->get_relative().y / 200.0;
ofs_x += mm->get_relative().x / 200.0;
}
if (mm.is_valid() && mm->get_button_mask() & 1) {
float y = -mm->get_relative().y / 20.0;
float x = mm->get_relative().x / 20.0;
if (mover.is_valid()) {
PhysicsServer *ps = PhysicsServer::get_singleton();
Transform t = ps->body_get_state(mover, PhysicsServer::BODY_STATE_TRANSFORM);
t.origin += Vector3(x, y, 0);
ps->body_set_state(mover, PhysicsServer::BODY_STATE_TRANSFORM, t);
}
}
}
virtual void request_quit() {
quit = true;
}
virtual void init() {
ofs_x = ofs_y = 0;
init_shapes();
PhysicsServer *ps = PhysicsServer::get_singleton();
space = RID_PRIME(ps->space_create());
ps->space_set_active(space, true);
RenderingServer *vs = RenderingServer::get_singleton();
/* LIGHT */
RID lightaux = RID_PRIME(vs->directional_light_create());
scenario = RID_PRIME(vs->scenario_create());
vs->light_set_shadow(lightaux, true);
light = vs->instance_create2(lightaux, scenario);
Transform t;
t.rotate(Vector3(1.0, 0, 0), 0.6);
vs->instance_set_transform(light, t);
/* CAMERA */
camera = RID_PRIME(vs->camera_create());
RID viewport = RID_PRIME(vs->viewport_create());
Size2i screen_size = OS::get_singleton()->get_window_size();
vs->viewport_set_size(viewport, screen_size.x, screen_size.y);
vs->viewport_attach_to_screen(viewport, Rect2(Vector2(), screen_size));
vs->viewport_set_active(viewport, true);
vs->viewport_attach_camera(viewport, camera);
vs->viewport_set_scenario(viewport, scenario);
vs->camera_set_perspective(camera, 60, 0.1, 40.0);
vs->camera_set_transform(camera, Transform(Basis(), Vector3(0, 9, 12)));
Transform gxf;
gxf.basis.scale(Vector3(1.4, 0.4, 1.4));
gxf.origin = Vector3(-2, 1, -2);
make_grid(5, 5, 2.5, 1, gxf);
test_fall();
quit = false;
}
virtual bool iteration(float p_time) {
if (mover.is_valid()) {
static float joy_speed = 10;
PhysicsServer *ps = PhysicsServer::get_singleton();
Transform t = ps->body_get_state(mover, PhysicsServer::BODY_STATE_TRANSFORM);
t.origin += Vector3(joy_speed * joy_direction.x * p_time, -joy_speed * joy_direction.y * p_time, 0);
ps->body_set_state(mover, PhysicsServer::BODY_STATE_TRANSFORM, t);
};
Transform cameratr;
cameratr.rotate(Vector3(0, 1, 0), ofs_x);
cameratr.rotate(Vector3(1, 0, 0), -ofs_y);
cameratr.translate_local(Vector3(0, 2, 8));
RenderingServer *vs = RenderingServer::get_singleton();
vs->camera_set_transform(camera, cameratr);
return quit;
}
virtual void finish() {
}
void test_joint() {
}
void test_hinge() {
}
void test_character() {
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer *ps = PhysicsServer::get_singleton();
PoolVector<Plane> capsule_planes = Geometry::build_capsule_planes(0.5, 1, 12, 5, Vector3::AXIS_Y);
RID capsule_mesh = RID_PRIME(vs->mesh_create());
Geometry::MeshData capsule_data = Geometry::build_convex_mesh(capsule_planes);
vs->mesh_add_surface_from_mesh_data(capsule_mesh, capsule_data);
type_mesh_map[PhysicsServer::SHAPE_CAPSULE] = capsule_mesh;
RID capsule_shape = ps->shape_create(PhysicsServer::SHAPE_CAPSULE);
Dictionary capsule_params;
capsule_params["radius"] = 0.5;
capsule_params["height"] = 1;
Transform shape_xform;
shape_xform.rotate(Vector3(1, 0, 0), Math_PI / 2.0);
//shape_xform.origin=Vector3(1,1,1);
ps->shape_set_data(capsule_shape, capsule_params);
RID mesh_instance = vs->instance_create2(capsule_mesh, scenario);
character = RID_PRIME(ps->body_create(PhysicsServer::BODY_MODE_CHARACTER));
ps->body_set_space(character, space);
//todo add space
ps->body_add_shape(character, capsule_shape);
ps->body_set_force_integration_callback(character, this, "body_changed_transform", mesh_instance);
ps->body_set_state(character, PhysicsServer::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(-2, 5, -2)));
bodies.push_back(character);
}
void test_fall() {
for (int i = 0; i < 35; i++) {
static const PhysicsServer::ShapeType shape_idx[] = {
PhysicsServer::SHAPE_CAPSULE,
PhysicsServer::SHAPE_BOX,
PhysicsServer::SHAPE_SPHERE,
PhysicsServer::SHAPE_CONVEX_POLYGON
};
PhysicsServer::ShapeType type = shape_idx[i % 4];
Transform t;
t.origin = Vector3(0.0 * i, 3.5 + 1.1 * i, 0.7 + 0.0 * i);
t.basis.rotate(Vector3(0.2, -1, 0), Math_PI / 2 * 0.6);
create_body(type, PhysicsServer::BODY_MODE_RIGID, t);
}
create_static_plane(Plane(Vector3(0, 1, 0), -1));
}
void test_activate() {
create_body(PhysicsServer::SHAPE_BOX, PhysicsServer::BODY_MODE_RIGID, Transform(Basis(), Vector3(0, 2, 0)), true);
create_static_plane(Plane(Vector3(0, 1, 0), -1));
}
virtual bool idle(float p_time) {
return false;
}
TestPhysicsMainLoop() {
}
};
namespace TestPhysics {
MainLoop *test() {
return memnew(TestPhysicsMainLoop);
}
} // namespace TestPhysics

View File

@ -1,40 +0,0 @@
#ifndef TEST_PHYSICS_H
#define TEST_PHYSICS_H
/*************************************************************************/
/* test_physics.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestPhysics {
MainLoop *test();
}
#endif

File diff suppressed because one or more lines are too long

View File

@ -1,40 +0,0 @@
#ifndef TEST_PHYSICS_2D_H
#define TEST_PHYSICS_2D_H
/*************************************************************************/
/* test_physics_2d.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestPhysics2D {
MainLoop *test();
}
#endif // TEST_PHYSICS_2D_H

View File

@ -1,238 +0,0 @@
/*************************************************************************/
/* test_render.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_render.h"
#include "core/math/convex_hull.h"
#include "core/math/math_funcs.h"
#include "core/os/keyboard.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "servers/rendering_server.h"
#define OBJECT_COUNT 50
namespace TestRender {
class TestMainLoop : public MainLoop {
RID test_cube;
RID instance;
RID camera;
RID viewport;
RID light;
RID scenario;
struct InstanceInfo {
RID instance;
Transform base;
Vector3 rot_axis;
};
List<InstanceInfo> instances;
float ofs;
bool quit;
protected:
public:
virtual void input_event(const Ref<InputEvent> &p_event) {
if (p_event->is_pressed()) {
quit = true;
}
}
virtual void init() {
print_line("INITIALIZING TEST RENDER");
RenderingServer *vs = RenderingServer::get_singleton();
test_cube = vs->get_test_cube();
scenario = RID_PRIME(vs->scenario_create());
Vector<Vector3> vts;
/*
PoolVector<Plane> sp = Geometry::build_sphere_planes(2,5,5);
Geometry::MeshData md2 = Geometry::build_convex_mesh(sp);
vts=md2.vertices;
*/
/*
static const int s = 20;
for(int i=0;i<s;i++) {
Basis rot(Vector3(0,1,0),i*Math_PI/s);
for(int j=0;j<s;j++) {
Vector3 v;
v.x=Math::sin(j*Math_PI*2/s);
v.y=Math::cos(j*Math_PI*2/s);
vts.push_back( rot.xform(v*2 ) );
}
}*/
/*for(int i=0;i<100;i++) {
vts.push_back( Vector3(Math::randf()*2-1.0,Math::randf()*2-1.0,Math::randf()*2-1.0).normalized()*2);
}*/
/*
vts.push_back(Vector3(0,0,1));
vts.push_back(Vector3(0,0,-1));
vts.push_back(Vector3(0,1,0));
vts.push_back(Vector3(0,-1,0));
vts.push_back(Vector3(1,0,0));
vts.push_back(Vector3(-1,0,0));*/
vts.push_back(Vector3(1, 1, 1));
vts.push_back(Vector3(1, -1, 1));
vts.push_back(Vector3(-1, 1, 1));
vts.push_back(Vector3(-1, -1, 1));
vts.push_back(Vector3(1, 1, -1));
vts.push_back(Vector3(1, -1, -1));
vts.push_back(Vector3(-1, 1, -1));
vts.push_back(Vector3(-1, -1, -1));
Geometry::MeshData md;
Error err = ConvexHullComputer::convex_hull(vts, md);
print_line("ERR: " + itos(err));
test_cube = RID_PRIME(vs->mesh_create());
vs->mesh_add_surface_from_mesh_data(test_cube, md);
//vs->scenario_set_debug(scenario,RS::SCENARIO_DEBUG_WIREFRAME);
/*
RID sm = vs->shader_create();
//vs->shader_set_fragment_code(sm,"OUT_ALPHA=mod(TIME,1);");
//vs->shader_set_vertex_code(sm,"OUT_VERTEX=IN_VERTEX*mod(TIME,1);");
vs->shader_set_fragment_code(sm,"OUT_DIFFUSE=vec3(1,0,1);OUT_GLOW=abs(sin(TIME));");
RID tcmat = vs->mesh_surface_get_material(test_cube,0);
vs->material_set_shader(tcmat,sm);
*/
List<String> cmdline = OS::get_singleton()->get_cmdline_args();
int object_count = OBJECT_COUNT;
if (cmdline.size() > 0 && cmdline[cmdline.size() - 1].to_int()) {
object_count = cmdline[cmdline.size() - 1].to_int();
};
for (int i = 0; i < object_count; i++) {
InstanceInfo ii;
ii.instance = vs->instance_create2(test_cube, scenario);
ii.base.translate_local(Math::random(-20, 20), Math::random(-20, 20), Math::random(-20, 18));
ii.base.rotate(Vector3(0, 1, 0), Math::randf() * Math_PI);
ii.base.rotate(Vector3(1, 0, 0), Math::randf() * Math_PI);
vs->instance_set_transform(ii.instance, ii.base);
ii.rot_axis = Vector3(Math::random(-1, 1), Math::random(-1, 1), Math::random(-1, 1)).normalized();
instances.push_back(ii);
}
camera = RID_PRIME(vs->camera_create());
// vs->camera_set_perspective( camera, 60.0,0.1, 100.0 );
viewport = RID_PRIME(vs->viewport_create());
Size2i screen_size = OS::get_singleton()->get_window_size();
vs->viewport_set_size(viewport, screen_size.x, screen_size.y);
vs->viewport_attach_to_screen(viewport, Rect2(Vector2(), screen_size));
vs->viewport_set_active(viewport, true);
vs->viewport_attach_camera(viewport, camera);
vs->viewport_set_scenario(viewport, scenario);
vs->camera_set_transform(camera, Transform(Basis(), Vector3(0, 3, 30)));
vs->camera_set_perspective(camera, 60, 0.1, 1000);
/*
RID lightaux = vs->light_create( RenderingServer::LIGHT_OMNI );
vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_RADIUS, 80 );
vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_ATTENUATION, 1 );
vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_ENERGY, 1.5 );
light = vs->instance_create( lightaux );
*/
RID lightaux;
lightaux = vs->directional_light_create();
//vs->light_set_color( lightaux, RenderingServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) );
vs->light_set_color(lightaux, Color(1.0, 1.0, 1.0));
//vs->light_set_shadow( lightaux, true );
light = vs->instance_create2(lightaux, scenario);
Transform lla;
//lla.set_look_at(Vector3(),Vector3(1,-1,1),Vector3(0,1,0));
lla.set_look_at(Vector3(), Vector3(-0.000000, -0.836026, -0.548690), Vector3(0, 1, 0));
vs->instance_set_transform(light, lla);
lightaux = vs->omni_light_create();
//vs->light_set_color( lightaux, RenderingServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,1.0) );
vs->light_set_color(lightaux, Color(1.0, 1.0, 0.0));
vs->light_set_param(lightaux, RenderingServer::LIGHT_PARAM_RANGE, 4);
vs->light_set_param(lightaux, RenderingServer::LIGHT_PARAM_ENERGY, 8);
//vs->light_set_shadow( lightaux, true );
//light = vs->instance_create( lightaux );
ofs = 0;
quit = false;
}
virtual bool iteration(float p_time) {
RenderingServer *vs = RenderingServer::get_singleton();
//Transform t;
//t.rotate(Vector3(0, 1, 0), ofs);
//t.translate_local(Vector3(0,0,20 ));
//vs->camera_set_transform(camera, t);
ofs += p_time * 0.05;
//return quit;
for (List<InstanceInfo>::Element *E = instances.front(); E; E = E->next()) {
Transform pre(Basis(E->get().rot_axis, ofs), Vector3());
vs->instance_set_transform(E->get().instance, pre * E->get().base);
/*
if( !E->next() ) {
vs->free( E->get().instance );
instances.erase(E );
}*/
}
return quit;
}
virtual bool idle(float p_time) {
return quit;
}
virtual void finish() {
}
};
MainLoop *test() {
return memnew(TestMainLoop);
}
} // namespace TestRender

View File

@ -1,40 +0,0 @@
#ifndef TEST_RENDER_H
#define TEST_RENDER_H
/*************************************************************************/
/* test_render.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestRender {
MainLoop *test();
}
#endif

View File

@ -1,435 +0,0 @@
/*************************************************************************/
/* test_shader_lang.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_shader_lang.h"
#include "core/os/file_access.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "scene/main/control.h"
#include "core/input/shortcut.h"
#include "scene/gui/text_edit.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering/shader_types.h"
typedef ShaderLanguage SL;
namespace TestShaderLang {
static String _mktab(int p_level) {
String tb;
for (int i = 0; i < p_level; i++) {
tb += "\t";
}
return tb;
}
static String _typestr(SL::DataType p_type) {
return ShaderLanguage::get_datatype_name(p_type);
}
static String _prestr(SL::DataPrecision p_pres) {
switch (p_pres) {
case SL::PRECISION_LOWP:
return "lowp ";
case SL::PRECISION_MEDIUMP:
return "mediump ";
case SL::PRECISION_HIGHP:
return "highp ";
case SL::PRECISION_DEFAULT:
return "";
}
return "";
}
static String _opstr(SL::Operator p_op) {
return ShaderLanguage::get_operator_text(p_op);
}
static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) {
switch (p_type) {
case SL::TYPE_BOOL:
return p_values[0].boolean ? "true" : "false";
case SL::TYPE_BVEC2:
return String() + "bvec2(" + (p_values[0].boolean ? "true" : "false") + (p_values[1].boolean ? "true" : "false") + ")";
case SL::TYPE_BVEC3:
return String() + "bvec3(" + (p_values[0].boolean ? "true" : "false") + "," + (p_values[1].boolean ? "true" : "false") + "," + (p_values[2].boolean ? "true" : "false") + ")";
case SL::TYPE_BVEC4:
return String() + "bvec4(" + (p_values[0].boolean ? "true" : "false") + "," + (p_values[1].boolean ? "true" : "false") + "," + (p_values[2].boolean ? "true" : "false") + "," + (p_values[3].boolean ? "true" : "false") + ")";
case SL::TYPE_INT:
return rtos(p_values[0].sint);
case SL::TYPE_IVEC2:
return String() + "ivec2(" + rtos(p_values[0].sint) + "," + rtos(p_values[1].sint) + ")";
case SL::TYPE_IVEC3:
return String() + "ivec3(" + rtos(p_values[0].sint) + "," + rtos(p_values[1].sint) + "," + rtos(p_values[2].sint) + ")";
case SL::TYPE_IVEC4:
return String() + "ivec4(" + rtos(p_values[0].sint) + "," + rtos(p_values[1].sint) + "," + rtos(p_values[2].sint) + "," + rtos(p_values[3].sint) + ")";
case SL::TYPE_UINT:
return rtos(p_values[0].real);
case SL::TYPE_UVEC2:
return String() + "uvec2(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + ")";
case SL::TYPE_UVEC3:
return String() + "uvec3(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + "," + rtos(p_values[2].real) + ")";
case SL::TYPE_UVEC4:
return String() + "uvec4(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + "," + rtos(p_values[2].real) + "," + rtos(p_values[3].real) + ")";
case SL::TYPE_FLOAT:
return rtos(p_values[0].real);
case SL::TYPE_VEC2:
return String() + "vec2(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + ")";
case SL::TYPE_VEC3:
return String() + "vec3(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + "," + rtos(p_values[2].real) + ")";
case SL::TYPE_VEC4:
return String() + "vec4(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + "," + rtos(p_values[2].real) + "," + rtos(p_values[3].real) + ")";
default:
ERR_FAIL_V(String());
}
}
static String dump_node_code(SL::Node *p_node, int p_level) {
String code;
switch (p_node->type) {
case SL::Node::TYPE_SHADER: {
SL::ShaderNode *pnode = (SL::ShaderNode *)p_node;
for (OrderedHashMap<StringName, SL::ShaderNode::Uniform>::Element E = pnode->uniforms.front(); E; E = E.next()) {
String ucode = "uniform ";
ucode += _prestr(E.get().precision);
ucode += _typestr(E.get().type);
ucode += " " + String(E.key());
if (E.get().default_value.size()) {
ucode += " = " + get_constant_text(E.get().type, E.get().default_value);
}
static const char *hint_name[SL::ShaderNode::Uniform::HINT_MAX] = {
"",
"color",
"range",
"albedo",
"normal",
"black",
"white"
};
if (E.get().hint) {
ucode += " : " + String(hint_name[E.get().hint]);
}
code += ucode + "\n";
}
for (OrderedHashMap<StringName, SL::ShaderNode::Varying>::Element E = pnode->varyings.front(); E; E = E.next()) {
String vcode = "varying ";
vcode += _prestr(E.get().precision);
vcode += _typestr(E.get().type);
vcode += " " + String(E.key());
code += vcode + "\n";
}
for (int i = 0; i < pnode->functions.size(); i++) {
SL::FunctionNode *fnode = pnode->functions[i].function;
String header;
header = _typestr(fnode->return_type) + " " + fnode->name + "(";
for (int j = 0; j < fnode->arguments.size(); j++) {
if (j > 0) {
header += ", ";
}
header += _prestr(fnode->arguments[j].precision) + _typestr(fnode->arguments[j].type) + " " + fnode->arguments[j].name;
}
header += ")\n";
code += header;
code += dump_node_code(fnode->body, p_level + 1);
}
//code+=dump_node_code(pnode->body,p_level);
} break;
case SL::Node::TYPE_STRUCT: {
} break;
case SL::Node::TYPE_FUNCTION: {
} break;
case SL::Node::TYPE_BLOCK: {
SL::BlockNode *bnode = (SL::BlockNode *)p_node;
//variables
code += _mktab(p_level - 1) + "{\n";
for (RBMap<StringName, SL::BlockNode::Variable>::Element *E = bnode->variables.front(); E; E = E->next()) {
code += _mktab(p_level) + _prestr(E->get().precision) + _typestr(E->get().type) + " " + E->key() + ";\n";
}
for (int i = 0; i < bnode->statements.size(); i++) {
String scode = dump_node_code(bnode->statements[i], p_level);
if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW) {
code += scode; //use directly
} else {
code += _mktab(p_level) + scode + ";\n";
}
}
code += _mktab(p_level - 1) + "}\n";
} break;
case SL::Node::TYPE_VARIABLE: {
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
code = vnode->name;
} break;
case SL::Node::TYPE_VARIABLE_DECLARATION: {
// FIXME: Implement
} break;
case SL::Node::TYPE_ARRAY: {
SL::ArrayNode *vnode = (SL::ArrayNode *)p_node;
code = vnode->name;
} break;
case SL::Node::TYPE_ARRAY_DECLARATION: {
// FIXME: Implement
} break;
case SL::Node::TYPE_ARRAY_CONSTRUCT: {
// FIXME: Implement
} break;
case SL::Node::TYPE_CONSTANT: {
SL::ConstantNode *cnode = (SL::ConstantNode *)p_node;
return get_constant_text(cnode->datatype, cnode->values);
} break;
case SL::Node::TYPE_OPERATOR: {
SL::OperatorNode *onode = (SL::OperatorNode *)p_node;
switch (onode->op) {
case SL::OP_ASSIGN:
case SL::OP_ASSIGN_ADD:
case SL::OP_ASSIGN_SUB:
case SL::OP_ASSIGN_MUL:
case SL::OP_ASSIGN_DIV:
case SL::OP_ASSIGN_SHIFT_LEFT:
case SL::OP_ASSIGN_SHIFT_RIGHT:
case SL::OP_ASSIGN_MOD:
case SL::OP_ASSIGN_BIT_AND:
case SL::OP_ASSIGN_BIT_OR:
case SL::OP_ASSIGN_BIT_XOR:
code = dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level);
break;
case SL::OP_BIT_INVERT:
case SL::OP_NEGATE:
case SL::OP_NOT:
case SL::OP_DECREMENT:
case SL::OP_INCREMENT:
code = _opstr(onode->op) + dump_node_code(onode->arguments[0], p_level);
break;
case SL::OP_POST_DECREMENT:
case SL::OP_POST_INCREMENT:
code = dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op);
break;
case SL::OP_CALL:
case SL::OP_CONSTRUCT:
code = dump_node_code(onode->arguments[0], p_level) + "(";
for (int i = 1; i < onode->arguments.size(); i++) {
if (i > 1) {
code += ", ";
}
code += dump_node_code(onode->arguments[i], p_level);
}
code += ")";
break;
default: {
code = "(" + dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level) + ")";
break;
}
}
} break;
case SL::Node::TYPE_CONTROL_FLOW: {
SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node;
if (cfnode->flow_op == SL::FLOW_OP_IF) {
code += _mktab(p_level) + "if (" + dump_node_code(cfnode->expressions[0], p_level) + ")\n";
code += dump_node_code(cfnode->blocks[0], p_level + 1);
if (cfnode->blocks.size() == 2) {
code += _mktab(p_level) + "else\n";
code += dump_node_code(cfnode->blocks[1], p_level + 1);
}
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
if (cfnode->blocks.size()) {
code = "return " + dump_node_code(cfnode->blocks[0], p_level);
} else {
code = "return";
}
}
} break;
case SL::Node::TYPE_MEMBER: {
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
code = dump_node_code(mnode->owner, p_level) + "." + mnode->name;
} break;
}
return code;
}
static Error recreate_code(void *p_str, SL::ShaderNode *p_program) {
String *str = (String *)p_str;
*str = dump_node_code(p_program, 0);
return OK;
}
MainLoop *test() {
List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
if (cmdlargs.empty()) {
//try editor!
print_line("usage: pandemonium -test shaderlang <shader>");
return nullptr;
}
List<String> code_list;
List<RBMap<StringName, SL::FunctionInfo>> dt_list;
List<Vector<StringName>> rm_list;
List<RBSet<String>> types_list;
int test_count = 0;
SL sl;
if (cmdlargs.empty() || cmdlargs.back()->get() == "shaderlang") {
{
String code;
code += "shader_type canvas_item;\n";
code += "render_mode test_rm;\n";
code += "\n";
code += "void fragment() {\n";
code += "\tCOLOR = vec4(1.0);\n";
code += "\tdiscard;\n";
code += "}\n";
code_list.push_back(code);
Vector<StringName> rm;
rm.push_back("test_rm");
rm_list.push_back(rm);
RBMap<StringName, SL::FunctionInfo> dt;
dt["fragment"].built_ins["COLOR"] = SL::TYPE_VEC4;
dt["fragment"].can_discard = true;
dt_list.push_back(dt);
RBSet<String> types;
types.insert("canvas_item");
types_list.push_back(types);
test_count++;
}
#ifndef _3D_DISABLED
{
String code;
code += "shader_type spatial;\n";
code += "render_mode test_rm;\n";
code += "\n";
code += "void fragment() {\n";
code += "\tALBEDO = vec3(1.0);\n";
code += "\tdiscard;\n";
code += "}\n";
code_list.push_back(code);
Vector<StringName> rm;
rm.push_back("test_rm");
rm_list.push_back(rm);
RBMap<StringName, SL::FunctionInfo> dt;
dt["fragment"].built_ins["ALBEDO"] = SL::TYPE_VEC3;
dt["fragment"].can_discard = true;
dt_list.push_back(dt);
RBSet<String> types;
types.insert("spatial");
types_list.push_back(types);
test_count++;
}
#endif
} else {
FileAccess *fa = FileAccess::open(cmdlargs.back()->get(), FileAccess::READ);
String code;
if (!fa) {
ERR_FAIL_V(nullptr);
}
while (true) {
CharType c = fa->get_8();
if (fa->eof_reached()) {
break;
}
code += c;
}
code_list.push_back(code);
String type = sl.get_shader_type(code);
if (type == "canvas_item") {
dt_list.push_back(ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode::SHADER_CANVAS_ITEM));
rm_list.push_back(ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode::SHADER_CANVAS_ITEM));
} else if (type == "spatial") {
dt_list.push_back(ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode::SHADER_SPATIAL));
rm_list.push_back(ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode::SHADER_SPATIAL));
} else if (type == "particles") {
dt_list.push_back(ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode::SHADER_PARTICLES));
rm_list.push_back(ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode::SHADER_PARTICLES));
}
types_list.push_back(ShaderTypes::get_singleton()->get_types());
test_count++;
}
for (int i = 0; i < test_count; i++) {
String code = code_list[i];
RBMap<StringName, SL::FunctionInfo> dt = dt_list[i];
Vector<StringName> rm = rm_list[i];
RBSet<String> types = types_list[i];
print_line("tokens:\n\n" + sl.token_debug(code));
Error err = sl.compile(code, dt, rm, types);
if (err) {
print_line("Error at line: " + rtos(sl.get_error_line()) + ": " + sl.get_error_text());
return nullptr;
} else {
String code2;
recreate_code(&code2, sl.get_shader());
print_line("code:\n\n" + code2);
}
}
return nullptr;
}
} // namespace TestShaderLang

View File

@ -1,40 +0,0 @@
#ifndef TEST_SHADER_LANG_H
#define TEST_SHADER_LANG_H
/*************************************************************************/
/* test_shader_lang.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestShaderLang {
MainLoop *test();
}
#endif // TEST_SHADER_LANG_H

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +0,0 @@
#ifndef TEST_STRING_H
#define TEST_STRING_H
/*************************************************************************/
/* test_string.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
#include "core/string/ustring.h"
namespace TestString {
MainLoop *test();
}
#endif

View File

@ -1,305 +0,0 @@
/*************************************************************************/
/* test_theme.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_theme.h"
#include "core/os/os.h"
#include "main/tests/test_tools.h"
#include "scene/resources/theme.h"
#define CHECK(X) \
if (!(X)) { \
OS::get_singleton()->print("\tFAIL at line %d: %s\n", __LINE__, #X); \
return false; \
} else { \
OS::get_singleton()->print("\tPASS\n"); \
}
namespace TestTheme {
class Fixture {
public:
struct DataEntry {
Theme::DataType type;
Variant value;
} valid_data[Theme::DATA_TYPE_MAX] = {
{ Theme::DATA_TYPE_COLOR, Color() },
{ Theme::DATA_TYPE_CONSTANT, 42 },
{ Theme::DATA_TYPE_FONT, Variant() },
{ Theme::DATA_TYPE_ICON, Variant() },
{ Theme::DATA_TYPE_STYLEBOX, Variant() },
};
const StringName valid_item_name = "valid_item_name";
const StringName valid_type_name = "ValidTypeName";
// Part of `valid_data` initialization is moved here so that it compiles in Visual Studio 2017.
// See issue #63975.
Fixture() {
valid_data[Theme::DATA_TYPE_FONT].value = Ref<Font>(memnew(BitmapFont));
valid_data[Theme::DATA_TYPE_ICON].value = Ref<Texture>(memnew(ImageTexture));
valid_data[Theme::DATA_TYPE_STYLEBOX].value = Ref<StyleBox>(memnew(StyleBoxFlat));
}
};
bool test_good_theme_type_names() {
Fixture fixture;
StringName names[] = {
"", // Empty name.
"CapitalizedName",
"snake_cased_name",
"42",
"_Underscore_",
};
// add_type
for (const StringName &name : names) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->add_type(name);
CHECK(!ed.has_error);
}
// set_theme_item
for (const StringName &name : names) {
for (const Fixture::DataEntry &entry : fixture.valid_data) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_theme_item(entry.type, fixture.valid_item_name, name, entry.value);
CHECK(!ed.has_error);
}
}
// add_theme_item_type
for (const StringName &name : names) {
for (const Fixture::DataEntry &entry : fixture.valid_data) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->add_theme_item_type(entry.type, name);
CHECK(!ed.has_error);
}
}
// set_type_variation
for (const StringName &name : names) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_type_variation(fixture.valid_type_name, name);
CHECK(ed.has_error == (name == StringName()));
}
for (const StringName &name : names) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_type_variation(name, fixture.valid_type_name);
CHECK(ed.has_error == (name == StringName()));
}
return true;
}
bool test_bad_theme_type_names() {
Fixture fixture;
StringName names[] = {
"With/Slash",
"With Space",
"With@various$symbols!",
String::utf8("contains_汉字"),
};
// add_type
for (const StringName &name : names) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->add_type(name);
CHECK(ed.has_error);
}
// set_theme_item
for (const StringName &name : names) {
for (const Fixture::DataEntry &entry : fixture.valid_data) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_theme_item(entry.type, fixture.valid_item_name, name, entry.value);
CHECK(ed.has_error);
}
}
// add_theme_item_type
for (const StringName &name : names) {
for (const Fixture::DataEntry &entry : fixture.valid_data) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->add_theme_item_type(entry.type, name);
CHECK(ed.has_error);
}
}
// set_type_variation
for (const StringName &name : names) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_type_variation(fixture.valid_type_name, name);
CHECK(ed.has_error);
}
for (const StringName &name : names) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_type_variation(name, fixture.valid_type_name);
CHECK(ed.has_error);
}
return true;
}
bool test_good_theme_item_names() {
Fixture fixture;
StringName names[] = {
"CapitalizedName",
"snake_cased_name",
"42",
"_Underscore_",
};
// set_theme_item
for (const StringName &name : names) {
for (const Fixture::DataEntry &entry : fixture.valid_data) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_theme_item(entry.type, name, fixture.valid_type_name, entry.value);
CHECK(!ed.has_error);
CHECK(theme->has_theme_item(entry.type, name, fixture.valid_type_name));
}
}
// rename_theme_item
for (const StringName &name : names) {
for (const Fixture::DataEntry &entry : fixture.valid_data) {
Ref<Theme> theme = memnew(Theme);
theme->set_theme_item(entry.type, fixture.valid_item_name, fixture.valid_type_name, entry.value);
ErrorDetector ed;
theme->rename_theme_item(entry.type, fixture.valid_item_name, name, fixture.valid_type_name);
CHECK(!ed.has_error);
CHECK(!theme->has_theme_item(entry.type, fixture.valid_item_name, fixture.valid_type_name));
CHECK(theme->has_theme_item(entry.type, name, fixture.valid_type_name));
}
}
return true;
}
bool test_bad_theme_item_names() {
Fixture fixture;
StringName names[] = {
"", // Empty name.
"With/Slash",
"With Space",
"With@various$symbols!",
String::utf8("contains_汉字"),
};
// set_theme_item
for (const StringName &name : names) {
for (const Fixture::DataEntry &entry : fixture.valid_data) {
Ref<Theme> theme = memnew(Theme);
ErrorDetector ed;
theme->set_theme_item(entry.type, name, fixture.valid_type_name, entry.value);
CHECK(ed.has_error);
CHECK(!theme->has_theme_item(entry.type, name, fixture.valid_type_name));
}
}
// rename_theme_item
for (const StringName &name : names) {
for (const Fixture::DataEntry &entry : fixture.valid_data) {
Ref<Theme> theme = memnew(Theme);
theme->set_theme_item(entry.type, fixture.valid_item_name, fixture.valid_type_name, entry.value);
ErrorDetector ed;
theme->rename_theme_item(entry.type, fixture.valid_item_name, name, fixture.valid_type_name);
CHECK(ed.has_error);
CHECK(theme->has_theme_item(entry.type, fixture.valid_item_name, fixture.valid_type_name));
CHECK(!theme->has_theme_item(entry.type, name, fixture.valid_type_name));
}
}
return true;
}
typedef bool (*TestFunc)();
TestFunc test_funcs[] = {
test_good_theme_type_names,
test_bad_theme_type_names,
test_good_theme_item_names,
test_bad_theme_item_names,
nullptr
};
MainLoop *test() {
int count = 0;
int passed = 0;
while (true) {
if (!test_funcs[count]) {
break;
}
bool pass = test_funcs[count]();
if (pass) {
passed++;
}
OS::get_singleton()->print("\t%s\n", pass ? "PASS" : "FAILED");
count++;
}
OS::get_singleton()->print("\n\n\n");
OS::get_singleton()->print("*************\n");
OS::get_singleton()->print("***TOTALS!***\n");
OS::get_singleton()->print("*************\n");
OS::get_singleton()->print("Passed %i of %i tests\n", passed, count);
return nullptr;
}
} // namespace TestTheme
#undef CHECK

View File

@ -1,41 +0,0 @@
/*************************************************************************/
/* test_theme.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_THEME_H
#define TEST_THEME_H
#include "core/os/main_loop.h"
namespace TestTheme {
MainLoop *test();
}
#endif // TEST_THEME_H

View File

@ -1,61 +0,0 @@
/*************************************************************************/
/* test_tools.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_TOOLS_H
#define TEST_TOOLS_H
#include "core/error/error_macros.h"
struct ErrorDetector {
ErrorDetector() {
eh.errfunc = _detect_error;
eh.userdata = this;
add_error_handler(&eh);
}
~ErrorDetector() {
remove_error_handler(&eh);
}
void clear() {
has_error = false;
}
static void _detect_error(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type) {
ErrorDetector *self = (ErrorDetector *)p_self;
self->has_error = true;
}
ErrorHandlerList eh;
bool has_error = false;
};
#endif // TEST_TOOLS_H

View File

@ -1,270 +0,0 @@
/*************************************************************************/
/* test_transform.cpp */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_transform.h"
#include "core/math/random_number_generator.h"
#include "core/math/transform.h"
#include "core/math/vector3.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
// #define PANDEMONIUM_TEST_TRANSFORM_NON_UNIFORM_SCALE_TESTS_ENABLED
namespace TestTransform {
bool test_plane() {
bool pass = true;
// test non-uniform scaling, forward and inverse
Transform tr;
tr.scale(Vector3(1, 2, 3));
Plane p(Vector3(1, 1, 1), Vector3(1, 1, 1).normalized());
Plane p2 = tr.xform(p);
Plane p3 = tr.xform_inv(p2);
if (!p3.normal.is_equal_approx(p.normal)) {
OS::get_singleton()->print("Fail due to Transform::xform(Plane)\n");
pass = false;
}
return pass;
}
bool test_aabb_regular() {
bool pass = true;
Transform tr;
tr.basis = Basis(Vector3(Math_PI, 0, 0));
tr.origin = Vector3(1, 2, 3);
AABB bb(Vector3(1, 1, 1), Vector3(2, 3, 4));
// Test forward xform.
AABB bb2 = tr.xform(bb);
AABB bb3 = tr.xform_inv(bb2);
if (!bb3.position.is_equal_approx(bb.position)) {
OS::get_singleton()->print("Fail due to Transform::xform_inv(AABB) position\n");
pass = false;
}
if (!bb3.size.is_equal_approx(bb.size)) {
OS::get_singleton()->print("Fail due to Transform::xform_inv(AABB) size\n");
pass = false;
}
if (!pass) {
String string = String("bb2 : ") + String(Variant(bb2));
OS::get_singleton()->print("\t%s\n", string.utf8().get_data());
string = String("bb3 : ") + String(Variant(bb3));
OS::get_singleton()->print("\t%s\n", string.utf8().get_data());
}
return pass;
}
bool test_aabb_non_uniform_scale() {
bool pass = true;
Transform tr;
tr.scale(Vector3(1, 2, 3));
AABB bb(Vector3(1, 1, 1), Vector3(2, 3, 4));
// Test forward xform.
AABB bb2 = tr.xform(bb);
if (!bb2.position.is_equal_approx(Vector3(1, 2, 3))) {
OS::get_singleton()->print("Fail with non-uniform scale due to Transform::xform(AABB) position\n");
pass = false;
}
if (!bb2.size.is_equal_approx(Vector3(2, 6, 12))) {
OS::get_singleton()->print("Fail with non-uniform scale due to Transform::xform(AABB) size\n");
pass = false;
}
// Now test inverse.
// This will fail if using the transpose and not the affine_inverse.
bb2.position = Vector3(1, 2, 3);
bb2.size = Vector3(2, 6, 12);
AABB bb3 = tr.xform_inv(bb2);
if (!bb3.position.is_equal_approx(bb.position)) {
OS::get_singleton()->print("Fail with non-uniform scale due to Transform::xform_inv(AABB) position\n");
pass = false;
}
if (!bb3.size.is_equal_approx(bb.size)) {
OS::get_singleton()->print("Fail with non-uniform scale due to Transform::xform_inv(AABB) size\n");
pass = false;
}
if (!pass) {
String string = String("bb2 : ") + String(Variant(bb2));
OS::get_singleton()->print("\t%s\n", string.utf8().get_data());
string = String("bb3 : ") + String(Variant(bb3));
OS::get_singleton()->print("\t%s\n", string.utf8().get_data());
}
return pass;
}
bool test_aabb() {
bool pass = true;
if (!test_aabb_regular()) {
pass = false;
}
#ifdef PANDEMONIUM_TEST_TRANSFORM_NON_UNIFORM_SCALE_TESTS_ENABLED
if (!test_aabb_non_uniform_scale()) {
pass = false;
}
#endif
return pass;
}
bool test_vector3_regular() {
bool pass = true;
Transform tr;
RandomNumberGenerator rng;
const real_t range = 1800.0;
const real_t range_rot = Math_PI;
bool passed_multi = true;
for (int n = 0; n < 1000; n++) {
Vector3 pt_test = Vector3(rng.randf_range(-range, range), rng.randf_range(-range, range), rng.randf_range(-range, range));
tr.origin = Vector3(rng.randf_range(-range, range), rng.randf_range(-range, range), rng.randf_range(-range, range));
tr.basis = Basis(Vector3(rng.randf_range(-range_rot, range_rot), rng.randf_range(-range_rot, range_rot), rng.randf_range(-range_rot, range_rot)));
Vector3 pt = tr.xform(pt_test);
pt = tr.xform_inv(pt);
if (!pt.is_equal_approx(pt_test, 0.1)) {
passed_multi = false;
}
}
if (!passed_multi) {
OS::get_singleton()->print("Failed multitest due to Transform::xform and xform_inv(Vector3)\n");
pass = false;
}
return pass;
}
bool test_vector3_non_uniform_scale() {
bool pass = true;
// Regular scale.
Transform tr;
tr.scale(Vector3(3, 3, 3));
Vector3 pt(1, 1, 1);
Vector3 res = tr.xform(pt);
if (!res.is_equal_approx(Vector3(3, 3, 3))) {
OS::get_singleton()->print("Fail with scale due to Transform::xform(Vector3)\n");
pass = false;
}
res = tr.xform_inv(res);
if (!res.is_equal_approx(pt)) {
OS::get_singleton()->print("Fail with scale due to Transform::xform_inv(Vector3)\n");
pass = false;
}
// Non uniform scale.
tr.scale(Vector3(1, 2, 3));
res = tr.xform(pt);
if (!res.is_equal_approx(Vector3(1, 2, 3))) {
OS::get_singleton()->print("Fail with non-uniform scale due to Transform::xform(Vector3)\n");
pass = false;
}
pt = Vector3(1, 2, 3);
res = tr.xform_inv(pt);
if (!res.is_equal_approx(Vector3(1, 1, 1))) {
OS::get_singleton()->print("Fail with non-uniform scale due to Transform::xform_inv(Vector3)\n");
pass = false;
}
return pass;
}
bool test_vector3() {
bool pass = true;
if (!test_vector3_regular()) {
pass = false;
}
#ifdef PANDEMONIUM_TEST_TRANSFORM_NON_UNIFORM_SCALE_TESTS_ENABLED
if (!test_vector3_non_uniform_scale()) {
pass = false;
}
#endif
return pass;
}
MainLoop *test() {
OS::get_singleton()->print("Start Transform checks.\n");
bool success = true;
if (!test_vector3()) {
success = false;
}
if (!test_plane()) {
success = false;
}
if (!test_aabb()) {
success = false;
}
if (success) {
OS::get_singleton()->print("Transform checks passed.\n");
} else {
OS::get_singleton()->print("Transform checks FAILED.\n");
}
return nullptr;
}
} // namespace TestTransform

View File

@ -1,39 +0,0 @@
#ifndef TEST_TRANSFORM_H
#define TEST_TRANSFORM_H
/*************************************************************************/
/* test_transform.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. */
/*************************************************************************/
#include "core/os/main_loop.h"
namespace TestTransform {
MainLoop *test();
}
#endif

View File

@ -1,294 +0,0 @@
/*************************************************************************/
/* test_xml_parser.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_xml_parser.h"
#include "core/os/os.h"
namespace TestXMLParser {
#define CHECK(X) \
if (!(X)) { \
OS::get_singleton()->print("\tFAIL at %s\n", #X); \
return false; \
} else { \
OS::get_singleton()->print("\tPASS\n"); \
}
#define REQUIRE_EQ(X, Y) \
if ((X) != (Y)) { \
OS::get_singleton()->print("\tFAIL at %s != %s\n", #X, #Y); \
return false; \
} else { \
OS::get_singleton()->print("\tPASS\n"); \
}
Vector<uint8_t> _to_buffer(const String &p_text) {
Vector<uint8_t> buff;
for (int i = 0; i < p_text.length(); i++) {
buff.push_back(p_text.get(i));
}
return buff;
}
bool test_1() {
String source = "<?xml version = \"1.0\" encoding=\"UTF-8\" ?>\
<top attr=\"attr value\">\
Text&lt;&#65;&#x42;&gt;\
</top>";
Vector<uint8_t> buff = _to_buffer(source);
XMLParser parser;
parser.open_buffer(buff);
// <?xml ...?> gets parsed as NODE_UNKNOWN
CHECK(parser.read() == OK);
CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_UNKNOWN);
CHECK(parser.read() == OK);
CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_ELEMENT);
CHECK(parser.get_node_name() == "top");
CHECK(parser.has_attribute("attr"));
CHECK(parser.get_attribute_value("attr") == "attr value");
CHECK(parser.read() == OK);
CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_TEXT);
CHECK(parser.get_node_data().lstrip(" \t") == "Text<AB>");
CHECK(parser.read() == OK);
CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_ELEMENT_END);
CHECK(parser.get_node_name() == "top");
parser.close();
return true;
}
bool test_comments() {
XMLParser parser;
// Missing end of comment.
{
const String input = "<first></first><!-- foo";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), 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);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
REQUIRE_EQ(parser.get_node_name(), " foo");
}
// Bad start of comment.
{
const String input = "<first></first><!-";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), 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);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
REQUIRE_EQ(parser.get_node_name(), "-");
}
// Unblanced angle brackets in comment.
{
const String input = "<!-- example << --><next-tag></next-tag>";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
REQUIRE_EQ(parser.get_node_name(), " example << ");
}
// Doctype.
{
const String input = "<!DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]>";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_COMMENT);
REQUIRE_EQ(parser.get_node_name(), "DOCTYPE greeting [<!ELEMENT greeting (#PCDATA)>]");
}
return true;
}
bool test_premature_endings() {
struct Case {
String input;
String expected_name;
XMLParser::NodeType expected_type;
} const cases[] = {
// Incomplete unknown.
{ "<first></first><?xml", "?xml", XMLParser::NodeType::NODE_UNKNOWN },
// Incomplete CDStart.
{ "<first></first><![CD", "", XMLParser::NodeType::NODE_CDATA },
// Incomplete CData.
{ "<first></first><![CDATA[example", "example", XMLParser::NodeType::NODE_CDATA },
// Incomplete CDEnd.
{ "<first></first><![CDATA[example]]", "example]]", XMLParser::NodeType::NODE_CDATA },
// Incomplete start-tag name.
{ "<first></first><second", "second", XMLParser::NodeType::NODE_ELEMENT },
};
XMLParser parser;
for (unsigned long i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
const Case &test_case = cases[i];
REQUIRE_EQ(parser.open_buffer(_to_buffer(test_case.input)), 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);
REQUIRE_EQ(parser.get_node_type(), test_case.expected_type);
REQUIRE_EQ(parser.get_node_name(), test_case.expected_name);
}
// Incomplete start-tag attribute name.
{
const String input = "<first></first><second attr1=\"foo\" attr2";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
REQUIRE_EQ(parser.get_node_name(), "second");
REQUIRE_EQ(parser.get_attribute_count(), 1);
REQUIRE_EQ(parser.get_attribute_name(0), "attr1");
REQUIRE_EQ(parser.get_attribute_value(0), "foo");
}
// Incomplete start-tag attribute unquoted value.
{
const String input = "<first></first><second attr1=\"foo\" attr2=bar";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
REQUIRE_EQ(parser.get_node_name(), "second");
REQUIRE_EQ(parser.get_attribute_count(), 1);
REQUIRE_EQ(parser.get_attribute_name(0), "attr1");
REQUIRE_EQ(parser.get_attribute_value(0), "foo");
}
// Incomplete start-tag attribute quoted value.
{
const String input = "<first></first><second attr1=\"foo\" attr2=\"bar";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
REQUIRE_EQ(parser.get_node_name(), "second");
REQUIRE_EQ(parser.get_attribute_count(), 2);
REQUIRE_EQ(parser.get_attribute_name(0), "attr1");
REQUIRE_EQ(parser.get_attribute_value(0), "foo");
REQUIRE_EQ(parser.get_attribute_name(1), "attr2");
REQUIRE_EQ(parser.get_attribute_value(1), "bar");
}
// Incomplete end-tag name.
{
const String input = "<first></fir";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
REQUIRE_EQ(parser.get_node_name(), "fir");
}
// Trailing text.
{
const String input = "<first></first>example";
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_TEXT);
REQUIRE_EQ(parser.get_node_data(), "example");
}
return true;
}
bool test_cdata() {
const String input = "<a><![CDATA[my cdata content goes here]]></a>";
XMLParser parser;
REQUIRE_EQ(parser.open_buffer(_to_buffer(input)), OK);
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT);
REQUIRE_EQ(parser.get_node_name(), "a");
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_CDATA);
REQUIRE_EQ(parser.get_node_name(), "my cdata content goes here");
REQUIRE_EQ(parser.read(), OK);
REQUIRE_EQ(parser.get_node_type(), XMLParser::NodeType::NODE_ELEMENT_END);
REQUIRE_EQ(parser.get_node_name(), "a");
return true;
}
typedef bool (*TestFunc)();
TestFunc test_funcs[] = {
test_1,
test_comments,
test_premature_endings,
test_cdata,
nullptr
};
MainLoop *test() {
int count = 0;
int passed = 0;
while (true) {
if (!test_funcs[count]) {
break;
}
bool pass = test_funcs[count]();
if (pass) {
passed++;
}
OS::get_singleton()->print("\t%s\n", pass ? "PASS" : "FAILED");
count++;
}
OS::get_singleton()->print("\n\n\n");
OS::get_singleton()->print("*************\n");
OS::get_singleton()->print("***TOTALS!***\n");
OS::get_singleton()->print("*************\n");
OS::get_singleton()->print("Passed %i of %i tests\n", passed, count);
return nullptr;
}
} // namespace TestXMLParser

View File

@ -1,44 +0,0 @@
#ifndef TEST_XML_PARSER_H
#define TEST_XML_PARSER_H
/*************************************************************************/
/* test_xml_parser.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. */
/*************************************************************************/
#include <inttypes.h>
#include "core/io/xml_parser.h"
#include "core/os/main_loop.h"
#include "core/string/ustring.h"
#include "core/containers/vector.h"
namespace TestXMLParser {
MainLoop *test();
}
#endif // TEST_XML_PARSER_H