diff --git a/doc/classes/FlowContainer.xml b/doc/classes/FlowContainer.xml index 784a0673569..9ceb2991d8c 100644 --- a/doc/classes/FlowContainer.xml +++ b/doc/classes/FlowContainer.xml @@ -17,6 +17,20 @@ + + + The alignment of the container's children (must be one of [constant ALIGN_BEGIN], [constant ALIGN_CENTER] or [constant ALIGN_END]). + + + + Aligns children with the beginning of the container. + + + Aligns children with the center of the container. + + + Aligns children with the end of the container. + diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp index 21a107c2a3a..a708b05e7a8 100644 --- a/scene/gui/flow_container.cpp +++ b/scene/gui/flow_container.cpp @@ -155,6 +155,28 @@ void FlowContainer::_resort() { line_data = lines_data[current_line_idx]; } + // The first child of each line adds the offset caused by the alignment, + // but only if the line doesn't contain a child that expands. + if (child_idx_in_line == 0 && Math::is_equal_approx(line_data.stretch_ratio_total, 0)) { + int align_ofs = 0; + switch (align) { + case ALIGN_BEGIN: + break; + case ALIGN_CENTER: + align_ofs = line_data.stretch_avail / 2; + break; + case ALIGN_END: + align_ofs = line_data.stretch_avail; + break; + } + + if (vertical) { /* VERTICAL */ + ofs.y += align_ofs; + } else { /* HORIZONTAL */ + ofs.x += align_ofs; + } + } + if (vertical) { /* VERTICAL */ if (child->get_h_size_flags() & (SIZE_FILL | SIZE_SHRINK_CENTER | SIZE_SHRINK_END)) { child_size.width = line_data.min_line_height; @@ -241,12 +263,33 @@ int FlowContainer::get_line_count() const { return cached_line_count; } +void FlowContainer::set_alignment(AlignMode p_align) { + if (align == p_align) { + return; + } + align = p_align; + _resort(); +} + +FlowContainer::AlignMode FlowContainer::get_alignment() const { + return align; +} + FlowContainer::FlowContainer(bool p_vertical) { vertical = p_vertical; + align = ALIGN_BEGIN; cached_size = 0; cached_line_count = 0; } void FlowContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_line_count"), &FlowContainer::get_line_count); + ClassDB::bind_method(D_METHOD("get_alignment"), &FlowContainer::get_alignment); + ClassDB::bind_method(D_METHOD("set_alignment", "alignment"), &FlowContainer::set_alignment); + + BIND_ENUM_CONSTANT(ALIGN_BEGIN); + BIND_ENUM_CONSTANT(ALIGN_CENTER); + BIND_ENUM_CONSTANT(ALIGN_END); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment", "get_alignment"); } diff --git a/scene/gui/flow_container.h b/scene/gui/flow_container.h index 1a40d0f7f18..48f2f75203c 100644 --- a/scene/gui/flow_container.h +++ b/scene/gui/flow_container.h @@ -36,11 +36,19 @@ class FlowContainer : public Container { GDCLASS(FlowContainer, Container); +public: + enum AlignMode { + ALIGN_BEGIN, + ALIGN_CENTER, + ALIGN_END + }; + private: int cached_size; int cached_line_count; bool vertical; + AlignMode align; void _resort(); @@ -55,6 +63,9 @@ public: virtual Size2 get_minimum_size() const; FlowContainer(bool p_vertical = false); + + void set_alignment(AlignMode p_align); + AlignMode get_alignment() const; }; class HFlowContainer : public FlowContainer { @@ -73,4 +84,6 @@ public: FlowContainer(true) {} }; +VARIANT_ENUM_CAST(FlowContainer::AlignMode); + #endif // FLOW_CONTAINER_H