Avoid FlowContainer crash with TextureRect using EXPAND_FIT_* expand modes

When a FlowContainer had a TextureRect child using any of the EXPAND_FIT_* expand modes, it could crash when changing the FlowContainer's minimum size, or that of its children.  This was due to the TextureRect resizing in FlowContainer::_resort, updating its minimum size, and triggering another _resort.  If the TextureRect's minimum size changed in a way that caused any of the FlowContainer's children to be put on a different line, it could repeatedly cause _resort to be called again, moving the children back and forth between the old and new lines.

This change is for FlowContainer::_resort to give a warning for TextureRects with EXPAND_FIT_* expand modes when multiple lines are used, and just keep the TextureRect size the same in that case.  This is similar to the check added to AspectRatioContainer in godotengine#73396, but attempting to still support it in FlowContainer when possible.  In the case where the TextureRect is forced to stay the same size, there may be some overlap between the FlowContainer's children, but should no longer crash.
This commit is contained in:
aaronp64 2024-07-12 16:57:33 -04:00
parent 26d1577f39
commit 5682cc7b81

View File

@ -30,6 +30,7 @@
#include "flow_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/theme/theme_db.h"
struct _LineData {
@ -203,7 +204,23 @@ void FlowContainer::_resort() {
}
}
if (vertical) { /* VERTICAL */
bool is_unsupported_texture_rect = false;
if (lines_data.size() > 1) {
TextureRect *trect = Object::cast_to<TextureRect>(child);
if (trect) {
TextureRect::ExpandMode mode = trect->get_expand_mode();
if (mode == TextureRect::EXPAND_FIT_WIDTH || mode == TextureRect::EXPAND_FIT_WIDTH_PROPORTIONAL ||
mode == TextureRect::EXPAND_FIT_HEIGHT || mode == TextureRect::EXPAND_FIT_HEIGHT_PROPORTIONAL) {
is_unsupported_texture_rect = true;
}
}
}
if (is_unsupported_texture_rect) {
// Temporary fix for editor crash. Changing size of TextureRect with EXPAND_FIT_* ExpandModes can lead to infinite loop if child items are moved between lines.
WARN_PRINT_ONCE("TextureRects with Fit Expand Modes are currently not supported inside FlowContainers with multiple lines");
child_size = child->get_size();
} else if (vertical) { /* VERTICAL */
if (child->get_h_size_flags().has_flag(SIZE_FILL) || child->get_h_size_flags().has_flag(SIZE_SHRINK_CENTER) || child->get_h_size_flags().has_flag(SIZE_SHRINK_END)) {
child_size.width = line_data.min_line_height;
}