Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/tests/scene/test_control.cpp
45991 views
1
/**************************************************************************/
2
/* test_control.cpp */
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
31
#include "tests/test_macros.h"
32
33
TEST_FORCE_LINK(test_control)
34
35
#include "core/input/input_map.h" // IWYU pragma: keep // Used by `SEND_GUI_ACTION` macro.
36
#include "scene/2d/node_2d.h"
37
#include "scene/gui/control.h"
38
#include "scene/main/scene_tree.h"
39
#include "scene/main/window.h"
40
#include "tests/display_server_mock.h"
41
#include "tests/signal_watcher.h"
42
43
namespace TestControl {
44
45
TEST_CASE("[SceneTree][Control] Transforms") {
46
SUBCASE("[Control][Global Transform] Global Transform should be accessible while not in SceneTree.") { // GH-79453
47
Control *test_node = memnew(Control);
48
Control *test_child = memnew(Control);
49
test_node->add_child(test_child);
50
51
test_node->set_global_position(Point2(1, 1));
52
CHECK_EQ(test_node->get_global_position(), Point2(1, 1));
53
CHECK_EQ(test_child->get_global_position(), Point2(1, 1));
54
test_node->set_global_position(Point2(2, 2));
55
CHECK_EQ(test_node->get_global_position(), Point2(2, 2));
56
test_node->set_scale(Vector2(4, 4));
57
CHECK_EQ(test_node->get_global_transform(), Transform2D(0, Size2(4, 4), 0, Vector2(2, 2)));
58
test_node->set_scale(Vector2(1, 1));
59
test_node->set_rotation_degrees(90);
60
CHECK_EQ(test_node->get_global_transform(), Transform2D(Math::PI / 2, Vector2(2, 2)));
61
test_node->set_pivot_offset(Vector2(1, 0));
62
CHECK_EQ(test_node->get_global_transform(), Transform2D(Math::PI / 2, Vector2(3, 1)));
63
64
memdelete(test_child);
65
memdelete(test_node);
66
}
67
}
68
69
TEST_CASE("[SceneTree][Control] Focus") {
70
Control *ctrl = memnew(Control);
71
SceneTree::get_singleton()->get_root()->add_child(ctrl);
72
73
SUBCASE("[SceneTree][Control] Default focus") {
74
CHECK_UNARY_FALSE(ctrl->has_focus());
75
}
76
77
SUBCASE("[SceneTree][Control] Can't grab focus with default focus mode") {
78
ERR_PRINT_OFF
79
ctrl->grab_focus();
80
ERR_PRINT_ON
81
82
CHECK_UNARY_FALSE(ctrl->has_focus());
83
}
84
85
SUBCASE("[SceneTree][Control] Can grab focus") {
86
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
87
ctrl->grab_focus();
88
89
CHECK_UNARY(ctrl->has_focus());
90
}
91
92
SUBCASE("[SceneTree][Control] Can release focus") {
93
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
94
ctrl->grab_focus();
95
CHECK_UNARY(ctrl->has_focus());
96
97
ctrl->release_focus();
98
CHECK_UNARY_FALSE(ctrl->has_focus());
99
}
100
101
SUBCASE("[SceneTree][Control] Only one can grab focus at the same time") {
102
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
103
ctrl->grab_focus();
104
CHECK_UNARY(ctrl->has_focus());
105
106
Control *other_ctrl = memnew(Control);
107
SceneTree::get_singleton()->get_root()->add_child(other_ctrl);
108
other_ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
109
other_ctrl->grab_focus();
110
111
CHECK_UNARY(other_ctrl->has_focus());
112
CHECK_UNARY_FALSE(ctrl->has_focus());
113
114
memdelete(other_ctrl);
115
}
116
117
SUBCASE("[SceneTree][Control] Hide control will cause the focus to be released") {
118
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
119
ctrl->grab_focus();
120
CHECK_UNARY(ctrl->has_focus());
121
122
ctrl->hide();
123
CHECK_UNARY_FALSE(ctrl->has_focus());
124
125
ctrl->show();
126
CHECK_UNARY_FALSE(ctrl->has_focus());
127
}
128
129
SUBCASE("[SceneTree][Control] The parent node is hidden causing the focus to be released") {
130
Control *child_ctrl = memnew(Control);
131
ctrl->add_child(child_ctrl);
132
133
child_ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
134
child_ctrl->grab_focus();
135
CHECK_UNARY(child_ctrl->has_focus());
136
137
ctrl->hide();
138
CHECK_UNARY_FALSE(child_ctrl->has_focus());
139
140
ctrl->show();
141
CHECK_UNARY_FALSE(child_ctrl->has_focus());
142
143
memdelete(child_ctrl);
144
}
145
146
SUBCASE("[SceneTree][Control] Grab focus with focus behavior recursive") {
147
CHECK_UNARY_FALSE(ctrl->has_focus());
148
149
// Cannot grab focus if focus behavior is disabled.
150
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
151
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_DISABLED);
152
153
ERR_PRINT_OFF
154
ctrl->grab_focus();
155
ERR_PRINT_ON
156
CHECK_UNARY_FALSE(ctrl->has_focus());
157
158
// Cannot grab focus if focus behavior is enabled but focus mode is none.
159
ctrl->set_focus_mode(Control::FocusMode::FOCUS_NONE);
160
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_ENABLED);
161
162
ERR_PRINT_OFF
163
ctrl->grab_focus();
164
ERR_PRINT_ON
165
CHECK_UNARY_FALSE(ctrl->has_focus());
166
167
// Can grab focus if focus behavior is enabled and focus mode is all.
168
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
169
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_ENABLED);
170
171
ctrl->grab_focus();
172
CHECK_UNARY(ctrl->has_focus());
173
}
174
175
SUBCASE("[SceneTree][Control] Children focus with focus behavior recursive") {
176
Control *child_control = memnew(Control);
177
ctrl->add_child(child_control);
178
179
// Can grab focus on child if parent focus behavior is inherit.
180
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
181
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_INHERITED);
182
child_control->set_focus_mode(Control::FocusMode::FOCUS_ALL);
183
child_control->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_INHERITED);
184
185
child_control->grab_focus();
186
CHECK_UNARY(child_control->has_focus());
187
188
// Cannot grab focus on child if parent focus behavior is disabled.
189
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
190
ctrl->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_DISABLED);
191
child_control->set_focus_mode(Control::FocusMode::FOCUS_ALL);
192
child_control->set_focus_behavior_recursive(Control::FOCUS_BEHAVIOR_INHERITED);
193
194
ERR_PRINT_OFF
195
child_control->grab_focus();
196
ERR_PRINT_ON
197
CHECK_UNARY_FALSE(child_control->has_focus());
198
199
memdelete(child_control);
200
}
201
202
memdelete(ctrl);
203
}
204
205
TEST_CASE("[SceneTree][Control] Find next/prev valid focus") {
206
Node *intermediate = memnew(Node);
207
Control *ctrl = memnew(Control);
208
intermediate->add_child(ctrl);
209
SceneTree::get_singleton()->get_root()->add_child(intermediate);
210
211
SUBCASE("[SceneTree][Control] In FOCUS_CLICK mode") {
212
ctrl->set_focus_mode(Control::FocusMode::FOCUS_CLICK);
213
ctrl->grab_focus();
214
REQUIRE_UNARY(ctrl->has_focus());
215
216
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
217
SEND_GUI_ACTION("ui_focus_next");
218
CHECK_UNARY(ctrl->has_focus());
219
}
220
221
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
222
SEND_GUI_ACTION("ui_focus_prev");
223
CHECK_UNARY(ctrl->has_focus());
224
}
225
226
SUBCASE("[SceneTree][Control] Has a sibling control and the parent is a window") {
227
Control *ctrl1 = memnew(Control);
228
Control *ctrl2 = memnew(Control);
229
Control *ctrl3 = memnew(Control);
230
Window *win = SceneTree::get_singleton()->get_root();
231
232
ctrl1->set_focus_mode(Control::FocusMode::FOCUS_ALL);
233
ctrl2->set_focus_mode(Control::FocusMode::FOCUS_ALL);
234
ctrl3->set_focus_mode(Control::FocusMode::FOCUS_ALL);
235
236
ctrl2->add_child(ctrl3);
237
win->add_child(ctrl1);
238
win->add_child(ctrl2);
239
240
SUBCASE("[SceneTree][Control] Focus Next") {
241
ctrl1->grab_focus();
242
CHECK_UNARY(ctrl1->has_focus());
243
244
SEND_GUI_ACTION("ui_focus_next");
245
CHECK_UNARY(ctrl2->has_focus());
246
247
SEND_GUI_ACTION("ui_focus_next");
248
CHECK_UNARY(ctrl3->has_focus());
249
250
SEND_GUI_ACTION("ui_focus_next");
251
CHECK_UNARY(ctrl1->has_focus());
252
}
253
254
SUBCASE("[SceneTree][Control] Focus Prev") {
255
ctrl1->grab_focus();
256
CHECK_UNARY(ctrl1->has_focus());
257
258
SEND_GUI_ACTION("ui_focus_prev");
259
CHECK_UNARY(ctrl3->has_focus());
260
261
SEND_GUI_ACTION("ui_focus_prev");
262
CHECK_UNARY(ctrl2->has_focus());
263
264
SEND_GUI_ACTION("ui_focus_prev");
265
CHECK_UNARY(ctrl1->has_focus());
266
}
267
268
memdelete(ctrl3);
269
memdelete(ctrl1);
270
memdelete(ctrl2);
271
}
272
273
SUBCASE("[SceneTree][Control] Has a sibling control but the parent node is not a control or window") {
274
Control *other_ctrl = memnew(Control);
275
intermediate->add_child(other_ctrl);
276
277
SUBCASE("[SceneTree][Control] Has a sibling control with FOCUS_ALL") {
278
other_ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
279
REQUIRE_EQ(other_ctrl->get_focus_mode(), Control::FocusMode::FOCUS_ALL);
280
281
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
282
SEND_GUI_ACTION("ui_focus_next");
283
CHECK_UNARY(ctrl->has_focus());
284
CHECK_UNARY_FALSE(other_ctrl->has_focus());
285
}
286
287
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
288
SEND_GUI_ACTION("ui_focus_prev");
289
CHECK_UNARY(ctrl->has_focus());
290
CHECK_UNARY_FALSE(other_ctrl->has_focus());
291
}
292
293
SUBCASE("[SceneTree][Control] Manually specify focus next") {
294
ctrl->set_focus_next(ctrl->get_path_to(other_ctrl));
295
296
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
297
SEND_GUI_ACTION("ui_focus_next");
298
CHECK_UNARY_FALSE(ctrl->has_focus());
299
CHECK_UNARY(other_ctrl->has_focus());
300
}
301
302
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
303
SEND_GUI_ACTION("ui_focus_prev");
304
CHECK_UNARY(ctrl->has_focus());
305
CHECK_UNARY_FALSE(other_ctrl->has_focus());
306
}
307
308
SUBCASE("[SceneTree][Control] Manually specified focus next is hidden") {
309
other_ctrl->hide();
310
REQUIRE_UNARY_FALSE(other_ctrl->is_visible());
311
312
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
313
SEND_GUI_ACTION("ui_focus_next");
314
CHECK_UNARY(ctrl->has_focus());
315
CHECK_UNARY_FALSE(other_ctrl->has_focus());
316
}
317
318
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
319
SEND_GUI_ACTION("ui_focus_prev");
320
CHECK_UNARY(ctrl->has_focus());
321
CHECK_UNARY_FALSE(other_ctrl->has_focus());
322
}
323
}
324
}
325
326
SUBCASE("[SceneTree][Control] Manually specify focus prev") {
327
ctrl->set_focus_previous(ctrl->get_path_to(other_ctrl));
328
329
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
330
SEND_GUI_ACTION("ui_focus_next");
331
CHECK_UNARY(ctrl->has_focus());
332
CHECK_UNARY_FALSE(other_ctrl->has_focus());
333
}
334
335
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
336
SEND_GUI_ACTION("ui_focus_prev");
337
CHECK_UNARY_FALSE(ctrl->has_focus());
338
CHECK_UNARY(other_ctrl->has_focus());
339
}
340
341
SUBCASE("[SceneTree][Control] Manually specified focus next is hidden") {
342
other_ctrl->hide();
343
REQUIRE_UNARY_FALSE(other_ctrl->is_visible());
344
345
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
346
SEND_GUI_ACTION("ui_focus_next");
347
CHECK_UNARY(ctrl->has_focus());
348
CHECK_UNARY_FALSE(other_ctrl->has_focus());
349
}
350
351
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
352
SEND_GUI_ACTION("ui_focus_prev");
353
CHECK_UNARY(ctrl->has_focus());
354
CHECK_UNARY_FALSE(other_ctrl->has_focus());
355
}
356
}
357
}
358
}
359
360
SUBCASE("[SceneTree][Control] Has a sibling control with FOCUS_CLICK") {
361
other_ctrl->set_focus_mode(Control::FocusMode::FOCUS_CLICK);
362
REQUIRE_EQ(other_ctrl->get_focus_mode(), Control::FocusMode::FOCUS_CLICK);
363
364
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
365
SEND_GUI_ACTION("ui_focus_next");
366
CHECK_UNARY(ctrl->has_focus());
367
CHECK_UNARY_FALSE(other_ctrl->has_focus());
368
}
369
370
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
371
SEND_GUI_ACTION("ui_focus_prev");
372
CHECK_UNARY(ctrl->has_focus());
373
CHECK_UNARY_FALSE(other_ctrl->has_focus());
374
}
375
376
SUBCASE("[SceneTree][Control] Manually specify focus next") {
377
ctrl->set_focus_next(ctrl->get_path_to(other_ctrl));
378
379
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
380
SEND_GUI_ACTION("ui_focus_next");
381
CHECK_UNARY_FALSE(ctrl->has_focus());
382
CHECK_UNARY(other_ctrl->has_focus());
383
}
384
385
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
386
SEND_GUI_ACTION("ui_focus_prev");
387
CHECK_UNARY(ctrl->has_focus());
388
CHECK_UNARY_FALSE(other_ctrl->has_focus());
389
}
390
}
391
392
SUBCASE("[SceneTree][Control] Manually specify focus prev") {
393
ctrl->set_focus_previous(ctrl->get_path_to(other_ctrl));
394
395
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
396
SEND_GUI_ACTION("ui_focus_next");
397
CHECK_UNARY(ctrl->has_focus());
398
CHECK_UNARY_FALSE(other_ctrl->has_focus());
399
}
400
401
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
402
SEND_GUI_ACTION("ui_focus_prev");
403
CHECK_UNARY_FALSE(ctrl->has_focus());
404
CHECK_UNARY(other_ctrl->has_focus());
405
}
406
}
407
}
408
409
SUBCASE("[SceneTree][Control] Has a sibling control with FOCUS_NONE") {
410
other_ctrl->set_focus_mode(Control::FocusMode::FOCUS_NONE);
411
REQUIRE_EQ(other_ctrl->get_focus_mode(), Control::FocusMode::FOCUS_NONE);
412
413
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
414
SEND_GUI_ACTION("ui_focus_next");
415
CHECK_UNARY(ctrl->has_focus());
416
CHECK_UNARY_FALSE(other_ctrl->has_focus());
417
}
418
419
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
420
SEND_GUI_ACTION("ui_focus_prev");
421
CHECK_UNARY(ctrl->has_focus());
422
CHECK_UNARY_FALSE(other_ctrl->has_focus());
423
}
424
425
SUBCASE("[SceneTree][Control] Manually specify focus next") {
426
ctrl->set_focus_next(ctrl->get_path_to(other_ctrl));
427
428
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
429
SEND_GUI_ACTION("ui_focus_next");
430
CHECK_UNARY(ctrl->has_focus());
431
CHECK_UNARY_FALSE(other_ctrl->has_focus());
432
}
433
434
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
435
SEND_GUI_ACTION("ui_focus_prev");
436
CHECK_UNARY(ctrl->has_focus());
437
CHECK_UNARY_FALSE(other_ctrl->has_focus());
438
}
439
}
440
441
SUBCASE("[SceneTree][Control] Manually specify focus prev") {
442
ctrl->set_focus_previous(ctrl->get_path_to(other_ctrl));
443
444
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
445
SEND_GUI_ACTION("ui_focus_next");
446
CHECK_UNARY(ctrl->has_focus());
447
CHECK_UNARY_FALSE(other_ctrl->has_focus());
448
}
449
450
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
451
SEND_GUI_ACTION("ui_focus_prev");
452
CHECK_UNARY(ctrl->has_focus());
453
CHECK_UNARY_FALSE(other_ctrl->has_focus());
454
}
455
}
456
}
457
458
memdelete(other_ctrl);
459
}
460
}
461
462
SUBCASE("[SceneTree][Control] In FOCUS_ALL mode") {
463
ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
464
REQUIRE_EQ(ctrl->get_focus_mode(), Control::FocusMode::FOCUS_ALL);
465
466
ctrl->grab_focus();
467
REQUIRE_UNARY(ctrl->has_focus());
468
469
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
470
SEND_GUI_ACTION("ui_focus_next");
471
CHECK_UNARY(ctrl->has_focus());
472
}
473
474
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
475
SEND_GUI_ACTION("ui_focus_prev");
476
CHECK_UNARY(ctrl->has_focus());
477
}
478
479
SUBCASE("[SceneTree][Control] Has a sibling control but the parent node is not a control") {
480
Control *other_ctrl = memnew(Control);
481
SceneTree::get_singleton()->get_root()->add_child(other_ctrl);
482
483
SUBCASE("[SceneTree][Control] Has a sibling control with FOCUS_ALL") {
484
other_ctrl->set_focus_mode(Control::FocusMode::FOCUS_ALL);
485
REQUIRE_EQ(other_ctrl->get_focus_mode(), Control::FocusMode::FOCUS_ALL);
486
487
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
488
SEND_GUI_ACTION("ui_focus_next");
489
CHECK_UNARY(ctrl->has_focus());
490
CHECK_UNARY_FALSE(other_ctrl->has_focus());
491
}
492
493
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
494
SEND_GUI_ACTION("ui_focus_prev");
495
CHECK_UNARY(ctrl->has_focus());
496
CHECK_UNARY_FALSE(other_ctrl->has_focus());
497
}
498
499
SUBCASE("[SceneTree][Control] Manually specify focus next") {
500
ctrl->set_focus_next(ctrl->get_path_to(other_ctrl));
501
502
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
503
SEND_GUI_ACTION("ui_focus_next");
504
CHECK_UNARY_FALSE(ctrl->has_focus());
505
CHECK_UNARY(other_ctrl->has_focus());
506
}
507
508
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
509
SEND_GUI_ACTION("ui_focus_prev");
510
CHECK_UNARY(ctrl->has_focus());
511
CHECK_UNARY_FALSE(other_ctrl->has_focus());
512
}
513
514
SUBCASE("[SceneTree][Control] Manually specified focus next is hidden") {
515
other_ctrl->hide();
516
REQUIRE_UNARY_FALSE(other_ctrl->is_visible());
517
518
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
519
SEND_GUI_ACTION("ui_focus_next");
520
CHECK_UNARY(ctrl->has_focus());
521
CHECK_UNARY_FALSE(other_ctrl->has_focus());
522
}
523
524
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
525
SEND_GUI_ACTION("ui_focus_prev");
526
CHECK_UNARY(ctrl->has_focus());
527
CHECK_UNARY_FALSE(other_ctrl->has_focus());
528
}
529
}
530
}
531
532
SUBCASE("[SceneTree][Control] Manually specify focus prev") {
533
ctrl->set_focus_previous(ctrl->get_path_to(other_ctrl));
534
535
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
536
SEND_GUI_ACTION("ui_focus_next");
537
CHECK_UNARY(ctrl->has_focus());
538
CHECK_UNARY_FALSE(other_ctrl->has_focus());
539
}
540
541
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
542
SEND_GUI_ACTION("ui_focus_prev");
543
CHECK_UNARY_FALSE(ctrl->has_focus());
544
CHECK_UNARY(other_ctrl->has_focus());
545
}
546
547
SUBCASE("[SceneTree][Control] Manually specified focus next is hidden") {
548
other_ctrl->hide();
549
REQUIRE_UNARY_FALSE(other_ctrl->is_visible());
550
551
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
552
SEND_GUI_ACTION("ui_focus_next");
553
CHECK_UNARY(ctrl->has_focus());
554
CHECK_UNARY_FALSE(other_ctrl->has_focus());
555
}
556
557
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
558
SEND_GUI_ACTION("ui_focus_prev");
559
CHECK_UNARY(ctrl->has_focus());
560
CHECK_UNARY_FALSE(other_ctrl->has_focus());
561
}
562
}
563
}
564
}
565
566
SUBCASE("[SceneTree][Control] Has a sibling control with FOCUS_CLICK") {
567
other_ctrl->set_focus_mode(Control::FocusMode::FOCUS_CLICK);
568
REQUIRE_EQ(other_ctrl->get_focus_mode(), Control::FocusMode::FOCUS_CLICK);
569
570
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
571
SEND_GUI_ACTION("ui_focus_next");
572
CHECK_UNARY(ctrl->has_focus());
573
CHECK_UNARY_FALSE(other_ctrl->has_focus());
574
}
575
576
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
577
SEND_GUI_ACTION("ui_focus_prev");
578
CHECK_UNARY(ctrl->has_focus());
579
CHECK_UNARY_FALSE(other_ctrl->has_focus());
580
}
581
582
SUBCASE("[SceneTree][Control] Manually specify focus next") {
583
ctrl->set_focus_next(ctrl->get_path_to(other_ctrl));
584
585
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
586
SEND_GUI_ACTION("ui_focus_next");
587
CHECK_UNARY_FALSE(ctrl->has_focus());
588
CHECK_UNARY(other_ctrl->has_focus());
589
}
590
591
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
592
SEND_GUI_ACTION("ui_focus_prev");
593
CHECK_UNARY(ctrl->has_focus());
594
CHECK_UNARY_FALSE(other_ctrl->has_focus());
595
}
596
}
597
598
SUBCASE("[SceneTree][Control] Manually specify focus prev") {
599
ctrl->set_focus_previous(ctrl->get_path_to(other_ctrl));
600
601
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
602
SEND_GUI_ACTION("ui_focus_next");
603
CHECK_UNARY(ctrl->has_focus());
604
CHECK_UNARY_FALSE(other_ctrl->has_focus());
605
}
606
607
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
608
SEND_GUI_ACTION("ui_focus_prev");
609
CHECK_UNARY_FALSE(ctrl->has_focus());
610
CHECK_UNARY(other_ctrl->has_focus());
611
}
612
}
613
}
614
615
SUBCASE("[SceneTree][Control] Has a sibling control with FOCUS_NONE") {
616
other_ctrl->set_focus_mode(Control::FocusMode::FOCUS_NONE);
617
REQUIRE_EQ(other_ctrl->get_focus_mode(), Control::FocusMode::FOCUS_NONE);
618
619
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
620
SEND_GUI_ACTION("ui_focus_next");
621
CHECK_UNARY(ctrl->has_focus());
622
CHECK_UNARY_FALSE(other_ctrl->has_focus());
623
}
624
625
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
626
SEND_GUI_ACTION("ui_focus_prev");
627
CHECK_UNARY(ctrl->has_focus());
628
CHECK_UNARY_FALSE(other_ctrl->has_focus());
629
}
630
631
SUBCASE("[SceneTree][Control] Manually specify focus next") {
632
ctrl->set_focus_next(ctrl->get_path_to(other_ctrl));
633
634
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
635
SEND_GUI_ACTION("ui_focus_next");
636
CHECK_UNARY(ctrl->has_focus());
637
CHECK_UNARY_FALSE(other_ctrl->has_focus());
638
}
639
640
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
641
SEND_GUI_ACTION("ui_focus_prev");
642
CHECK_UNARY(ctrl->has_focus());
643
CHECK_UNARY_FALSE(other_ctrl->has_focus());
644
}
645
}
646
647
SUBCASE("[SceneTree][Control] Manually specify focus prev") {
648
ctrl->set_focus_previous(ctrl->get_path_to(other_ctrl));
649
650
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
651
SEND_GUI_ACTION("ui_focus_next");
652
CHECK_UNARY(ctrl->has_focus());
653
CHECK_UNARY_FALSE(other_ctrl->has_focus());
654
}
655
656
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
657
SEND_GUI_ACTION("ui_focus_prev");
658
CHECK_UNARY(ctrl->has_focus());
659
CHECK_UNARY_FALSE(other_ctrl->has_focus());
660
}
661
}
662
}
663
664
memdelete(other_ctrl);
665
}
666
667
SUBCASE("[SceneTree][Control] Simple control tree") {
668
Control *ctrl_0 = memnew(Control);
669
Control *ctrl_1 = memnew(Control);
670
Node2D *node_2d_2 = memnew(Node2D);
671
672
ctrl->add_child(ctrl_0);
673
ctrl->add_child(ctrl_1);
674
ctrl->add_child(node_2d_2);
675
676
ctrl_0->set_focus_mode(Control::FocusMode::FOCUS_ALL);
677
ctrl_1->set_focus_mode(Control::FocusMode::FOCUS_ALL);
678
REQUIRE_EQ(ctrl_0->get_focus_mode(), Control::FocusMode::FOCUS_ALL);
679
REQUIRE_EQ(ctrl_1->get_focus_mode(), Control::FocusMode::FOCUS_ALL);
680
681
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
682
SEND_GUI_ACTION("ui_focus_next");
683
CHECK_UNARY(ctrl_0->has_focus());
684
685
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
686
SEND_GUI_ACTION("ui_focus_next");
687
CHECK_UNARY(ctrl_1->has_focus());
688
689
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
690
SEND_GUI_ACTION("ui_focus_next");
691
CHECK_UNARY(ctrl->has_focus());
692
}
693
}
694
}
695
696
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
697
SEND_GUI_ACTION("ui_focus_prev");
698
CHECK_UNARY(ctrl_1->has_focus());
699
700
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
701
SEND_GUI_ACTION("ui_focus_prev");
702
CHECK_UNARY(ctrl_0->has_focus());
703
704
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
705
SEND_GUI_ACTION("ui_focus_prev");
706
CHECK_UNARY(ctrl->has_focus());
707
}
708
}
709
}
710
711
SUBCASE("[SceneTree][Control] Skip next hidden control") {
712
ctrl_0->hide();
713
REQUIRE_UNARY_FALSE(ctrl_0->is_visible());
714
SEND_GUI_ACTION("ui_focus_next");
715
CHECK_UNARY_FALSE(ctrl_0->has_focus());
716
CHECK_UNARY(ctrl_1->has_focus());
717
}
718
719
SUBCASE("[SceneTree][Control] Skip next control with FOCUS_NONE") {
720
ctrl_0->set_focus_mode(Control::FocusMode::FOCUS_NONE);
721
REQUIRE_EQ(ctrl_0->get_focus_mode(), Control::FocusMode::FOCUS_NONE);
722
SEND_GUI_ACTION("ui_focus_next");
723
CHECK_UNARY_FALSE(ctrl_0->has_focus());
724
CHECK_UNARY(ctrl_1->has_focus());
725
}
726
727
SUBCASE("[SceneTree][Control] Skip next control with FOCUS_CLICK") {
728
ctrl_0->set_focus_mode(Control::FocusMode::FOCUS_CLICK);
729
REQUIRE_EQ(ctrl_0->get_focus_mode(), Control::FocusMode::FOCUS_CLICK);
730
SEND_GUI_ACTION("ui_focus_next");
731
CHECK_UNARY_FALSE(ctrl_0->has_focus());
732
CHECK_UNARY(ctrl_1->has_focus());
733
}
734
735
SUBCASE("[SceneTree][Control] Skip next top level control") {
736
ctrl_0->set_as_top_level(true);
737
REQUIRE_UNARY(ctrl_0->is_set_as_top_level());
738
SEND_GUI_ACTION("ui_focus_next");
739
CHECK_UNARY_FALSE(ctrl_0->has_focus());
740
CHECK_UNARY(ctrl_1->has_focus());
741
}
742
743
SUBCASE("[SceneTree][Control] Skip prev hidden control") {
744
ctrl_1->hide();
745
REQUIRE_UNARY_FALSE(ctrl_1->is_visible());
746
SEND_GUI_ACTION("ui_focus_prev");
747
CHECK_UNARY_FALSE(ctrl_1->has_focus());
748
CHECK_UNARY(ctrl_0->has_focus());
749
}
750
751
SUBCASE("[SceneTree][Control] Skip prev control with FOCUS_NONE") {
752
ctrl_1->set_focus_mode(Control::FocusMode::FOCUS_NONE);
753
REQUIRE_EQ(ctrl_1->get_focus_mode(), Control::FocusMode::FOCUS_NONE);
754
SEND_GUI_ACTION("ui_focus_prev");
755
CHECK_UNARY_FALSE(ctrl_1->has_focus());
756
CHECK_UNARY(ctrl_0->has_focus());
757
}
758
759
SUBCASE("[SceneTree][Control] Skip prev control with FOCUS_CLICK") {
760
ctrl_1->set_focus_mode(Control::FocusMode::FOCUS_CLICK);
761
REQUIRE_EQ(ctrl_1->get_focus_mode(), Control::FocusMode::FOCUS_CLICK);
762
SEND_GUI_ACTION("ui_focus_prev");
763
CHECK_UNARY_FALSE(ctrl_1->has_focus());
764
CHECK_UNARY(ctrl_0->has_focus());
765
}
766
767
SUBCASE("[SceneTree][Control] Skip prev top level control") {
768
ctrl_1->set_as_top_level(true);
769
REQUIRE_UNARY(ctrl_1->is_set_as_top_level());
770
SEND_GUI_ACTION("ui_focus_prev");
771
CHECK_UNARY_FALSE(ctrl_1->has_focus());
772
CHECK_UNARY(ctrl_0->has_focus());
773
}
774
775
SUBCASE("[SceneTree][Control] Add more node controls") {
776
Control *ctrl_0_0 = memnew(Control);
777
Control *ctrl_0_1 = memnew(Control);
778
Control *ctrl_0_2 = memnew(Control);
779
ctrl_0->add_child(ctrl_0_0);
780
ctrl_0->add_child(ctrl_0_1);
781
ctrl_0->add_child(ctrl_0_2);
782
ctrl_0_0->set_focus_mode(Control::FocusMode::FOCUS_ALL);
783
ctrl_0_1->set_focus_mode(Control::FocusMode::FOCUS_ALL);
784
ctrl_0_2->set_focus_mode(Control::FocusMode::FOCUS_ALL);
785
786
Control *ctrl_1_0 = memnew(Control);
787
Control *ctrl_1_1 = memnew(Control);
788
Control *ctrl_1_2 = memnew(Control);
789
ctrl_1->add_child(ctrl_1_0);
790
ctrl_1->add_child(ctrl_1_1);
791
ctrl_1->add_child(ctrl_1_2);
792
ctrl_1_0->set_focus_mode(Control::FocusMode::FOCUS_ALL);
793
ctrl_1_1->set_focus_mode(Control::FocusMode::FOCUS_ALL);
794
ctrl_1_2->set_focus_mode(Control::FocusMode::FOCUS_ALL);
795
796
Control *ctrl_2_0 = memnew(Control);
797
Control *ctrl_2_1 = memnew(Control);
798
Control *ctrl_2_2 = memnew(Control);
799
node_2d_2->add_child(ctrl_2_0);
800
node_2d_2->add_child(ctrl_2_1);
801
node_2d_2->add_child(ctrl_2_2);
802
ctrl_2_0->set_focus_mode(Control::FocusMode::FOCUS_ALL);
803
ctrl_2_1->set_focus_mode(Control::FocusMode::FOCUS_ALL);
804
ctrl_2_2->set_focus_mode(Control::FocusMode::FOCUS_ALL);
805
806
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
807
SEND_GUI_ACTION("ui_focus_next");
808
CHECK_UNARY(ctrl_0->has_focus());
809
810
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
811
SEND_GUI_ACTION("ui_focus_next");
812
CHECK_UNARY(ctrl_0_0->has_focus());
813
}
814
815
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
816
SEND_GUI_ACTION("ui_focus_prev");
817
CHECK_UNARY(ctrl->has_focus());
818
}
819
}
820
821
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
822
SEND_GUI_ACTION("ui_focus_prev");
823
CHECK_UNARY(ctrl_1_2->has_focus());
824
}
825
826
SUBCASE("[SceneTree][Control] Exist top level tree") {
827
ctrl_0->set_as_top_level(true);
828
REQUIRE_UNARY(ctrl_0->is_set_as_top_level());
829
830
SUBCASE("[SceneTree][Control] Outside top level tree") {
831
ctrl->grab_focus();
832
REQUIRE_UNARY(ctrl->has_focus());
833
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
834
SEND_GUI_ACTION("ui_focus_next");
835
CHECK_UNARY(ctrl_1->has_focus());
836
837
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
838
SEND_GUI_ACTION("ui_focus_prev");
839
CHECK_UNARY(ctrl->has_focus());
840
}
841
}
842
}
843
844
SUBCASE("[SceneTree][Control] Inside top level tree") {
845
ctrl_0->grab_focus();
846
REQUIRE_UNARY(ctrl_0->has_focus());
847
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
848
SEND_GUI_ACTION("ui_focus_next");
849
CHECK_UNARY(ctrl_0_0->has_focus());
850
851
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
852
SEND_GUI_ACTION("ui_focus_prev");
853
CHECK_UNARY(ctrl_0->has_focus());
854
}
855
}
856
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
857
SEND_GUI_ACTION("ui_focus_prev");
858
CHECK_UNARY(ctrl_0_2->has_focus());
859
860
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
861
SEND_GUI_ACTION("ui_focus_next");
862
CHECK_UNARY(ctrl_0->has_focus());
863
}
864
}
865
}
866
867
SUBCASE("[SceneTree][Control] Manually specified focus next") {
868
ctrl->set_focus_next(ctrl->get_path_to(ctrl_2_1));
869
ctrl_2_1->set_focus_next(ctrl_2_1->get_path_to(ctrl_1_0));
870
ctrl_1_0->set_focus_next(ctrl_1_0->get_path_to(ctrl_0));
871
ctrl_0->set_focus_next(ctrl_0->get_path_to(ctrl));
872
873
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
874
SEND_GUI_ACTION("ui_focus_next");
875
CHECK_UNARY(ctrl_2_1->has_focus());
876
877
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
878
SEND_GUI_ACTION("ui_focus_next");
879
CHECK_UNARY(ctrl_1_0->has_focus());
880
881
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
882
SEND_GUI_ACTION("ui_focus_next");
883
CHECK_UNARY(ctrl_0->has_focus());
884
885
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
886
SEND_GUI_ACTION("ui_focus_next");
887
CHECK_UNARY(ctrl->has_focus());
888
}
889
890
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
891
SEND_GUI_ACTION("ui_focus_prev");
892
CHECK_UNARY(ctrl_0_2->has_focus());
893
}
894
}
895
896
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
897
SEND_GUI_ACTION("ui_focus_prev");
898
CHECK_UNARY(ctrl_1->has_focus());
899
}
900
}
901
902
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
903
SEND_GUI_ACTION("ui_focus_prev");
904
CHECK_UNARY(ctrl_2_1->has_focus());
905
}
906
}
907
908
SUBCASE("[SceneTree][Control] The parent node is not visible") {
909
node_2d_2->hide();
910
REQUIRE_UNARY(ctrl_2_1->is_visible());
911
REQUIRE_UNARY_FALSE(ctrl_2_1->is_visible_in_tree());
912
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
913
SEND_GUI_ACTION("ui_focus_next");
914
CHECK_UNARY_FALSE(ctrl->has_focus());
915
CHECK_UNARY_FALSE(ctrl_2_1->has_focus());
916
CHECK_UNARY_FALSE(ctrl_0->has_focus());
917
CHECK_UNARY(ctrl_1->has_focus());
918
}
919
}
920
}
921
922
SUBCASE("[SceneTree][Control] Manually specified focus prev") {
923
ctrl->set_focus_previous(ctrl->get_path_to(ctrl_0_2));
924
ctrl_0_2->set_focus_previous(ctrl_0_2->get_path_to(ctrl_1_1));
925
ctrl_1_1->set_focus_previous(ctrl_1_1->get_path_to(ctrl_2_0));
926
ctrl_2_0->set_focus_previous(ctrl_2_0->get_path_to(ctrl));
927
928
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
929
SEND_GUI_ACTION("ui_focus_prev");
930
CHECK_UNARY(ctrl_0_2->has_focus());
931
932
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
933
SEND_GUI_ACTION("ui_focus_prev");
934
CHECK_UNARY(ctrl_1_1->has_focus());
935
936
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
937
SEND_GUI_ACTION("ui_focus_prev");
938
CHECK_UNARY(ctrl_2_0->has_focus());
939
940
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
941
SEND_GUI_ACTION("ui_focus_prev");
942
CHECK_UNARY(ctrl->has_focus());
943
}
944
945
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
946
SEND_GUI_ACTION("ui_focus_next");
947
CHECK_UNARY(ctrl_2_0->has_focus());
948
}
949
}
950
951
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
952
SEND_GUI_ACTION("ui_focus_next");
953
CHECK_UNARY(ctrl_1_2->has_focus());
954
}
955
}
956
957
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
958
SEND_GUI_ACTION("ui_focus_next");
959
CHECK_UNARY(ctrl_0->has_focus());
960
}
961
}
962
963
SUBCASE("[SceneTree][Control] The parent node is not visible") {
964
ctrl_0->hide();
965
REQUIRE_UNARY(ctrl_0_2->is_visible());
966
REQUIRE_UNARY_FALSE(ctrl_0_2->is_visible_in_tree());
967
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
968
SEND_GUI_ACTION("ui_focus_prev");
969
CHECK_UNARY_FALSE(ctrl->has_focus());
970
CHECK_UNARY_FALSE(ctrl_0_2->has_focus());
971
CHECK_UNARY(ctrl_1_2->has_focus());
972
}
973
}
974
}
975
}
976
977
SUBCASE("[SceneTree][Control] Exist hidden control tree") {
978
ctrl_0->hide();
979
REQUIRE_UNARY_FALSE(ctrl_0->is_visible());
980
981
SUBCASE("[SceneTree][Control] Simulate ui_focus_next action") {
982
SEND_GUI_ACTION("ui_focus_next");
983
CHECK_UNARY(ctrl_1->has_focus());
984
985
SUBCASE("[SceneTree][Control] Simulate ui_focus_prev action") {
986
SEND_GUI_ACTION("ui_focus_prev");
987
CHECK_UNARY(ctrl->has_focus());
988
}
989
}
990
}
991
992
memdelete(ctrl_2_2);
993
memdelete(ctrl_2_1);
994
memdelete(ctrl_2_0);
995
memdelete(ctrl_1_2);
996
memdelete(ctrl_1_1);
997
memdelete(ctrl_1_0);
998
memdelete(ctrl_0_2);
999
memdelete(ctrl_0_1);
1000
memdelete(ctrl_0_0);
1001
}
1002
1003
memdelete(node_2d_2);
1004
memdelete(ctrl_1);
1005
memdelete(ctrl_0);
1006
}
1007
}
1008
1009
memdelete(ctrl);
1010
memdelete(intermediate);
1011
}
1012
1013
TEST_CASE("[SceneTree][Control] Anchoring") {
1014
Control *test_control = memnew(Control);
1015
Control *test_child = memnew(Control);
1016
test_control->add_child(test_child);
1017
test_control->set_size(Size2(2, 2));
1018
Window *root = SceneTree::get_singleton()->get_root();
1019
root->add_child(test_control);
1020
1021
SUBCASE("Anchoring without offsets") {
1022
test_child->set_anchor(SIDE_RIGHT, 0.75);
1023
test_child->set_anchor(SIDE_BOTTOM, 0.1);
1024
CHECK_MESSAGE(
1025
test_child->get_size().is_equal_approx(Vector2(1.5, 0.2)),
1026
"With no LEFT or TOP anchors, positive RIGHT and BOTTOM anchors should be proportional to the size.");
1027
CHECK_MESSAGE(
1028
test_child->get_position().is_equal_approx(Vector2(0, 0)),
1029
"With positive RIGHT and BOTTOM anchors set and no LEFT or TOP anchors, the position should not change.");
1030
1031
test_child->set_anchor(SIDE_LEFT, 0.5);
1032
test_child->set_anchor(SIDE_TOP, 0.01);
1033
CHECK_MESSAGE(
1034
test_child->get_size().is_equal_approx(Vector2(0.5, 0.18)),
1035
"With all anchors set, the size should fit between all four anchors.");
1036
CHECK_MESSAGE(
1037
test_child->get_position().is_equal_approx(Vector2(1, 0.02)),
1038
"With all anchors set, the LEFT and TOP anchors should proportional to the position.");
1039
}
1040
1041
SUBCASE("Anchoring with offsets") {
1042
test_child->set_offset(SIDE_RIGHT, 0.33);
1043
test_child->set_offset(SIDE_BOTTOM, 0.2);
1044
CHECK_MESSAGE(
1045
test_child->get_size().is_equal_approx(Vector2(0.33, 0.2)),
1046
"With no anchors or LEFT or TOP offsets set, the RIGHT and BOTTOM offsets should be equal to size.");
1047
CHECK_MESSAGE(
1048
test_child->get_position().is_equal_approx(Vector2(0, 0)),
1049
"With only positive RIGHT and BOTTOM offsets set, the position should not change.");
1050
1051
test_child->set_offset(SIDE_LEFT, 0.1);
1052
test_child->set_offset(SIDE_TOP, 0.05);
1053
CHECK_MESSAGE(
1054
test_child->get_size().is_equal_approx(Vector2(0.23, 0.15)),
1055
"With no anchors set, the size should fit between all four offsets.");
1056
CHECK_MESSAGE(
1057
test_child->get_position().is_equal_approx(Vector2(0.1, 0.05)),
1058
"With no anchors set, the LEFT and TOP offsets should be equal to the position.");
1059
1060
test_child->set_anchor(SIDE_RIGHT, 0.5);
1061
test_child->set_anchor(SIDE_BOTTOM, 0.3);
1062
test_child->set_anchor(SIDE_LEFT, 0.2);
1063
test_child->set_anchor(SIDE_TOP, 0.1);
1064
CHECK_MESSAGE(
1065
test_child->get_size().is_equal_approx(Vector2(0.83, 0.55)),
1066
"Anchors adjust size first then it is affected by offsets.");
1067
CHECK_MESSAGE(
1068
test_child->get_position().is_equal_approx(Vector2(0.5, 0.25)),
1069
"Anchors adjust positions first then it is affected by offsets.");
1070
1071
test_child->set_offset(SIDE_RIGHT, -0.1);
1072
test_child->set_offset(SIDE_BOTTOM, -0.01);
1073
test_child->set_offset(SIDE_LEFT, -0.33);
1074
test_child->set_offset(SIDE_TOP, -0.16);
1075
CHECK_MESSAGE(
1076
test_child->get_size().is_equal_approx(Vector2(0.83, 0.55)),
1077
"Keeping offset distance equal when changing offsets, keeps size equal.");
1078
CHECK_MESSAGE(
1079
test_child->get_position().is_equal_approx(Vector2(0.07, 0.04)),
1080
"Negative offsets move position in top left direction.");
1081
}
1082
1083
SUBCASE("Anchoring is preserved on parent size changed") {
1084
test_child->set_offset(SIDE_RIGHT, -0.05);
1085
test_child->set_offset(SIDE_BOTTOM, 0.1);
1086
test_child->set_offset(SIDE_LEFT, 0.05);
1087
test_child->set_offset(SIDE_TOP, 0.1);
1088
test_child->set_anchor(SIDE_RIGHT, 0.3);
1089
test_child->set_anchor(SIDE_BOTTOM, 0.85);
1090
test_child->set_anchor(SIDE_LEFT, 0.2);
1091
test_child->set_anchor(SIDE_TOP, 0.55);
1092
CHECK(test_child->get_rect().is_equal_approx(
1093
Rect2(Vector2(0.45, 1.2), Size2(0.1, 0.6))));
1094
1095
test_control->set_size(Size2(4, 1));
1096
CHECK(test_child->get_rect().is_equal_approx(
1097
Rect2(Vector2(0.85, 0.65), Size2(0.3, 0.3))));
1098
}
1099
1100
memdelete(test_child);
1101
memdelete(test_control);
1102
}
1103
1104
TEST_CASE("[SceneTree][Control] Custom minimum size") {
1105
Control *test_control = memnew(Control);
1106
test_control->set_custom_minimum_size(Size2(4, 2));
1107
Window *root = SceneTree::get_singleton()->get_root();
1108
root->add_child(test_control);
1109
CHECK_MESSAGE(
1110
test_control->get_size().is_equal_approx(Vector2(4, 2)),
1111
"Size increases to match custom minimum size.");
1112
1113
test_control->set_size(Size2(5, 4));
1114
CHECK_MESSAGE(
1115
test_control->get_size().is_equal_approx(Vector2(5, 4)),
1116
"Size does not change if above custom minimum size.");
1117
1118
test_control->set_size(Size2(1, 1));
1119
CHECK_MESSAGE(
1120
test_control->get_size().is_equal_approx(Vector2(4, 2)),
1121
"Size matches minimum size if set below custom minimum size.");
1122
1123
test_control->set_size(Size2(3, 3));
1124
CHECK_MESSAGE(
1125
test_control->get_size().is_equal_approx(Vector2(4, 3)),
1126
"Adjusts only x axis size if x is below custom minimum size.");
1127
1128
test_control->set_size(Size2(10, 0.1));
1129
CHECK_MESSAGE(
1130
test_control->get_size().is_equal_approx(Vector2(10, 2)),
1131
"Adjusts only y axis size if y is below custom minimum size.");
1132
1133
memdelete(test_control);
1134
}
1135
1136
TEST_CASE("[SceneTree][Control] Grow direction") {
1137
Control *test_control = memnew(Control);
1138
test_control->set_size(Size2(1, 1));
1139
Window *root = SceneTree::get_singleton()->get_root();
1140
root->add_child(test_control);
1141
1142
SUBCASE("Defaults") {
1143
CHECK(test_control->get_h_grow_direction() == Control::GROW_DIRECTION_END);
1144
CHECK(test_control->get_v_grow_direction() == Control::GROW_DIRECTION_END);
1145
}
1146
1147
SIGNAL_WATCH(test_control, SNAME("minimum_size_changed"))
1148
Array signal_args = { {} };
1149
1150
SUBCASE("Horizontal grow direction begin") {
1151
test_control->set_h_grow_direction(Control::GROW_DIRECTION_BEGIN);
1152
test_control->set_custom_minimum_size(Size2(2, 2));
1153
SceneTree::get_singleton()->process(0);
1154
SIGNAL_CHECK("minimum_size_changed", signal_args)
1155
CHECK_MESSAGE(
1156
test_control->get_rect().is_equal_approx(
1157
Rect2(Vector2(-1, 0), Size2(2, 2))),
1158
"Expand leftwards.");
1159
}
1160
1161
SUBCASE("Vertical grow direction begin") {
1162
test_control->set_v_grow_direction(Control::GROW_DIRECTION_BEGIN);
1163
test_control->set_custom_minimum_size(Size2(4, 3));
1164
SceneTree::get_singleton()->process(0);
1165
SIGNAL_CHECK("minimum_size_changed", signal_args);
1166
CHECK_MESSAGE(
1167
test_control->get_rect().is_equal_approx(
1168
Rect2(Vector2(0, -2), Size2(4, 3))),
1169
"Expand upwards.");
1170
}
1171
1172
SUBCASE("Horizontal grow direction end") {
1173
test_control->set_h_grow_direction(Control::GROW_DIRECTION_END);
1174
test_control->set_custom_minimum_size(Size2(5, 3));
1175
SceneTree::get_singleton()->process(0);
1176
SIGNAL_CHECK("minimum_size_changed", signal_args);
1177
CHECK_MESSAGE(
1178
test_control->get_rect().is_equal_approx(
1179
Rect2(Vector2(0, 0), Size2(5, 3))),
1180
"Expand rightwards.");
1181
}
1182
1183
SUBCASE("Vertical grow direction end") {
1184
test_control->set_v_grow_direction(Control::GROW_DIRECTION_END);
1185
test_control->set_custom_minimum_size(Size2(4, 4));
1186
SceneTree::get_singleton()->process(0);
1187
SIGNAL_CHECK("minimum_size_changed", signal_args);
1188
CHECK_MESSAGE(
1189
test_control->get_rect().is_equal_approx(
1190
Rect2(Vector2(0, 0), Size2(4, 4))),
1191
"Expand downwards.");
1192
;
1193
}
1194
1195
SUBCASE("Horizontal grow direction both") {
1196
test_control->set_h_grow_direction(Control::GROW_DIRECTION_BOTH);
1197
test_control->set_custom_minimum_size(Size2(2, 4));
1198
SceneTree::get_singleton()->process(0);
1199
SIGNAL_CHECK("minimum_size_changed", signal_args);
1200
CHECK_MESSAGE(
1201
test_control->get_rect().is_equal_approx(
1202
Rect2(Vector2(-0.5, 0), Size2(2, 4))),
1203
"Expand equally leftwards and rightwards.");
1204
}
1205
1206
SUBCASE("Vertical grow direction both") {
1207
test_control->set_v_grow_direction(Control::GROW_DIRECTION_BOTH);
1208
test_control->set_custom_minimum_size(Size2(6, 3));
1209
SceneTree::get_singleton()->process(0);
1210
SIGNAL_CHECK("minimum_size_changed", signal_args);
1211
CHECK_MESSAGE(
1212
test_control->get_rect().is_equal_approx(
1213
Rect2(Vector2(0, -1), Size2(6, 3))),
1214
"Expand equally upwards and downwards.");
1215
}
1216
1217
memdelete(test_control);
1218
}
1219
1220
} // namespace TestControl
1221
1222