Add tests for Container nodes
This commit is contained in:
1 parent
ee713ccb7c
commit
039d474aa7
9 files changed
+2999
No files matched your search
@@ -0,0 +1,358 @@
|
||||
/**************************************************************************/
|
||||
/* test_aspect_ratio_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_aspect_ratio_container)
|
||||
|
||||
#include "scene/gui/aspect_ratio_container.h"
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
namespace TestAspectRatioContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][AspectRatioContainer] Default Properties") {
|
||||
AspectRatioContainer *aspect_ratio_container = memnew(AspectRatioContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(aspect_ratio_container);
|
||||
Control *child_control = memnew(Control);
|
||||
aspect_ratio_container->add_child(child_control);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
aspect_ratio_container->get_stretch_mode() == AspectRatioContainer::STRETCH_FIT,
|
||||
"AspectRatioContainer stretch mode is set to STRETCH_FIT by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(aspect_ratio_container->get_ratio(), 1.0f),
|
||||
"AspectRatioContainer ratio is set to 1.0 by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is positioned at the top-left corner of the AspectRatioContainer by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_h_size_flags() == Control::SIZE_FILL,
|
||||
"Child control horizontal size flags are set to SIZE_FILL by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_v_size_flags() == Control::SIZE_FILL,
|
||||
"Child control vertical size flags are set to SIZE_FILL by default.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(aspect_ratio_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][AspectRatioContainer] Aspect Ratio") {
|
||||
AspectRatioContainer *aspect_ratio_container = memnew(AspectRatioContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(aspect_ratio_container);
|
||||
Control *child_control = memnew(Control);
|
||||
aspect_ratio_container->add_child(child_control);
|
||||
|
||||
aspect_ratio_container->set_size(Size2(200, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"Child control is resized to maintain aspect ratio when AspectRatioContainer is resized.");
|
||||
|
||||
aspect_ratio_container->set_size(Size2(100, 200));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"Child control is resized to maintain aspect ratio when AspectRatioContainer is resized.");
|
||||
|
||||
aspect_ratio_container->set_ratio(2.0f);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 50)),
|
||||
"Child control is resized to maintain aspect ratio when AspectRatioContainer ratio is changed.");
|
||||
|
||||
aspect_ratio_container->set_ratio(0.5f);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 200)),
|
||||
"Child control is resized to maintain aspect ratio when AspectRatioContainer ratio is changed.");
|
||||
|
||||
aspect_ratio_container->set_size(Size2(200, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(50, 100)),
|
||||
"Child control is resized to maintain aspect ratio when AspectRatioContainer is resized after ratio change.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(aspect_ratio_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][AspectRatioContainer] Stretch Modes") {
|
||||
AspectRatioContainer *aspect_ratio_container = memnew(AspectRatioContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(aspect_ratio_container);
|
||||
Control *child_control = memnew(Control);
|
||||
aspect_ratio_container->add_child(child_control);
|
||||
|
||||
aspect_ratio_container->set_size(Size2(200, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"Child control is resized to maintain aspect ratio in STRETCH_FIT mode.");
|
||||
|
||||
aspect_ratio_container->set_stretch_mode(AspectRatioContainer::STRETCH_WIDTH_CONTROLS_HEIGHT);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(200, 200)),
|
||||
"Child control height is adjusted to maintain aspect ratio in STRETCH_WIDTH_CONTROLS_HEIGHT mode.");
|
||||
|
||||
aspect_ratio_container->set_stretch_mode(AspectRatioContainer::STRETCH_HEIGHT_CONTROLS_WIDTH);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"Child control width is adjusted to maintain aspect ratio in STRETCH_HEIGHT_CONTROLS_WIDTH mode.");
|
||||
|
||||
aspect_ratio_container->set_stretch_mode(AspectRatioContainer::STRETCH_COVER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(200, 200)),
|
||||
"Child control is resized to cover the entire AspectRatioContainer in STRETCH_COVER mode.");
|
||||
|
||||
aspect_ratio_container->set_size(Size2(100, 200));
|
||||
aspect_ratio_container->set_stretch_mode(AspectRatioContainer::STRETCH_FIT);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
aspect_ratio_container->get_stretch_mode() == AspectRatioContainer::STRETCH_FIT,
|
||||
"AspectRatioContainer stretch mode is set to STRETCH_FIT by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"Child control is resized to maintain aspect ratio in STRETCH_FIT mode.");
|
||||
|
||||
aspect_ratio_container->set_stretch_mode(AspectRatioContainer::STRETCH_WIDTH_CONTROLS_HEIGHT);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"Child control height is adjusted to maintain aspect ratio in STRETCH_WIDTH_CONTROLS_HEIGHT mode.");
|
||||
|
||||
aspect_ratio_container->set_stretch_mode(AspectRatioContainer::STRETCH_HEIGHT_CONTROLS_WIDTH);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(200, 200)),
|
||||
"Child control width is adjusted to maintain aspect ratio in STRETCH_HEIGHT_CONTROLS_WIDTH mode.");
|
||||
|
||||
aspect_ratio_container->set_stretch_mode(AspectRatioContainer::STRETCH_COVER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(200, 200)),
|
||||
"Child control is resized to cover the entire AspectRatioContainer in STRETCH_COVER mode.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(aspect_ratio_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][AspectRatioContainer] Alignment modes") {
|
||||
AspectRatioContainer *aspect_ratio_container = memnew(AspectRatioContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(aspect_ratio_container);
|
||||
Control *child_control = memnew(Control);
|
||||
aspect_ratio_container->add_child(child_control);
|
||||
|
||||
SUBCASE("Horizontal Alignment") {
|
||||
aspect_ratio_container->set_size(Size2(200, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
aspect_ratio_container->get_alignment_horizontal() == AspectRatioContainer::ALIGNMENT_CENTER,
|
||||
"AspectRatioContainer horizontal alignment is set to ALIGNMENT_CENTER by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Child control is aligned to the center in ALIGNMENT_CENTER horizontal alignment mode.");
|
||||
|
||||
aspect_ratio_container->set_alignment_horizontal(AspectRatioContainer::ALIGNMENT_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left in ALIGNMENT_BEGIN horizontal alignment mode.");
|
||||
|
||||
aspect_ratio_container->set_alignment_horizontal(AspectRatioContainer::ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Child control is aligned to the right in ALIGNMENT_END horizontal alignment mode.");
|
||||
}
|
||||
|
||||
SUBCASE("Vertical Alignment") {
|
||||
aspect_ratio_container->set_size(Size2(100, 200));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
aspect_ratio_container->get_alignment_vertical() == AspectRatioContainer::ALIGNMENT_CENTER,
|
||||
"AspectRatioContainer vertical alignment is set to ALIGNMENT_CENTER by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"Child control is aligned to the center in ALIGNMENT_CENTER vertical alignment mode.");
|
||||
|
||||
aspect_ratio_container->set_alignment_vertical(AspectRatioContainer::ALIGNMENT_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top in ALIGNMENT_BEGIN vertical alignment mode.");
|
||||
|
||||
aspect_ratio_container->set_alignment_vertical(AspectRatioContainer::ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 100)),
|
||||
"Child control is aligned to the bottom in ALIGNMENT_END vertical alignment mode.");
|
||||
}
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(aspect_ratio_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][AspectRatioContainer] Container Sizing Flags") {
|
||||
AspectRatioContainer *aspect_ratio_container = memnew(AspectRatioContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(aspect_ratio_container);
|
||||
Control *child_control = memnew(Control);
|
||||
aspect_ratio_container->add_child(child_control);
|
||||
|
||||
SUBCASE("Horizontal Flags") {
|
||||
aspect_ratio_container->set_size(Size2(200, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Child control is vertically centered by default with SIZE_FILL.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Child control is aligned to the left of its would-be area with SIZE_FILL in SIZE_SHRINK_BEGIN horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Child control is centered in its would-be area with SIZE_FILL in SIZE_SHRINK_CENTER horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(150, 0)),
|
||||
"Child control is aligned to the right of its would-be area with SIZE_FILL in SIZE_SHRINK_END horizontal size flag mode.");
|
||||
}
|
||||
|
||||
SUBCASE("Horizontal Flags RTL") {
|
||||
aspect_ratio_container->set_size(Size2(200, 100));
|
||||
aspect_ratio_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Child control is vertically centered by default with SIZE_FILL.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(150, 0)),
|
||||
"Child control is aligned to the right of its would-be area with SIZE_FILL in RTL SIZE_SHRINK_BEGIN horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Child control is centered in its would-be area with SIZE_FILL in SIZE_SHRINK_CENTER horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Child control is aligned to the left of its would-be area with SIZE_FILL in RTL SIZE_SHRINK_END horizontal size flag mode.");
|
||||
}
|
||||
|
||||
SUBCASE("Vertical Flags") {
|
||||
aspect_ratio_container->set_size(Size2(100, 200));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"Child control is horizontally centered by default with SIZE_FILL.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"Child control is aligned to the top of its would-be area with SIZE_FILL in SIZE_SHRINK_BEGIN vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 100)),
|
||||
"Child control is centered in its would-be area with SIZE_FILL in SIZE_SHRINK_CENTER vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 150)),
|
||||
"Child control is aligned to the bottom of its would-be area with SIZE_FILL in SIZE_SHRINK_END vertical size flag mode.");
|
||||
}
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(aspect_ratio_container);
|
||||
}
|
||||
|
||||
} // namespace TestAspectRatioContainer
|
||||
@@ -0,0 +1,625 @@
|
||||
/**************************************************************************/
|
||||
/* test_box_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_box_container)
|
||||
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
namespace TestBoxContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][BoxContainer] HBoxContainer") {
|
||||
HBoxContainer *hbox_container = memnew(HBoxContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(hbox_container);
|
||||
|
||||
hbox_container->set_size(Size2(100, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
SUBCASE("Default behavior") {
|
||||
Control *child_control = memnew(Control);
|
||||
hbox_container->add_child(child_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
hbox_container->get_alignment() == BoxContainer::ALIGNMENT_BEGIN,
|
||||
"HBoxContainer alignment is set to ALIGNMENT_BEGIN by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!hbox_container->is_vertical(),
|
||||
"HBoxContainer orientation is horizontal.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left in ALIGNMENT_BEGIN mode.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_h_size_flags() == Control::SIZE_FILL,
|
||||
"Child control horizontal size flags are set to SIZE_FILL by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_v_size_flags() == Control::SIZE_FILL,
|
||||
"Child control vertical size flags are set to SIZE_FILL by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(0, 100)),
|
||||
"Child control takes up minimum horizontal space and matches container height by default.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Horizontal Size Flags") {
|
||||
Control *child_control = memnew(Control);
|
||||
hbox_container->add_child(child_control);
|
||||
child_control->set_custom_minimum_size(Size2(20, 20));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left by default with SIZE_FILL.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left of in SIZE_SHRINK_BEGIN horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left of in SIZE_SHRINK_CENTER horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left of in SIZE_SHRINK_END horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left in SIZE_EXPAND | SIZE_SHRINK_BEGIN horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(40, 0)),
|
||||
"Child control is aligned to the center in SIZE_EXPAND | SIZE_SHRINK_CENTER horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(80, 0)),
|
||||
"Child control is aligned to the right in SIZE_EXPAND | SIZE_SHRINK_END horizontal size flag mode.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Vertical Size Flags") {
|
||||
Control *child_control = memnew(Control);
|
||||
hbox_container->add_child(child_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top by default with SIZE_FILL.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top of in SIZE_SHRINK_BEGIN vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"Child control is aligned to the center of in SIZE_SHRINK_CENTER vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 100)),
|
||||
"Child control is aligned to the bottom of in SIZE_SHRINK_END vertical size flag mode.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Alignment") {
|
||||
Control *child_control = memnew(Control);
|
||||
hbox_container->add_child(child_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left in ALIGNMENT_BEGIN mode by default.");
|
||||
|
||||
hbox_container->set_alignment(BoxContainer::ALIGNMENT_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Child control is aligned to the center in ALIGNMENT_CENTER mode.");
|
||||
|
||||
hbox_container->set_alignment(BoxContainer::ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Child control is aligned to the right in ALIGNMENT_END mode.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Alignment RTL") {
|
||||
Control *child_control = memnew(Control);
|
||||
hbox_container->add_child(child_control);
|
||||
hbox_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Child control is aligned to the right in RTL ALIGNMENT_BEGIN mode by default.");
|
||||
|
||||
hbox_container->set_alignment(BoxContainer::ALIGNMENT_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Child control is aligned to the center in RTL ALIGNMENT_CENTER mode.");
|
||||
|
||||
hbox_container->set_alignment(BoxContainer::ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the right in RTL ALIGNMENT_END mode.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Separation") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
hbox_container->add_child(child_control_1);
|
||||
hbox_container->add_child(child_control_2);
|
||||
|
||||
hbox_container->add_theme_constant_override("separation", 10);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(10, 0)),
|
||||
"Child controls are separated by the specified separation value.");
|
||||
|
||||
memdelete(child_control_1);
|
||||
memdelete(child_control_2);
|
||||
}
|
||||
|
||||
SUBCASE("Spacers") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
hbox_container->add_child(child_control_1);
|
||||
hbox_container->add_spacer();
|
||||
hbox_container->add_child(child_control_2);
|
||||
hbox_container->add_theme_constant_override("separation", 0);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Spacer pushes child controls apart.");
|
||||
|
||||
memdelete(child_control_1);
|
||||
memdelete(child_control_2);
|
||||
}
|
||||
|
||||
SUBCASE("Expanding children") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
hbox_container->add_child(child_control_1);
|
||||
hbox_container->add_child(child_control_2);
|
||||
hbox_container->add_theme_constant_override("separation", 0);
|
||||
|
||||
child_control_1->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"One child control expands to fill available space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(0, 100)),
|
||||
"The non-expanding child control remains at minimum size.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Expanding child control is aligned to the left.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Non-expanding child control is positioned after the expanding child control.");
|
||||
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 0));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(80, 100)),
|
||||
"Expanding child control shrinks to accommodate the custom minimum size of the other child.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(20, 100)),
|
||||
"The non-expanding child control respects its custom minimum size.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Expanding child control is aligned to the left.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(80, 0)),
|
||||
"Non-expanding child control is positioned after the expanding child control.");
|
||||
|
||||
child_control_2->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(50, 100)),
|
||||
"Both child controls expand equally to fill available space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(50, 100)),
|
||||
"Both child controls expand equally to fill available space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First expanding child control is aligned to the left.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Second expanding child control is positioned after the first expanding child control.");
|
||||
|
||||
child_control_2->set_stretch_ratio(3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(25, 100)),
|
||||
"Child control with lower stretch ratio takes less space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(75, 100)),
|
||||
"Child control with higher stretch ratio takes more space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First expanding child control is aligned to the left.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(25, 0)),
|
||||
"Second expanding child control is positioned after the first expanding child control.");
|
||||
|
||||
memdelete(child_control_1);
|
||||
memdelete(child_control_2);
|
||||
}
|
||||
|
||||
memdelete(hbox_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][BoxContainer] VBoxContainer") {
|
||||
VBoxContainer *vbox_container = memnew(VBoxContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(vbox_container);
|
||||
|
||||
vbox_container->set_size(Size2(100, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
SUBCASE("Default behavior") {
|
||||
Control *child_control = memnew(Control);
|
||||
vbox_container->add_child(child_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vbox_container->get_alignment() == BoxContainer::ALIGNMENT_BEGIN,
|
||||
"HBoxContainer alignment is set to ALIGNMENT_BEGIN by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vbox_container->is_vertical(),
|
||||
"VBoxContainer orientation is vertical.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left in ALIGNMENT_BEGIN mode.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_h_size_flags() == Control::SIZE_FILL,
|
||||
"Child control horizontal size flags are set to SIZE_FILL by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_v_size_flags() == Control::SIZE_FILL,
|
||||
"Child control vertical size flags are set to SIZE_FILL by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 0)),
|
||||
"Child control takes up minimum vertical space and matches container width by default.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Size Flags") {
|
||||
Control *child_control = memnew(Control);
|
||||
vbox_container->add_child(child_control);
|
||||
child_control->set_custom_minimum_size(Size2(20, 20));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top by default with SIZE_FILL.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top of in SIZE_SHRINK_BEGIN vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top of in SIZE_SHRINK_CENTER vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top of in SIZE_SHRINK_END vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top in SIZE_EXPAND | SIZE_SHRINK_BEGIN vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 40)),
|
||||
"Child control is aligned to the center in SIZE_EXPAND | SIZE_SHRINK_CENTER vertical size flag mode.");
|
||||
|
||||
child_control->set_v_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 80)),
|
||||
"Child control is aligned to the bottom in SIZE_EXPAND | SIZE_SHRINK_END vertical size flag mode.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Horizontal Size Flags") {
|
||||
Control *child_control = memnew(Control);
|
||||
vbox_container->add_child(child_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left by default with SIZE_FILL.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_BEGIN);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the left of in SIZE_SHRINK_BEGIN horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Child control is aligned to the center of in SIZE_SHRINK_CENTER horizontal size flag mode.");
|
||||
|
||||
child_control->set_h_size_flags(Control::SIZE_SHRINK_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Child control is aligned to the right of in SIZE_SHRINK_END horizontal size flag mode.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Alignment") {
|
||||
Control *child_control = memnew(Control);
|
||||
vbox_container->add_child(child_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top in ALIGNMENT_BEGIN mode by default.");
|
||||
|
||||
vbox_container->set_alignment(BoxContainer::ALIGNMENT_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"Child control is aligned to the center in ALIGNMENT_CENTER mode.");
|
||||
|
||||
vbox_container->set_alignment(BoxContainer::ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 100)),
|
||||
"Child control is aligned to the bottom in ALIGNMENT_END mode.");
|
||||
|
||||
memdelete(child_control);
|
||||
}
|
||||
|
||||
SUBCASE("Child Separation") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
vbox_container->add_child(child_control_1);
|
||||
vbox_container->add_child(child_control_2);
|
||||
|
||||
vbox_container->add_theme_constant_override("separation", 10);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 10)),
|
||||
"Child controls are separated by the specified separation value.");
|
||||
|
||||
memdelete(child_control_1);
|
||||
memdelete(child_control_2);
|
||||
}
|
||||
|
||||
SUBCASE("Spacers") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
vbox_container->add_child(child_control_1);
|
||||
vbox_container->add_spacer();
|
||||
vbox_container->add_child(child_control_2);
|
||||
vbox_container->add_theme_constant_override("separation", 0);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 100)),
|
||||
"Spacer pushes child controls apart.");
|
||||
|
||||
memdelete(child_control_1);
|
||||
memdelete(child_control_2);
|
||||
}
|
||||
|
||||
SUBCASE("Expanding children") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
vbox_container->add_child(child_control_1);
|
||||
vbox_container->add_child(child_control_2);
|
||||
vbox_container->add_theme_constant_override("separation", 0);
|
||||
|
||||
child_control_1->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"One child control expands to fill available space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(100, 0)),
|
||||
"The non-expanding child control remains at minimum size.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Expanding child control is aligned to the left.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 100)),
|
||||
"Non-expanding child control is positioned after the expanding child control.");
|
||||
|
||||
child_control_2->set_custom_minimum_size(Size2(0, 20));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(100, 80)),
|
||||
"Expanding child control shrinks to accommodate the custom minimum size of the other child.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(100, 20)),
|
||||
"The non-expanding child control respects its custom minimum size.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Expanding child control is aligned to the left.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 80)),
|
||||
"Non-expanding child control is positioned after the expanding child control.");
|
||||
|
||||
child_control_2->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(100, 50)),
|
||||
"Both child controls expand equally to fill available space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(100, 50)),
|
||||
"Both child controls expand equally to fill available space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First expanding child control is aligned to the left.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"Second expanding child control is positioned after the first expanding child control.");
|
||||
|
||||
child_control_2->set_stretch_ratio(3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(100, 25)),
|
||||
"Child control with lower stretch ratio takes less space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(100, 75)),
|
||||
"Child control with higher stretch ratio takes more space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First expanding child control is aligned to the left.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 25)),
|
||||
"Second expanding child control is positioned after the first expanding child control.");
|
||||
|
||||
memdelete(child_control_1);
|
||||
memdelete(child_control_2);
|
||||
}
|
||||
|
||||
memdelete(vbox_container);
|
||||
}
|
||||
|
||||
} // namespace TestBoxContainer
|
||||
@@ -0,0 +1,170 @@
|
||||
/**************************************************************************/
|
||||
/* test_center_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_center_container)
|
||||
|
||||
#include "scene/gui/center_container.h"
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
namespace TestCenterContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][CenterContainer] Standard behavior") {
|
||||
CenterContainer *center_container = memnew(CenterContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(center_container);
|
||||
Control *child_control = memnew(Control);
|
||||
center_container->add_child(child_control);
|
||||
|
||||
center_container->set_size(Size2(100, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 50)),
|
||||
"Child control is centered within the CenterContainer by default.");
|
||||
|
||||
child_control->set_custom_minimum_size(Size2(20, 20));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(40, 40)),
|
||||
"Child control remains centered when custom minimum size is set.");
|
||||
|
||||
child_control->set_custom_minimum_size(Size2(200, 200));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
center_container->get_size().is_equal_approx(Size2(200, 200)),
|
||||
"CenterContainer expands to accommodate the minimum size of its child control.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is positioned at the top-left corner when its minimum size equals the container size.");
|
||||
|
||||
child_control->set_custom_minimum_size(Size2());
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(50, 50)),
|
||||
"Child control re-centers when custom minimum size is reset.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
center_container->get_size().is_equal_approx(Size2(100, 100)),
|
||||
"CenterContainer returns to original size when child control's custom minimum size is reset.");
|
||||
|
||||
center_container->set_use_top_left(true);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control is aligned to the top-left corner when use_top_left is enabled.");
|
||||
|
||||
center_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Child control is aligned to the top-right corner in RTL layout direction when use_top_left is enabled.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(center_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][CenterContainer] Multiple children") {
|
||||
CenterContainer *center_container = memnew(CenterContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(center_container);
|
||||
|
||||
center_container->set_size(Size2(100, 100));
|
||||
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
center_container->add_child(child_control_1);
|
||||
center_container->add_child(child_control_2);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(50, 50)),
|
||||
"First child control is centered within the CenterContainer.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(50, 50)),
|
||||
"Second child control is also centered and overlaps the first child control by default.");
|
||||
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 20));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(40, 40)),
|
||||
"First child control remains centered when custom minimum size is set.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(50, 50)),
|
||||
"Second child control remains centered and overlaps the first child control even when the first child has a custom minimum size.");
|
||||
|
||||
child_control_1->set_custom_minimum_size(Size2(200, 0));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
center_container->get_size().is_equal_approx(Size2(200, 100)),
|
||||
"CenterContainer expands to accommodate the minimum size of the first child control.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"First child control is aligned to the left edge of the CenterContainer when its minimum width equals the container width.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(100, 50)),
|
||||
"Second child control is centered on the new container center.");
|
||||
|
||||
child_control_2->set_custom_minimum_size(Size2(0, 200));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
center_container->get_size().is_equal_approx(Size2(200, 200)),
|
||||
"CenterContainer expands to accommodate the minimum size of the second child control.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 100)),
|
||||
"First child control is aligned to the left edge and centered vertically when its minimum width equals the container width but its minimum height is smaller than the container height.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(100, 0)),
|
||||
"Second child control is aligned to the top edge and centered horizontally when its minimum height equals the container height but its minimum width is smaller than the container width.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
memdelete(center_container);
|
||||
}
|
||||
|
||||
} // namespace TestCenterContainer
|
||||
@@ -0,0 +1,576 @@
|
||||
/**************************************************************************/
|
||||
/* test_flow_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_flow_container)
|
||||
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/gui/flow_container.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
namespace TestFlowContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][FlowContainer] HFlowContainer") {
|
||||
HFlowContainer *hflow_container = memnew(HFlowContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(hflow_container);
|
||||
|
||||
hflow_container->add_theme_constant_override("h_separation", 0);
|
||||
hflow_container->add_theme_constant_override("v_separation", 0);
|
||||
hflow_container->set_size(Size2(100, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
SUBCASE("Default behavior") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_3->set_custom_minimum_size(Size2(20, 10));
|
||||
hflow_container->add_child(child_control_1);
|
||||
hflow_container->add_child(child_control_2);
|
||||
hflow_container->add_child(child_control_3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
hflow_container->get_alignment() == FlowContainer::ALIGNMENT_BEGIN,
|
||||
"HFlowContainer alignment is set to ALIGNMENT_BEGIN by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
hflow_container->get_last_wrap_alignment() == FlowContainer::LAST_WRAP_ALIGNMENT_INHERIT,
|
||||
"HFlowContainer last wrap alignment is set to LAST_WRAP_ALIGNMENT_INHERIT by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!hflow_container->is_vertical(),
|
||||
"HFlowContainer is horizontal.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!hflow_container->is_reverse_fill(),
|
||||
"HFlowContainer reverse fill is disabled by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
hflow_container->get_line_count() == 1,
|
||||
"HFlowContainer keeps all children in one line when there is enough horizontal space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
hflow_container->get_line_max_child_count() == 3,
|
||||
"HFlowContainer reports the child count of the first line.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First child control is positioned at the beginning of the line.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(20, 0)),
|
||||
"Second child control is placed after the first child control.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(40, 0)),
|
||||
"Third child control is placed after the second child control.");
|
||||
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
SUBCASE("Wrapping and last wrap alignment") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_3->set_custom_minimum_size(Size2(20, 10));
|
||||
hflow_container->set_size(Size2(50, 100));
|
||||
hflow_container->add_child(child_control_1);
|
||||
hflow_container->add_child(child_control_2);
|
||||
hflow_container->add_child(child_control_3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
hflow_container->get_line_count() == 2,
|
||||
"HFlowContainer wraps children to a second line when they no longer fit.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
hflow_container->get_line_max_child_count() == 2,
|
||||
"HFlowContainer reports the first line child count as the line max child count.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First child control starts at the first line origin.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(20, 0)),
|
||||
"Second child control remains on the first line.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(0, 10)),
|
||||
"Third child control wraps to the second line.");
|
||||
|
||||
hflow_container->set_last_wrap_alignment(FlowContainer::LAST_WRAP_ALIGNMENT_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(10, 10)),
|
||||
"Last wrapped line is centered relative to the previous line when LAST_WRAP_ALIGNMENT_CENTER is used.");
|
||||
|
||||
hflow_container->set_last_wrap_alignment(FlowContainer::LAST_WRAP_ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(20, 10)),
|
||||
"Last wrapped line is aligned to the end relative to the previous line when LAST_WRAP_ALIGNMENT_END is used.");
|
||||
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
SUBCASE("Alignment and RTL") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 10));
|
||||
hflow_container->set_size(Size2(100, 100));
|
||||
hflow_container->add_child(child_control_1);
|
||||
hflow_container->add_child(child_control_2);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
hflow_container->set_alignment(FlowContainer::ALIGNMENT_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(30, 0)),
|
||||
"First child control is centered when ALIGNMENT_CENTER is used.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Second child control follows centered alignment when ALIGNMENT_CENTER is used.");
|
||||
|
||||
hflow_container->set_alignment(FlowContainer::ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(60, 0)),
|
||||
"First child control is aligned to the end when ALIGNMENT_END is used.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(80, 0)),
|
||||
"Second child control is aligned to the end when ALIGNMENT_END is used.");
|
||||
|
||||
hflow_container->set_alignment(FlowContainer::ALIGNMENT_BEGIN);
|
||||
hflow_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(80, 0)),
|
||||
"First child control starts at the right edge in RTL mode with ALIGNMENT_BEGIN.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(60, 0)),
|
||||
"Second child control follows right-to-left ordering in RTL mode with ALIGNMENT_BEGIN.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
SUBCASE("Expanding children and stretch ratio") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_1->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
child_control_2->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
hflow_container->set_size(Size2(100, 100));
|
||||
hflow_container->add_child(child_control_1);
|
||||
hflow_container->add_child(child_control_2);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(50, 10)),
|
||||
"First child control expands to half of the available width when both children have equal stretch ratio.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(50, 10)),
|
||||
"Second child control expands to half of the available width when both children have equal stretch ratio.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(50, 0)),
|
||||
"Second child control is placed immediately after the first expanded child control.");
|
||||
|
||||
child_control_2->set_stretch_ratio(3.0f);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(35, 10)),
|
||||
"First child control receives less width when its stretch ratio is lower.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(65, 10)),
|
||||
"Second child control receives more width when its stretch ratio is higher.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(35, 0)),
|
||||
"Second child control starts after the first child control's stretched width.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
SUBCASE("Reverse fill") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_3->set_custom_minimum_size(Size2(20, 10));
|
||||
hflow_container->set_size(Size2(50, 100));
|
||||
hflow_container->add_child(child_control_1);
|
||||
hflow_container->add_child(child_control_2);
|
||||
hflow_container->add_child(child_control_3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First child control starts at the top row by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(0, 10)),
|
||||
"Third child control wraps to the next row by default.");
|
||||
|
||||
hflow_container->set_reverse_fill(true);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 90)),
|
||||
"First child control moves to the bottom row when reverse fill is enabled.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(20, 90)),
|
||||
"Second child control remains in the same row as the first child control when reverse fill is enabled.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(0, 80)),
|
||||
"Wrapped row order is inverted from bottom to top when reverse fill is enabled.");
|
||||
|
||||
hflow_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(30, 90)),
|
||||
"RTL mirrors horizontal placement while reverse fill keeps rows bottom to top.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(10, 90)),
|
||||
"Second child control follows mirrored RTL order while reverse fill remains enabled.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(30, 80)),
|
||||
"Wrapped child control is mirrored in RTL while keeping reverse-filled row order.");
|
||||
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
memdelete(hflow_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][FlowContainer] VFlowContainer") {
|
||||
VFlowContainer *vflow_container = memnew(VFlowContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(vflow_container);
|
||||
|
||||
vflow_container->add_theme_constant_override("h_separation", 0);
|
||||
vflow_container->add_theme_constant_override("v_separation", 0);
|
||||
vflow_container->set_size(Size2(100, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
SUBCASE("Default behavior") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 10));
|
||||
child_control_3->set_custom_minimum_size(Size2(20, 10));
|
||||
vflow_container->add_child(child_control_1);
|
||||
vflow_container->add_child(child_control_2);
|
||||
vflow_container->add_child(child_control_3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vflow_container->get_alignment() == FlowContainer::ALIGNMENT_BEGIN,
|
||||
"VFlowContainer alignment is set to ALIGNMENT_BEGIN by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vflow_container->get_last_wrap_alignment() == FlowContainer::LAST_WRAP_ALIGNMENT_INHERIT,
|
||||
"VFlowContainer last wrap alignment is set to LAST_WRAP_ALIGNMENT_INHERIT by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vflow_container->is_vertical(),
|
||||
"VFlowContainer is vertical.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!vflow_container->is_reverse_fill(),
|
||||
"VFlowContainer reverse fill is disabled by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vflow_container->get_line_count() == 1,
|
||||
"VFlowContainer keeps all children in one column when there is enough vertical space.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vflow_container->get_line_max_child_count() == 3,
|
||||
"VFlowContainer reports the child count of the first column.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First child control is positioned at the top of the first column.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 10)),
|
||||
"Second child control is placed below the first child control.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(0, 20)),
|
||||
"Third child control is placed below the second child control.");
|
||||
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
SUBCASE("Wrapping and last wrap alignment") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_3->set_custom_minimum_size(Size2(20, 20));
|
||||
vflow_container->set_size(Size2(100, 50));
|
||||
vflow_container->add_child(child_control_1);
|
||||
vflow_container->add_child(child_control_2);
|
||||
vflow_container->add_child(child_control_3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vflow_container->get_line_count() == 2,
|
||||
"VFlowContainer wraps children to a second column when they no longer fit vertically.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
vflow_container->get_line_max_child_count() == 2,
|
||||
"VFlowContainer reports the first column child count as the line max child count.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First child control starts at the first column origin.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 20)),
|
||||
"Second child control remains in the first column.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(20, 0)),
|
||||
"Third child control wraps to the second column.");
|
||||
|
||||
vflow_container->set_last_wrap_alignment(FlowContainer::LAST_WRAP_ALIGNMENT_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(20, 10)),
|
||||
"Last wrapped column is centered relative to the previous column when LAST_WRAP_ALIGNMENT_CENTER is used.");
|
||||
|
||||
vflow_container->set_last_wrap_alignment(FlowContainer::LAST_WRAP_ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(20, 20)),
|
||||
"Last wrapped column is aligned to the end relative to the previous column when LAST_WRAP_ALIGNMENT_END is used.");
|
||||
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
SUBCASE("Alignment and RTL") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 20));
|
||||
vflow_container->set_size(Size2(100, 100));
|
||||
vflow_container->add_child(child_control_1);
|
||||
vflow_container->add_child(child_control_2);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
vflow_container->set_alignment(FlowContainer::ALIGNMENT_CENTER);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 30)),
|
||||
"First child control is vertically centered when ALIGNMENT_CENTER is used.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"Second child control follows centered vertical alignment when ALIGNMENT_CENTER is used.");
|
||||
|
||||
vflow_container->set_alignment(FlowContainer::ALIGNMENT_END);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 60)),
|
||||
"First child control is aligned to the bottom when ALIGNMENT_END is used.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 80)),
|
||||
"Second child control is aligned to the bottom when ALIGNMENT_END is used.");
|
||||
|
||||
vflow_container->set_alignment(FlowContainer::ALIGNMENT_BEGIN);
|
||||
vflow_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(80, 0)),
|
||||
"First child control moves to the right edge in RTL mode with vertical flow.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(80, 20)),
|
||||
"Second child control follows RTL horizontal mirroring in vertical flow.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
SUBCASE("Expanding children and stretch ratio") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_1->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
child_control_2->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
vflow_container->set_size(Size2(100, 100));
|
||||
vflow_container->add_child(child_control_1);
|
||||
vflow_container->add_child(child_control_2);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(20, 50)),
|
||||
"First child control expands to half of the available height when both children have equal stretch ratio.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(20, 50)),
|
||||
"Second child control expands to half of the available height when both children have equal stretch ratio.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 50)),
|
||||
"Second child control is placed immediately after the first expanded child control.");
|
||||
|
||||
child_control_2->set_stretch_ratio(3.0f);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(20, 35)),
|
||||
"First child control receives less height when its stretch ratio is lower.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(20, 65)),
|
||||
"Second child control receives more height when its stretch ratio is higher.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 35)),
|
||||
"Second child control starts after the first child control's stretched height.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
SUBCASE("Reverse fill") {
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_3->set_custom_minimum_size(Size2(20, 20));
|
||||
vflow_container->set_size(Size2(100, 30));
|
||||
vflow_container->add_child(child_control_1);
|
||||
vflow_container->add_child(child_control_2);
|
||||
vflow_container->add_child(child_control_3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First child control starts in the first column by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(20, 0)),
|
||||
"Second child control starts in the second column by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(40, 0)),
|
||||
"Third child control starts in the third column by default.");
|
||||
|
||||
vflow_container->set_reverse_fill(true);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(80, 0)),
|
||||
"First child control starts from the right when reverse fill is enabled in vertical mode.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(60, 0)),
|
||||
"Second child control follows right-to-left column filling when reverse fill is enabled.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(40, 0)),
|
||||
"Third child control continues right-to-left column filling when reverse fill is enabled.");
|
||||
|
||||
vflow_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Vertical flow with RTL and reverse fill fills columns from left to right.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(20, 0)),
|
||||
"Second child control follows left-to-right order in vertical mode with RTL and reverse fill.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(40, 0)),
|
||||
"Third child control follows left-to-right order in vertical mode with RTL and reverse fill.");
|
||||
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
}
|
||||
|
||||
memdelete(vflow_container);
|
||||
}
|
||||
|
||||
} // namespace TestFlowContainer
|
||||
@@ -0,0 +1,270 @@
|
||||
/**************************************************************************/
|
||||
/* test_foldable_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_foldable_container)
|
||||
|
||||
#ifndef ADVANCED_GUI_DISABLED
|
||||
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/gui/foldable_container.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
namespace TestFoldableContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][FoldableContainer] Default properties") {
|
||||
FoldableContainer *foldable_container = memnew(FoldableContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(foldable_container);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!foldable_container->is_folded(),
|
||||
"FoldableContainer is expanded by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_title().is_empty(),
|
||||
"FoldableContainer title is empty by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_title_alignment() == HORIZONTAL_ALIGNMENT_LEFT,
|
||||
"FoldableContainer title alignment is set to left by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_title_position() == FoldableContainer::POSITION_TOP,
|
||||
"FoldableContainer title position is set to top by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_title_text_direction() == Control::TEXT_DIRECTION_AUTO,
|
||||
"FoldableContainer title text direction is set to auto by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_title_text_overrun_behavior() == TextServer::OVERRUN_NO_TRIMMING,
|
||||
"FoldableContainer title overrun behavior is set to no trimming by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_language().is_empty(),
|
||||
"FoldableContainer language is empty by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_focus_mode() == Control::FOCUS_ALL,
|
||||
"FoldableContainer focus mode is set to FOCUS_ALL by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_mouse_filter() == Control::MOUSE_FILTER_STOP,
|
||||
"FoldableContainer mouse filter is set to MOUSE_FILTER_STOP by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_foldable_group().is_null(),
|
||||
"FoldableContainer has no foldable group by default.");
|
||||
|
||||
memdelete(foldable_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][FoldableContainer] Fold and expand behavior") {
|
||||
FoldableContainer *foldable_container = memnew(FoldableContainer("Section"));
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(foldable_container);
|
||||
|
||||
Control *child_control = memnew(Control);
|
||||
child_control->set_custom_minimum_size(Size2(120, 80));
|
||||
foldable_container->add_child(child_control);
|
||||
foldable_container->set_size(Size2(200, 200));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
Size2 expanded_minimum_size = foldable_container->get_minimum_size();
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->is_visible(),
|
||||
"Child control is visible when FoldableContainer is expanded.");
|
||||
|
||||
foldable_container->fold();
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->is_folded(),
|
||||
"FoldableContainer is folded after calling fold().");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!child_control->is_visible(),
|
||||
"Child control is hidden when FoldableContainer is folded.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->get_minimum_size().y < expanded_minimum_size.y,
|
||||
"Folded minimum size is smaller than expanded minimum size when content is present.");
|
||||
|
||||
foldable_container->expand();
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!foldable_container->is_folded(),
|
||||
"FoldableContainer is expanded after calling expand().");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->is_visible(),
|
||||
"Child control is visible again after FoldableContainer is expanded.");
|
||||
|
||||
foldable_container->set_folded(true);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_container->is_folded(),
|
||||
"set_folded(true) folds the FoldableContainer.");
|
||||
|
||||
foldable_container->set_folded(false);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!foldable_container->is_folded(),
|
||||
"set_folded(false) expands the FoldableContainer.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(foldable_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][FoldableContainer] Title position and title bar controls") {
|
||||
FoldableContainer *foldable_container = memnew(FoldableContainer("Section"));
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(foldable_container);
|
||||
|
||||
Control *content_control = memnew(Control);
|
||||
content_control->set_custom_minimum_size(Size2(40, 40));
|
||||
foldable_container->add_child(content_control);
|
||||
|
||||
Control *title_control = memnew(Control);
|
||||
title_control->set_custom_minimum_size(Size2(30, 20));
|
||||
foldable_container->add_title_bar_control(title_control);
|
||||
|
||||
foldable_container->set_size(Size2(200, 140));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
title_control->get_parent() == foldable_container,
|
||||
"Title bar control is reparented to the FoldableContainer when added.");
|
||||
|
||||
real_t top_title_control_y = title_control->get_position().y;
|
||||
real_t top_content_y = content_control->get_position().y;
|
||||
|
||||
foldable_container->set_title_position(FoldableContainer::POSITION_BOTTOM);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
real_t bottom_title_control_y = title_control->get_position().y;
|
||||
real_t bottom_content_y = content_control->get_position().y;
|
||||
|
||||
CHECK_MESSAGE(
|
||||
bottom_title_control_y > top_title_control_y,
|
||||
"Title bar controls move to the bottom when title position is set to POSITION_BOTTOM.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
bottom_content_y < top_content_y,
|
||||
"Content area shifts upward when title position is changed from top to bottom.");
|
||||
|
||||
foldable_container->remove_title_bar_control(title_control);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
title_control->get_parent() == nullptr,
|
||||
"Title bar control is detached from FoldableContainer when removed.");
|
||||
|
||||
memdelete(title_control);
|
||||
memdelete(content_control);
|
||||
memdelete(foldable_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][FoldableContainer] FoldableGroup behavior") {
|
||||
Ref<FoldableGroup> foldable_group;
|
||||
foldable_group.instantiate();
|
||||
|
||||
FoldableContainer *container_a = memnew(FoldableContainer("A"));
|
||||
FoldableContainer *container_b = memnew(FoldableContainer("B"));
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(container_a);
|
||||
root->add_child(container_b);
|
||||
|
||||
container_a->set_folded(true);
|
||||
container_b->set_folded(true);
|
||||
container_a->set_foldable_group(foldable_group);
|
||||
container_b->set_foldable_group(foldable_group);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!container_a->is_folded(),
|
||||
"First grouped FoldableContainer auto-expands when allow_folding_all is false and no container is expanded.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
container_b->is_folded(),
|
||||
"Second grouped FoldableContainer remains folded when another container in the group is expanded.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_group->get_expanded_container() == container_a,
|
||||
"FoldableGroup tracks the currently expanded container.");
|
||||
|
||||
container_b->set_folded(false);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
container_a->is_folded(),
|
||||
"Expanding one grouped FoldableContainer folds the previously expanded container.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!container_b->is_folded(),
|
||||
"Expanded grouped FoldableContainer remains unfolded.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_group->get_expanded_container() == container_b,
|
||||
"FoldableGroup updates expanded container after a different container is expanded.");
|
||||
|
||||
container_b->set_folded(true);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!container_b->is_folded(),
|
||||
"Expanded grouped FoldableContainer cannot be folded when allow_folding_all is false.");
|
||||
|
||||
foldable_group->set_allow_folding_all(true);
|
||||
container_b->set_folded(true);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
container_b->is_folded(),
|
||||
"Grouped FoldableContainer can be folded when allow_folding_all is true.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
foldable_group->get_expanded_container() == nullptr,
|
||||
"FoldableGroup has no expanded container when all grouped containers are folded.");
|
||||
|
||||
memdelete(container_b);
|
||||
memdelete(container_a);
|
||||
}
|
||||
|
||||
} // namespace TestFoldableContainer
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,265 @@
|
||||
/**************************************************************************/
|
||||
/* test_grid_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_grid_container)
|
||||
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/gui/grid_container.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
namespace TestGridContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][GridContainer] Default properties") {
|
||||
GridContainer *grid_container = memnew(GridContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(grid_container);
|
||||
|
||||
grid_container->set_size(Size2(200, 200));
|
||||
grid_container->add_theme_constant_override("h_separation", 0);
|
||||
grid_container->add_theme_constant_override("v_separation", 0);
|
||||
|
||||
Control *child_control = memnew(Control);
|
||||
child_control->set_custom_minimum_size(Size2(20, 10));
|
||||
grid_container->add_child(child_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
grid_container->get_columns() == 1,
|
||||
"GridContainer columns are set to 1 by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Single child control starts at the top-left corner.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(20, 10)),
|
||||
"Single child control keeps its minimum size when no expansion is requested.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(grid_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][GridContainer] Columns and placement order") {
|
||||
GridContainer *grid_container = memnew(GridContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(grid_container);
|
||||
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
Control *child_control_4 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(10, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(10, 10));
|
||||
child_control_3->set_custom_minimum_size(Size2(10, 10));
|
||||
child_control_4->set_custom_minimum_size(Size2(10, 10));
|
||||
|
||||
grid_container->set_columns(2);
|
||||
grid_container->set_size(Size2(200, 200));
|
||||
grid_container->add_theme_constant_override("h_separation", 0);
|
||||
grid_container->add_theme_constant_override("v_separation", 0);
|
||||
grid_container->add_child(child_control_1);
|
||||
grid_container->add_child(child_control_2);
|
||||
grid_container->add_child(child_control_3);
|
||||
grid_container->add_child(child_control_4);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
grid_container->get_columns() == 2,
|
||||
"GridContainer uses the configured number of columns.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First child control is placed at row 0, column 0.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(10, 0)),
|
||||
"Second child control is placed at row 0, column 1.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(0, 10)),
|
||||
"Third child control is placed at row 1, column 0.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_4->get_position().is_equal_approx(Point2(10, 10)),
|
||||
"Fourth child control is placed at row 1, column 1.");
|
||||
|
||||
memdelete(child_control_4);
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
memdelete(grid_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][GridContainer] Separation and minimum size") {
|
||||
GridContainer *grid_container = memnew(GridContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(grid_container);
|
||||
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(10, 20));
|
||||
child_control_2->set_custom_minimum_size(Size2(30, 10));
|
||||
child_control_3->set_custom_minimum_size(Size2(15, 40));
|
||||
|
||||
grid_container->set_columns(2);
|
||||
grid_container->add_theme_constant_override("h_separation", 5);
|
||||
grid_container->add_theme_constant_override("v_separation", 7);
|
||||
grid_container->add_child(child_control_1);
|
||||
grid_container->add_child(child_control_2);
|
||||
grid_container->add_child(child_control_3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
grid_container->get_h_separation() == 5,
|
||||
"GridContainer reports overridden horizontal separation.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
grid_container->get_minimum_size().is_equal_approx(Size2(50, 67)),
|
||||
"GridContainer minimum size matches per-column and per-row maxima plus separations.");
|
||||
|
||||
grid_container->set_size(Size2(50, 67));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"First child control is placed at row 0, column 0 with configured separations.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(20, 0)),
|
||||
"Second child control is offset by column width and horizontal separation.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(0, 27)),
|
||||
"Third child control is offset by row height and vertical separation.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(15, 20)),
|
||||
"First child control fills the first grid cell dimensions.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(30, 20)),
|
||||
"Second child control fills the second grid cell dimensions.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_size().is_equal_approx(Size2(15, 40)),
|
||||
"Third child control fills the second-row first-column cell dimensions.");
|
||||
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
memdelete(grid_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][GridContainer] Expanding rows and columns") {
|
||||
GridContainer *grid_container = memnew(GridContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(grid_container);
|
||||
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
Control *child_control_3 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_3->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_1->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
child_control_1->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
|
||||
grid_container->set_columns(2);
|
||||
grid_container->add_theme_constant_override("h_separation", 0);
|
||||
grid_container->add_theme_constant_override("v_separation", 0);
|
||||
grid_container->set_size(Size2(100, 100));
|
||||
grid_container->add_child(child_control_1);
|
||||
grid_container->add_child(child_control_2);
|
||||
grid_container->add_child(child_control_3);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_size().is_equal_approx(Size2(80, 80)),
|
||||
"Expanded child control grows with its expanded column and row.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_size().is_equal_approx(Size2(20, 80)),
|
||||
"Non-expanded column still receives expanded row height.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_size().is_equal_approx(Size2(80, 20)),
|
||||
"Non-expanded row still receives expanded column width.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(80, 0)),
|
||||
"Second child control is positioned after expanded first column width.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_3->get_position().is_equal_approx(Point2(0, 80)),
|
||||
"Third child control is positioned after expanded first row height.");
|
||||
|
||||
memdelete(child_control_3);
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
memdelete(grid_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][GridContainer] RTL placement") {
|
||||
GridContainer *grid_container = memnew(GridContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(grid_container);
|
||||
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(20, 20));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 20));
|
||||
|
||||
grid_container->set_columns(2);
|
||||
grid_container->add_theme_constant_override("h_separation", 0);
|
||||
grid_container->add_theme_constant_override("v_separation", 0);
|
||||
grid_container->set_size(Size2(40, 20));
|
||||
grid_container->add_child(child_control_1);
|
||||
grid_container->add_child(child_control_2);
|
||||
grid_container->set_layout_direction(Control::LAYOUT_DIRECTION_RTL);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_1->get_position().is_equal_approx(Point2(20, 0)),
|
||||
"First child control starts in the right column in RTL mode.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control_2->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Second child control is placed in the left column in RTL mode.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
memdelete(grid_container);
|
||||
}
|
||||
|
||||
} // namespace TestGridContainer
|
||||
@@ -0,0 +1,146 @@
|
||||
/**************************************************************************/
|
||||
/* test_margin_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_margin_container)
|
||||
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/gui/margin_container.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
namespace TestMarginContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][MarginContainer] Default margins and layout") {
|
||||
MarginContainer *margin_container = memnew(MarginContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(margin_container);
|
||||
|
||||
Control *child_control = memnew(Control);
|
||||
child_control->set_custom_minimum_size(Size2(20, 10));
|
||||
margin_container->add_child(child_control);
|
||||
|
||||
margin_container->set_size(Size2(100, 80));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
margin_container->get_margin_size(SIDE_LEFT) == 0,
|
||||
"Left margin is 0 by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
margin_container->get_margin_size(SIDE_TOP) == 0,
|
||||
"Top margin is 0 by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
margin_container->get_margin_size(SIDE_RIGHT) == 0,
|
||||
"Right margin is 0 by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
margin_container->get_margin_size(SIDE_BOTTOM) == 0,
|
||||
"Bottom margin is 0 by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(0, 0)),
|
||||
"Child control starts at the top-left corner when all margins are 0.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(100, 80)),
|
||||
"Child control fills the container area when all margins are 0.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
margin_container->get_minimum_size().is_equal_approx(Size2(20, 10)),
|
||||
"Minimum size equals the child minimum size when all margins are 0.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(margin_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][MarginContainer] Custom margins affect layout and minimum size") {
|
||||
MarginContainer *margin_container = memnew(MarginContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(margin_container);
|
||||
|
||||
margin_container->add_theme_constant_override("margin_left", 10);
|
||||
margin_container->add_theme_constant_override("margin_top", 20);
|
||||
margin_container->add_theme_constant_override("margin_right", 30);
|
||||
margin_container->add_theme_constant_override("margin_bottom", 40);
|
||||
|
||||
Control *child_control = memnew(Control);
|
||||
child_control->set_custom_minimum_size(Size2(20, 10));
|
||||
margin_container->add_child(child_control);
|
||||
|
||||
margin_container->set_size(Size2(200, 150));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(10, 20)),
|
||||
"Child control is offset by left and top margins.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(160, 90)),
|
||||
"Child control size is reduced by left/right and top/bottom margins.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
margin_container->get_minimum_size().is_equal_approx(Size2(60, 70)),
|
||||
"Minimum size equals child minimum size plus all configured margins.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(margin_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][MarginContainer] Multiple children use maximum minimum size") {
|
||||
MarginContainer *margin_container = memnew(MarginContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(margin_container);
|
||||
|
||||
margin_container->add_theme_constant_override("margin_left", 1);
|
||||
margin_container->add_theme_constant_override("margin_top", 2);
|
||||
margin_container->add_theme_constant_override("margin_right", 3);
|
||||
margin_container->add_theme_constant_override("margin_bottom", 4);
|
||||
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(40, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 50));
|
||||
margin_container->add_child(child_control_1);
|
||||
margin_container->add_child(child_control_2);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
margin_container->get_minimum_size().is_equal_approx(Size2(44, 56)),
|
||||
"Minimum size uses maximum child minimum width/height plus margins.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
memdelete(margin_container);
|
||||
}
|
||||
|
||||
} // namespace TestMarginContainer
|
||||
@@ -0,0 +1,114 @@
|
||||
/**************************************************************************/
|
||||
/* test_panel_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_panel_container)
|
||||
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/gui/panel_container.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
#include "scene/resources/style_box.h"
|
||||
|
||||
namespace TestPanelContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][PanelContainer] Default properties") {
|
||||
PanelContainer *panel_container = memnew(PanelContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(panel_container);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
panel_container->get_mouse_filter() == Control::MOUSE_FILTER_STOP,
|
||||
"PanelContainer mouse filter is set to MOUSE_FILTER_STOP by default.");
|
||||
|
||||
memdelete(panel_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][PanelContainer] StyleBox affects layout and minimum size") {
|
||||
PanelContainer *panel_container = memnew(PanelContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(panel_container);
|
||||
|
||||
Ref<StyleBoxEmpty> panel_style = memnew(StyleBoxEmpty);
|
||||
panel_style->set_content_margin_individual(5, 6, 7, 8);
|
||||
panel_container->add_theme_style_override("panel", panel_style);
|
||||
|
||||
Control *child_control = memnew(Control);
|
||||
child_control->set_custom_minimum_size(Size2(20, 10));
|
||||
panel_container->add_child(child_control);
|
||||
|
||||
panel_container->set_size(Size2(100, 80));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_position().is_equal_approx(Point2(5, 6)),
|
||||
"Child control is offset by the panel StyleBox margins.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
child_control->get_size().is_equal_approx(Size2(88, 66)),
|
||||
"Child control size is reduced by the panel StyleBox minimum size.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
panel_container->get_minimum_size().is_equal_approx(Size2(32, 24)),
|
||||
"Minimum size equals child minimum size plus panel StyleBox minimum size.");
|
||||
|
||||
memdelete(child_control);
|
||||
memdelete(panel_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][PanelContainer] Multiple children use maximum minimum size") {
|
||||
PanelContainer *panel_container = memnew(PanelContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(panel_container);
|
||||
|
||||
Ref<StyleBoxEmpty> panel_style = memnew(StyleBoxEmpty);
|
||||
panel_style->set_content_margin_individual(2, 3, 4, 5);
|
||||
panel_container->add_theme_style_override("panel", panel_style);
|
||||
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
child_control_1->set_custom_minimum_size(Size2(40, 10));
|
||||
child_control_2->set_custom_minimum_size(Size2(20, 50));
|
||||
panel_container->add_child(child_control_1);
|
||||
panel_container->add_child(child_control_2);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
panel_container->get_minimum_size().is_equal_approx(Size2(46, 58)),
|
||||
"Minimum size uses maximum child minimum width/height plus panel StyleBox minimum size.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
memdelete(panel_container);
|
||||
}
|
||||
|
||||
} // namespace TestPanelContainer
|
||||
@@ -0,0 +1,475 @@
|
||||
/**************************************************************************/
|
||||
/* test_scroll_container.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 "tests/test_macros.h"
|
||||
|
||||
TEST_FORCE_LINK(test_scroll_container)
|
||||
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/gui/scroll_container.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
#include "scene/main/window.h"
|
||||
|
||||
namespace TestScrollContainer {
|
||||
|
||||
TEST_CASE("[SceneTree][ScrollContainer] Default behavior") {
|
||||
ScrollContainer *test_container = memnew(ScrollContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(test_container);
|
||||
|
||||
Control *test_control = memnew(Control);
|
||||
test_control->set_custom_minimum_size(Size2(20, 20));
|
||||
test_container->add_child(test_control);
|
||||
|
||||
test_container->set_size(Size2(100, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_horizontal_scroll_mode() == ScrollContainer::SCROLL_MODE_AUTO,
|
||||
"Horizontal scroll mode is SCROLL_MODE_AUTO by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_vertical_scroll_mode() == ScrollContainer::SCROLL_MODE_AUTO,
|
||||
"Vertical scroll mode is SCROLL_MODE_AUTO by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_scroll_hint_mode() == ScrollContainer::SCROLL_HINT_MODE_DISABLED,
|
||||
"Scroll hint mode is SCROLL_HINT_MODE_DISABLED by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->is_scroll_hint_tiled(),
|
||||
"tile_scroll_hint is disabled by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->is_following_focus(),
|
||||
"follow_focus is disabled by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->is_scroll_horizontal_by_default(),
|
||||
"scroll_horizontal_by_default is disabled by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_draw_focus_border(),
|
||||
"draw_focus_border is disabled by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->is_clipping_contents(),
|
||||
"clip_contents is enabled by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll() == 0,
|
||||
"Horizontal scroll starts at 0 by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll() == 0,
|
||||
"Vertical scroll starts at 0 by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll_bar() != nullptr,
|
||||
"Horizontal scrollbar is created by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll_bar() != nullptr,
|
||||
"Vertical scrollbar is created by default.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_h_scroll_bar()->is_visible(),
|
||||
"Horizontal scrollbar is hidden in auto mode when content fits.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_v_scroll_bar()->is_visible(),
|
||||
"Vertical scrollbar is hidden in auto mode when content fits.");
|
||||
|
||||
memdelete(test_control);
|
||||
memdelete(test_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][ScrollContainer] Scroll modes") {
|
||||
ScrollContainer *test_container = memnew(ScrollContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(test_container);
|
||||
Control *test_control = memnew(Control);
|
||||
test_container->add_child(test_control);
|
||||
test_control->set_custom_minimum_size(Size2(100, 100));
|
||||
Control *target_control = memnew(Control);
|
||||
target_control->set_custom_minimum_size(Size2(20, 20));
|
||||
target_control->set_position(Point2(80, 80));
|
||||
target_control->set_size(Size2(20, 20));
|
||||
test_control->add_child(target_control);
|
||||
|
||||
test_container->set_size(Size2(50, 50));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar displays when ScrollContainer width is smaller than contents width with SCROLL_MODE_AUTO.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar displays when ScrollContainer height is smaller than contents height with SCROLL_MODE_AUTO.");
|
||||
|
||||
test_container->set_size(Size2(150, 150));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar does not display when ScrollContainer width is larger than contents width with SCROLL_MODE_AUTO.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar does not display when ScrollContainer height is larger than contents height with SCROLL_MODE_AUTO.");
|
||||
|
||||
test_container->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
|
||||
test_container->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
|
||||
|
||||
test_container->set_size(Size2(50, 50));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar does not display when ScrollContainer width is smaller than contents width with SCROLL_MODE_DISABLED.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar does not display when ScrollContainer height is smaller than contents height with SCROLL_MODE_DISABLED.");
|
||||
|
||||
test_container->set_h_scroll(0);
|
||||
test_container->set_v_scroll(0);
|
||||
int disabled_h_scroll_before = test_container->get_h_scroll();
|
||||
int disabled_v_scroll_before = test_container->get_v_scroll();
|
||||
test_container->ensure_control_visible(target_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll() == disabled_h_scroll_before,
|
||||
"SCROLL_MODE_DISABLED does not change horizontal scroll when ensure_control_visible() targets an out-of-view descendant.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll() == disabled_v_scroll_before,
|
||||
"SCROLL_MODE_DISABLED does not change vertical scroll when ensure_control_visible() targets an out-of-view descendant.");
|
||||
|
||||
test_container->set_h_scroll(0);
|
||||
test_container->set_v_scroll(0);
|
||||
|
||||
test_container->set_size(Size2(150, 150));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar does not display when ScrollContainer width is larger than contents width with SCROLL_MODE_DISABLED.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar does not display when ScrollContainer height is larger than contents height with SCROLL_MODE_DISABLED.");
|
||||
|
||||
test_container->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_SHOW_ALWAYS);
|
||||
test_container->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_SHOW_ALWAYS);
|
||||
|
||||
test_container->set_size(Size2(50, 50));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar displays when ScrollContainer width is smaller than contents width with SCROLL_MODE_SHOW_ALWAYS.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar displays when ScrollContainer height is smaller than contents height with SCROLL_MODE_SHOW_ALWAYS.");
|
||||
|
||||
test_container->set_size(Size2(150, 150));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar displays when ScrollContainer width is larger than contents width with SCROLL_MODE_SHOW_ALWAYS.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar displays when ScrollContainer height is larger than contents height with SCROLL_MODE_SHOW_ALWAYS.");
|
||||
|
||||
test_container->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_SHOW_NEVER);
|
||||
test_container->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_SHOW_NEVER);
|
||||
|
||||
test_container->set_size(Size2(50, 50));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar does not display when ScrollContainer width is smaller than contents width with SCROLL_MODE_SHOW_NEVER.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar does not display when ScrollContainer height is smaller than contents height with SCROLL_MODE_SHOW_NEVER.");
|
||||
|
||||
test_container->set_h_scroll(0);
|
||||
test_container->set_v_scroll(0);
|
||||
int show_never_h_scroll_before = test_container->get_h_scroll();
|
||||
int show_never_v_scroll_before = test_container->get_v_scroll();
|
||||
test_container->ensure_control_visible(target_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll() > show_never_h_scroll_before,
|
||||
"SCROLL_MODE_SHOW_NEVER keeps horizontal scrollbar hidden while still allowing programmatic scrolling.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll() > show_never_v_scroll_before,
|
||||
"SCROLL_MODE_SHOW_NEVER keeps vertical scrollbar hidden while still allowing programmatic scrolling.");
|
||||
|
||||
test_container->set_h_scroll(0);
|
||||
test_container->set_v_scroll(0);
|
||||
|
||||
test_container->set_size(Size2(150, 150));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar does not display when ScrollContainer width is larger than contents width with SCROLL_MODE_SHOW_NEVER.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar does not display when ScrollContainer height is larger than contents height with SCROLL_MODE_SHOW_NEVER.");
|
||||
|
||||
test_container->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_RESERVE);
|
||||
test_container->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_RESERVE);
|
||||
|
||||
test_container->set_size(Size2(50, 50));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar displays when ScrollContainer width is smaller than contents width with SCROLL_MODE_RESERVE.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar displays when ScrollContainer height is smaller than contents height with SCROLL_MODE_RESERVE.");
|
||||
|
||||
test_container->set_size(Size2(150, 150));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_h_scroll_bar()->is_visible(),
|
||||
"H Scrollbar does not display when ScrollContainer width is larger than contents width with SCROLL_MODE_RESERVE.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
!test_container->get_v_scroll_bar()->is_visible(),
|
||||
"V Scrollbar does not display when ScrollContainer height is larger than contents height with SCROLL_MODE_RESERVE.");
|
||||
|
||||
memdelete(test_control);
|
||||
memdelete(test_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][ScrollContainer] Scroll values and property setters") {
|
||||
ScrollContainer *test_container = memnew(ScrollContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(test_container);
|
||||
|
||||
Control *test_control = memnew(Control);
|
||||
test_control->set_custom_minimum_size(Size2(300, 300));
|
||||
test_container->add_child(test_control);
|
||||
|
||||
test_container->set_size(Size2(100, 100));
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
test_container->set_h_scroll(25);
|
||||
test_container->set_v_scroll(35);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll() == 25,
|
||||
"Horizontal scroll value is updated by set_h_scroll().");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll() == 35,
|
||||
"Vertical scroll value is updated by set_v_scroll().");
|
||||
|
||||
test_container->set_horizontal_custom_step(7.0f);
|
||||
test_container->set_vertical_custom_step(9.0f);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(test_container->get_horizontal_custom_step(), 7.0f),
|
||||
"Horizontal custom step is updated correctly.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(test_container->get_vertical_custom_step(), 9.0f),
|
||||
"Vertical custom step is updated correctly.");
|
||||
|
||||
test_container->set_deadzone(13);
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_deadzone() == 13,
|
||||
"Deadzone value is updated correctly.");
|
||||
|
||||
test_container->set_scroll_horizontal_by_default(true);
|
||||
CHECK_MESSAGE(
|
||||
test_container->is_scroll_horizontal_by_default(),
|
||||
"scroll_horizontal_by_default is enabled correctly.");
|
||||
|
||||
test_container->set_follow_focus(true);
|
||||
CHECK_MESSAGE(
|
||||
test_container->is_following_focus(),
|
||||
"follow_focus is enabled correctly.");
|
||||
|
||||
test_container->set_scroll_hint_mode(ScrollContainer::SCROLL_HINT_MODE_ALL);
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_scroll_hint_mode() == ScrollContainer::SCROLL_HINT_MODE_ALL,
|
||||
"Scroll hint mode is updated correctly.");
|
||||
|
||||
test_container->set_tile_scroll_hint(true);
|
||||
CHECK_MESSAGE(
|
||||
test_container->is_scroll_hint_tiled(),
|
||||
"Tiled scroll hint mode is enabled correctly.");
|
||||
|
||||
test_container->set_draw_focus_border(true);
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_draw_focus_border(),
|
||||
"draw_focus_border is enabled correctly.");
|
||||
|
||||
memdelete(test_control);
|
||||
memdelete(test_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][ScrollContainer] ensure_control_visible and follow_focus") {
|
||||
ScrollContainer *test_container = memnew(ScrollContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(test_container);
|
||||
|
||||
Control *content_control = memnew(Control);
|
||||
content_control->set_custom_minimum_size(Size2(300, 300));
|
||||
test_container->add_child(content_control);
|
||||
|
||||
Control *target_control = memnew(Control);
|
||||
target_control->set_focus_mode(Control::FOCUS_ALL);
|
||||
target_control->set_custom_minimum_size(Size2(20, 20));
|
||||
target_control->set_position(Point2(260, 250));
|
||||
target_control->set_size(Size2(20, 20));
|
||||
content_control->add_child(target_control);
|
||||
|
||||
test_container->set_size(Size2(100, 100));
|
||||
test_container->set_h_scroll(0);
|
||||
test_container->set_v_scroll(0);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll() == 0,
|
||||
"Horizontal scroll starts at 0 for this setup.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll() == 0,
|
||||
"Vertical scroll starts at 0 for this setup.");
|
||||
|
||||
test_container->ensure_control_visible(target_control);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll() > 0,
|
||||
"ensure_control_visible() scrolls horizontally when target control is outside the visible area.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll() > 0,
|
||||
"ensure_control_visible() scrolls vertically when target control is outside the visible area.");
|
||||
|
||||
Rect2 target_rect(target_control->get_position(), target_control->get_size());
|
||||
real_t side_margin = test_container->get_v_scroll_bar()->is_visible() ? test_container->get_v_scroll_bar()->get_size().x : 0.0f;
|
||||
real_t bottom_margin = test_container->get_h_scroll_bar()->is_visible() ? test_container->get_h_scroll_bar()->get_size().y : 0.0f;
|
||||
real_t visible_left = test_container->get_h_scroll();
|
||||
real_t visible_top = test_container->get_v_scroll();
|
||||
real_t visible_right = visible_left + test_container->get_size().x - side_margin;
|
||||
real_t visible_bottom = visible_top + test_container->get_size().y - bottom_margin;
|
||||
|
||||
CHECK_MESSAGE(
|
||||
(target_rect.position.x >= visible_left && (target_rect.position.x + target_rect.size.x) <= visible_right),
|
||||
"ensure_control_visible() fully reveals target control horizontally.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
(target_rect.position.y >= visible_top && (target_rect.position.y + target_rect.size.y) <= visible_bottom),
|
||||
"ensure_control_visible() fully reveals target control vertically.");
|
||||
|
||||
test_container->set_h_scroll(0);
|
||||
test_container->set_v_scroll(0);
|
||||
test_container->set_follow_focus(true);
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
target_control->grab_focus();
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_h_scroll() > 0,
|
||||
"follow_focus scrolls horizontally to focused descendants.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_v_scroll() > 0,
|
||||
"follow_focus scrolls vertically to focused descendants.");
|
||||
|
||||
visible_left = test_container->get_h_scroll();
|
||||
visible_top = test_container->get_v_scroll();
|
||||
visible_right = visible_left + test_container->get_size().x - side_margin;
|
||||
visible_bottom = visible_top + test_container->get_size().y - bottom_margin;
|
||||
|
||||
CHECK_MESSAGE(
|
||||
(target_rect.position.x >= visible_left && (target_rect.position.x + target_rect.size.x) <= visible_right),
|
||||
"follow_focus fully reveals focused target control horizontally.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
(target_rect.position.y >= visible_top && (target_rect.position.y + target_rect.size.y) <= visible_bottom),
|
||||
"follow_focus fully reveals focused target control vertically.");
|
||||
|
||||
memdelete(target_control);
|
||||
memdelete(content_control);
|
||||
memdelete(test_container);
|
||||
}
|
||||
|
||||
TEST_CASE("[SceneTree][ScrollContainer] Configuration warnings") {
|
||||
ScrollContainer *test_container = memnew(ScrollContainer);
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
root->add_child(test_container);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_configuration_warnings().size() == 1,
|
||||
"ScrollContainer reports one configuration warning when it has no content child.");
|
||||
|
||||
Control *child_control_1 = memnew(Control);
|
||||
Control *child_control_2 = memnew(Control);
|
||||
test_container->add_child(child_control_1);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_configuration_warnings().is_empty(),
|
||||
"ScrollContainer reports no configuration warning when it has exactly one content child.");
|
||||
|
||||
test_container->add_child(child_control_2);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
test_container->get_configuration_warnings().size() == 1,
|
||||
"ScrollContainer reports one configuration warning when it has more than one content child.");
|
||||
|
||||
memdelete(child_control_2);
|
||||
memdelete(child_control_1);
|
||||
memdelete(test_container);
|
||||
}
|
||||
|
||||
} // namespace TestScrollContainer
|
||||
Reference in new issue
Block a user