@@ -4,6 +4,8 @@ namespace LuaUi
44{
55 void LuaFlex::updateProperties ()
66 {
7+ mGap = propertyValue (" gap" , 0 );
8+ mWrap = propertyValue (" wrap" , false );
79 mHorizontal = propertyValue (" horizontal" , false );
810 mAutoSized = propertyValue (" autoSize" , true );
911 mAlign = propertyValue (" align" , Alignment::Start);
@@ -15,22 +17,16 @@ namespace LuaUi
1517 {
1618 int alignSize (int container, int content, Alignment alignment)
1719 {
18- int alignedPosition = 0 ;
20+ switch (alignment)
1921 {
20- switch (alignment)
21- {
22- case Alignment::Start:
23- alignedPosition = 0 ;
24- break ;
25- case Alignment::Center:
26- alignedPosition = (container - content) / 2 ;
27- break ;
28- case Alignment::End:
29- alignedPosition = container - content;
30- break ;
31- }
22+ case Alignment::Start:
23+ return 0 ;
24+ case Alignment::Center:
25+ return (container - content) / 2 ;
26+ case Alignment::End:
27+ return container - content;
3228 }
33- return alignedPosition ;
29+ return 0 ;
3430 }
3531
3632 float getGrow (WidgetExtension* w)
@@ -41,41 +37,94 @@ namespace LuaUi
4137
4238 void LuaFlex::updateChildren ()
4339 {
44- float totalGrow = 0 ;
40+ const auto & flexChildren = children ();
41+ MyGUI::IntSize flexSize = calculateSize ();
42+
4543 MyGUI::IntSize childrenSize;
46- for (auto * w : children ())
47- {
48- w->clearForced ();
49- MyGUI::IntSize size = w->calculateSize ();
50- primary (childrenSize) += primary (size);
51- secondary (childrenSize) = std::max (secondary (childrenSize), secondary (size));
52- totalGrow += getGrow (w);
53- }
54- mChildrenSize = childrenSize;
44+ int currentSecondaryAxisPosition = 0 ;
45+ size_t widgetIndex = 0 ;
5546
56- MyGUI::IntSize flexSize = calculateSize ();
57- int growSize = 0 ;
58- float growFactor = 0 ;
59- if (totalGrow > 0 )
47+ while (widgetIndex < flexChildren.size ())
6048 {
61- growSize = primary (flexSize) - primary (childrenSize);
62- growFactor = growSize / totalGrow;
63- }
49+ const size_t trackStart = widgetIndex;
50+ int primaryAxisSize = 0 ;
51+ int primaryAxisSizeRemaining = mAutoSized ? 0 : primary (flexSize);
52+ int secondaryAxisSize = 0 ;
53+ float totalPrimaryGrow = 0 ;
6454
65- MyGUI::IntPoint childPosition;
66- primary (childPosition) = alignSize (primary (flexSize) - growSize, primary (childrenSize), mAlign );
67- for (auto * w : children ())
68- {
69- MyGUI::IntSize size = w->calculateSize ();
70- primary (size) += static_cast <int >(growFactor * getGrow (w));
71- float stretch = std::clamp (w->externalValue (" stretch" , 0 .0f ), 0 .0f , 1 .0f );
72- secondary (size) = std::max (secondary (size), static_cast <int >(stretch * secondary (flexSize)));
73- secondary (childPosition) = alignSize (secondary (flexSize), secondary (size), mArrange );
74- w->forcePosition (childPosition);
75- w->forceSize (size);
76- w->updateCoord ();
77- primary (childPosition) += primary (size);
55+ while (widgetIndex < flexChildren.size ())
56+ {
57+ auto * w = flexChildren[widgetIndex];
58+ w->clearForced ();
59+
60+ const MyGUI::IntSize size = w->calculateSize ();
61+ const int childPrimary = primary (size);
62+ const int childSecondary = secondary (size);
63+ const bool notFirstOnTrack = (widgetIndex > trackStart);
64+ const int primaryToAdd = childPrimary + (notFirstOnTrack ? mGap : 0 );
65+
66+ if (!mAutoSized && mWrap && notFirstOnTrack && primaryAxisSizeRemaining < primaryToAdd)
67+ break ;
68+
69+ primaryAxisSize += primaryToAdd;
70+ if (!mAutoSized )
71+ primaryAxisSizeRemaining -= primaryToAdd;
72+ secondaryAxisSize = std::max (childSecondary, secondaryAxisSize);
73+ totalPrimaryGrow += getGrow (w);
74+ widgetIndex++;
75+ }
76+ primaryAxisSizeRemaining = std::max (0 , primaryAxisSizeRemaining);
77+
78+ if (mAutoSized )
79+ {
80+ primary (childrenSize) = std::max (primaryAxisSize, primary (childrenSize));
81+ secondary (childrenSize) += secondaryAxisSize;
82+ }
83+
84+ const int primaryAxisChildrenShift
85+ = alignSize (primaryAxisSize, primaryAxisSize - primaryAxisSizeRemaining, mAlign );
86+ int currentPrimaryAxisPosition = primaryAxisChildrenShift;
87+
88+ // Keeping a constant total here ensures widgets that use grow don't use the
89+ // changing 'primaryAxisSizeRemaining' (which shrinks as we take off grown amounts
90+ const int totalPrimaryAxisSizeRemaining = primaryAxisSizeRemaining;
91+
92+ for (size_t j = trackStart; j < widgetIndex; ++j)
93+ {
94+ auto * w = flexChildren[j];
95+ MyGUI::IntPoint widgetPosition;
96+ MyGUI::IntSize widgetSize = w->calculateSize ();
97+
98+ // Note: Grow is on the primary axis and stretch is "grow" on the cross/secondary axis
99+ const float widgetGrowFactor = getGrow (w);
100+ const float stretch = std::clamp (w->externalValue (" stretch" , 0 .0f ), 0 .0f , 1 .0f );
101+ if (widgetGrowFactor > 0 )
102+ {
103+ const int pixelsToExpandBy = std::clamp (
104+ static_cast <int >(
105+ std::round ((widgetGrowFactor / totalPrimaryGrow) * totalPrimaryAxisSizeRemaining)),
106+ 0 , primaryAxisSizeRemaining);
107+ primary (widgetSize) += pixelsToExpandBy;
108+ primaryAxisSizeRemaining -= pixelsToExpandBy;
109+ }
110+
111+ secondary (widgetSize) = std::max (secondary (widgetSize),
112+ std::clamp (static_cast <int >(std::round (stretch * secondaryAxisSize)), 0 , secondaryAxisSize));
113+
114+ primary (widgetPosition) = currentPrimaryAxisPosition;
115+ currentPrimaryAxisPosition += primary (widgetSize) + mGap ;
116+ secondary (widgetPosition)
117+ = currentSecondaryAxisPosition + alignSize (secondaryAxisSize, secondary (widgetSize), mArrange );
118+
119+ w->forceSize (widgetSize);
120+ w->forcePosition (widgetPosition);
121+ w->updateCoord ();
122+ }
123+
124+ currentSecondaryAxisPosition += secondaryAxisSize + mGap ;
78125 }
126+
127+ mChildrenSize = childrenSize;
79128 WidgetExtension::updateChildren ();
80129 }
81130
@@ -108,7 +157,7 @@ namespace LuaUi
108157 const std::vector<std::string_view>& LuaFlex::allUsedProperties () const
109158 {
110159 static std::vector<std::string_view> usedProps = std::invoke ([this ] {
111- std::vector<std::string_view> props = { " horizontal" , " autoSize" , " arrange" , " align" };
160+ std::vector<std::string_view> props = { " horizontal" , " autoSize" , " arrange" , " align" , " gap " , " wrap " };
112161 auto baseProps = WidgetExtension::allUsedProperties ();
113162 props.insert (props.end (), baseProps.begin (), baseProps.end ());
114163 return props;
0 commit comments