test_node.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /**************************************************************************/
  2. /* test_node.h */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #ifndef TEST_NODE_H
  31. #define TEST_NODE_H
  32. #include "scene/main/node.h"
  33. #include "tests/test_macros.h"
  34. namespace TestNode {
  35. TEST_CASE("[SceneTree][Node] Testing node operations with a very simple scene tree") {
  36. Node *node = memnew(Node);
  37. // Check initial scene tree setup.
  38. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 0);
  39. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 1);
  40. // Check initial node setup.
  41. CHECK(node->get_name() == StringName());
  42. CHECK_FALSE(node->is_inside_tree());
  43. CHECK_EQ(node->get_parent(), nullptr);
  44. ERR_PRINT_OFF;
  45. CHECK(node->get_path().is_empty());
  46. ERR_PRINT_ON;
  47. CHECK_EQ(node->get_child_count(), 0);
  48. SceneTree::get_singleton()->get_root()->add_child(node);
  49. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 1);
  50. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 2);
  51. CHECK(node->get_name() != StringName());
  52. CHECK(node->is_inside_tree());
  53. CHECK_EQ(SceneTree::get_singleton()->get_root(), node->get_parent());
  54. CHECK_FALSE(node->get_path().is_empty());
  55. CHECK_EQ(node->get_child_count(), 0);
  56. SUBCASE("Node should be accessible as first child") {
  57. Node *child = SceneTree::get_singleton()->get_root()->get_child(0);
  58. CHECK_EQ(child, node);
  59. }
  60. SUBCASE("Node should be accessible via the node path") {
  61. Node *child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(node->get_path());
  62. CHECK_EQ(child_by_path, node);
  63. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(NodePath("Node"));
  64. CHECK_EQ(child_by_path, nullptr);
  65. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(NodePath("/root/Node"));
  66. CHECK_EQ(child_by_path, nullptr);
  67. node->set_name("Node");
  68. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(node->get_path());
  69. CHECK_EQ(child_by_path, node);
  70. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(NodePath("Node"));
  71. CHECK_EQ(child_by_path, node);
  72. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(NodePath("/root/Node"));
  73. CHECK_EQ(child_by_path, node);
  74. }
  75. SUBCASE("Node should be accessible via group") {
  76. List<Node *> nodes;
  77. SceneTree::get_singleton()->get_nodes_in_group("nodes", &nodes);
  78. CHECK(nodes.is_empty());
  79. node->add_to_group("nodes");
  80. SceneTree::get_singleton()->get_nodes_in_group("nodes", &nodes);
  81. CHECK_EQ(nodes.size(), 1);
  82. List<Node *>::Element *E = nodes.front();
  83. CHECK_EQ(E->get(), node);
  84. }
  85. SUBCASE("Node should be possible to find") {
  86. Node *child = SceneTree::get_singleton()->get_root()->find_child("Node", true, false);
  87. CHECK_EQ(child, nullptr);
  88. node->set_name("Node");
  89. child = SceneTree::get_singleton()->get_root()->find_child("Node", true, false);
  90. CHECK_EQ(child, node);
  91. }
  92. SUBCASE("Node should be possible to remove") {
  93. SceneTree::get_singleton()->get_root()->remove_child(node);
  94. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 0);
  95. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 1);
  96. CHECK_FALSE(node->is_inside_tree());
  97. CHECK_EQ(node->get_parent(), nullptr);
  98. ERR_PRINT_OFF;
  99. CHECK(node->get_path().is_empty());
  100. ERR_PRINT_ON;
  101. }
  102. SUBCASE("Node should be possible to move") {
  103. SceneTree::get_singleton()->get_root()->move_child(node, 0);
  104. Node *child = SceneTree::get_singleton()->get_root()->get_child(0);
  105. CHECK_EQ(child, node);
  106. CHECK(node->is_inside_tree());
  107. }
  108. SUBCASE("Node should be possible to reparent") {
  109. node->reparent(SceneTree::get_singleton()->get_root());
  110. Node *child = SceneTree::get_singleton()->get_root()->get_child(0);
  111. CHECK_EQ(child, node);
  112. CHECK(node->is_inside_tree());
  113. }
  114. SUBCASE("Node should be possible to duplicate") {
  115. node->set_name("MyName");
  116. Node *duplicate = node->duplicate();
  117. CHECK_FALSE(node == duplicate);
  118. CHECK_FALSE(duplicate->is_inside_tree());
  119. CHECK_EQ(duplicate->get_name(), node->get_name());
  120. memdelete(duplicate);
  121. }
  122. memdelete(node);
  123. }
  124. TEST_CASE("[SceneTree][Node] Testing node operations with a more complex simple scene tree") {
  125. Node *node1 = memnew(Node);
  126. Node *node2 = memnew(Node);
  127. Node *node1_1 = memnew(Node);
  128. SceneTree::get_singleton()->get_root()->add_child(node1);
  129. SceneTree::get_singleton()->get_root()->add_child(node2);
  130. node1->add_child(node1_1);
  131. CHECK(node1_1->is_inside_tree());
  132. CHECK_EQ(node1_1->get_parent(), node1);
  133. CHECK_EQ(node1->get_child_count(), 1);
  134. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 2);
  135. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 4);
  136. SUBCASE("Nodes should be accessible via get_child(..)") {
  137. Node *child1 = SceneTree::get_singleton()->get_root()->get_child(0);
  138. CHECK_EQ(child1, node1);
  139. Node *child2 = SceneTree::get_singleton()->get_root()->get_child(1);
  140. CHECK_EQ(child2, node2);
  141. Node *child1_1 = node1->get_child(0);
  142. CHECK_EQ(child1_1, node1_1);
  143. }
  144. SUBCASE("Removed nodes should also remove their children from the scene tree") {
  145. // Should also remove node1_1 from the scene tree.
  146. SceneTree::get_singleton()->get_root()->remove_child(node1);
  147. CHECK_EQ(node1->get_child_count(), 1);
  148. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 1);
  149. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 2);
  150. // First child should now be the second node.
  151. Node *child1 = SceneTree::get_singleton()->get_root()->get_child(0);
  152. CHECK_EQ(child1, node2);
  153. }
  154. SUBCASE("Removed children nodes should not affect their parent in the scene tree") {
  155. node1->remove_child(node1_1);
  156. CHECK_EQ(node1_1->get_parent(), nullptr);
  157. CHECK_EQ(node1->get_child_count(), 0);
  158. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 3);
  159. }
  160. SUBCASE("Nodes should be in the expected order when a node is moved to the back") {
  161. SceneTree::get_singleton()->get_root()->move_child(node1, 1);
  162. Node *child1 = SceneTree::get_singleton()->get_root()->get_child(0);
  163. CHECK_EQ(child1, node2);
  164. Node *child2 = SceneTree::get_singleton()->get_root()->get_child(1);
  165. CHECK_EQ(child2, node1);
  166. }
  167. SUBCASE("Nodes should be in the expected order when a node is moved to the front") {
  168. SceneTree::get_singleton()->get_root()->move_child(node2, 0);
  169. Node *child1 = SceneTree::get_singleton()->get_root()->get_child(0);
  170. CHECK_EQ(child1, node2);
  171. Node *child2 = SceneTree::get_singleton()->get_root()->get_child(1);
  172. CHECK_EQ(child2, node1);
  173. }
  174. SUBCASE("Nodes should be in the expected order when reparented (remove/add)") {
  175. CHECK_EQ(node2->get_child_count(), 0);
  176. node1->remove_child(node1_1);
  177. CHECK_EQ(node1->get_child_count(), 0);
  178. CHECK_EQ(node1_1->get_parent(), nullptr);
  179. node2->add_child(node1_1);
  180. CHECK_EQ(node2->get_child_count(), 1);
  181. CHECK_EQ(node1_1->get_parent(), node2);
  182. Node *child = node2->get_child(0);
  183. CHECK_EQ(child, node1_1);
  184. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 2);
  185. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 4);
  186. }
  187. SUBCASE("Nodes should be in the expected order when reparented") {
  188. CHECK_EQ(node2->get_child_count(), 0);
  189. node1_1->reparent(node2);
  190. CHECK_EQ(node1->get_child_count(), 0);
  191. CHECK_EQ(node2->get_child_count(), 1);
  192. CHECK_EQ(node1_1->get_parent(), node2);
  193. Node *child = node2->get_child(0);
  194. CHECK_EQ(child, node1_1);
  195. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 2);
  196. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 4);
  197. }
  198. SUBCASE("Nodes should be possible to find") {
  199. Node *child = SceneTree::get_singleton()->get_root()->find_child("NestedNode", true, false);
  200. CHECK_EQ(child, nullptr);
  201. node1->set_name("Node1");
  202. node2->set_name("Node2");
  203. node1_1->set_name("NestedNode");
  204. child = SceneTree::get_singleton()->get_root()->find_child("NestedNode", true, false);
  205. CHECK_EQ(child, node1_1);
  206. // First node that matches with the name is node1.
  207. child = SceneTree::get_singleton()->get_root()->find_child("Node?", true, false);
  208. CHECK_EQ(child, node1);
  209. SceneTree::get_singleton()->get_root()->move_child(node2, 0);
  210. // It should be node2, as it is now the first one in the tree.
  211. child = SceneTree::get_singleton()->get_root()->find_child("Node?", true, false);
  212. CHECK_EQ(child, node2);
  213. }
  214. SUBCASE("Nodes should be accessible via their node path") {
  215. Node *child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(node1->get_path());
  216. CHECK_EQ(child_by_path, node1);
  217. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(node2->get_path());
  218. CHECK_EQ(child_by_path, node2);
  219. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(node1_1->get_path());
  220. CHECK_EQ(child_by_path, node1_1);
  221. node1->set_name("Node1");
  222. node1_1->set_name("NestedNode");
  223. child_by_path = node1->get_node_or_null(NodePath("NestedNode"));
  224. CHECK_EQ(child_by_path, node1_1);
  225. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(NodePath("/root/Node1/NestedNode"));
  226. CHECK_EQ(child_by_path, node1_1);
  227. child_by_path = SceneTree::get_singleton()->get_root()->get_node_or_null(NodePath("Node1/NestedNode"));
  228. CHECK_EQ(child_by_path, node1_1);
  229. }
  230. SUBCASE("Nodes should be accessible via their groups") {
  231. List<Node *> nodes;
  232. SceneTree::get_singleton()->get_nodes_in_group("nodes", &nodes);
  233. CHECK(nodes.is_empty());
  234. SceneTree::get_singleton()->get_nodes_in_group("other_nodes", &nodes);
  235. CHECK(nodes.is_empty());
  236. node1->add_to_group("nodes");
  237. node2->add_to_group("other_nodes");
  238. node1_1->add_to_group("nodes");
  239. node1_1->add_to_group("other_nodes");
  240. SceneTree::get_singleton()->get_nodes_in_group("nodes", &nodes);
  241. CHECK_EQ(nodes.size(), 2);
  242. List<Node *>::Element *E = nodes.front();
  243. CHECK_EQ(E->get(), node1);
  244. E = E->next();
  245. CHECK_EQ(E->get(), node1_1);
  246. // Clear and try again with the other group.
  247. nodes.clear();
  248. SceneTree::get_singleton()->get_nodes_in_group("other_nodes", &nodes);
  249. CHECK_EQ(nodes.size(), 2);
  250. E = nodes.front();
  251. CHECK_EQ(E->get(), node1_1);
  252. E = E->next();
  253. CHECK_EQ(E->get(), node2);
  254. // Clear and try again with the other group and one node removed.
  255. nodes.clear();
  256. node1->remove_from_group("nodes");
  257. SceneTree::get_singleton()->get_nodes_in_group("nodes", &nodes);
  258. CHECK_EQ(nodes.size(), 1);
  259. E = nodes.front();
  260. CHECK_EQ(E->get(), node1_1);
  261. }
  262. SUBCASE("Nodes added as siblings of another node should be right next to it") {
  263. node1->remove_child(node1_1);
  264. node1->add_sibling(node1_1);
  265. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 3);
  266. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 4);
  267. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child(0), node1);
  268. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child(1), node1_1);
  269. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child(2), node2);
  270. }
  271. SUBCASE("Replaced nodes should be be removed and the replacing node added") {
  272. SceneTree::get_singleton()->get_root()->remove_child(node2);
  273. node1->replace_by(node2);
  274. CHECK_EQ(SceneTree::get_singleton()->get_root()->get_child_count(), 1);
  275. CHECK_EQ(SceneTree::get_singleton()->get_node_count(), 3);
  276. CHECK_FALSE(node1->is_inside_tree());
  277. CHECK(node2->is_inside_tree());
  278. CHECK_EQ(node1->get_parent(), nullptr);
  279. CHECK_EQ(node2->get_parent(), SceneTree::get_singleton()->get_root());
  280. CHECK_EQ(node2->get_child_count(), 1);
  281. CHECK_EQ(node2->get_child(0), node1_1);
  282. }
  283. SUBCASE("Replacing nodes should keep the groups of the replaced nodes") {
  284. SceneTree::get_singleton()->get_root()->remove_child(node2);
  285. node1->add_to_group("nodes");
  286. node1->replace_by(node2, true);
  287. List<Node *> nodes;
  288. SceneTree::get_singleton()->get_nodes_in_group("nodes", &nodes);
  289. CHECK_EQ(nodes.size(), 1);
  290. List<Node *>::Element *E = nodes.front();
  291. CHECK_EQ(E->get(), node2);
  292. }
  293. SUBCASE("Duplicating a node should also duplicate the children") {
  294. node1->set_name("MyName1");
  295. node1_1->set_name("MyName1_1");
  296. Node *duplicate1 = node1->duplicate();
  297. CHECK_EQ(duplicate1->get_child_count(), node1->get_child_count());
  298. Node *duplicate1_1 = duplicate1->get_child(0);
  299. CHECK_EQ(duplicate1_1->get_child_count(), node1_1->get_child_count());
  300. CHECK_EQ(duplicate1->get_name(), node1->get_name());
  301. CHECK_EQ(duplicate1_1->get_name(), node1_1->get_name());
  302. CHECK_FALSE(duplicate1->is_inside_tree());
  303. CHECK_FALSE(duplicate1_1->is_inside_tree());
  304. memdelete(duplicate1_1);
  305. memdelete(duplicate1);
  306. }
  307. memdelete(node1_1);
  308. memdelete(node1);
  309. memdelete(node2);
  310. }
  311. TEST_CASE("[Node] Processing") {
  312. Node *node = memnew(Node);
  313. SUBCASE("Processing") {
  314. CHECK_FALSE(node->is_processing());
  315. node->set_process(true);
  316. CHECK(node->is_processing());
  317. node->set_process(false);
  318. CHECK_FALSE(node->is_processing());
  319. }
  320. SUBCASE("Physics processing") {
  321. CHECK_FALSE(node->is_physics_processing());
  322. node->set_physics_process(true);
  323. CHECK(node->is_physics_processing());
  324. node->set_physics_process(false);
  325. CHECK_FALSE(node->is_physics_processing());
  326. }
  327. SUBCASE("Unhandled input processing") {
  328. CHECK_FALSE(node->is_processing_unhandled_input());
  329. node->set_process_unhandled_input(true);
  330. CHECK(node->is_processing_unhandled_input());
  331. node->set_process_unhandled_input(false);
  332. CHECK_FALSE(node->is_processing_unhandled_input());
  333. }
  334. SUBCASE("Input processing") {
  335. CHECK_FALSE(node->is_processing_input());
  336. node->set_process_input(true);
  337. CHECK(node->is_processing_input());
  338. node->set_process_input(false);
  339. CHECK_FALSE(node->is_processing_input());
  340. }
  341. SUBCASE("Unhandled key input processing") {
  342. CHECK_FALSE(node->is_processing_unhandled_key_input());
  343. node->set_process_unhandled_key_input(true);
  344. CHECK(node->is_processing_unhandled_key_input());
  345. node->set_process_unhandled_key_input(false);
  346. CHECK_FALSE(node->is_processing_unhandled_key_input());
  347. }
  348. SUBCASE("Shortcut input processing") {
  349. CHECK_FALSE(node->is_processing_shortcut_input());
  350. node->set_process_shortcut_input(true);
  351. CHECK(node->is_processing_shortcut_input());
  352. node->set_process_shortcut_input(false);
  353. CHECK_FALSE(node->is_processing_shortcut_input());
  354. }
  355. SUBCASE("Internal processing") {
  356. CHECK_FALSE(node->is_processing_internal());
  357. node->set_process_internal(true);
  358. CHECK(node->is_processing_internal());
  359. node->set_process_internal(false);
  360. CHECK_FALSE(node->is_processing_internal());
  361. }
  362. memdelete(node);
  363. }
  364. } // namespace TestNode
  365. #endif // TEST_NODE_H