Implement layout scale type in CPP runtime This PR includes 2 updates: 1. Break out the layout scaleType bitfield property into seperate width and height scale properties. This will allow us to animate these properties easily in the future 2. Implement the logic based on scale type in CPP runtime. @alxgibsn This fixes the issues you observed in runtimes where the` fill` scale type wasn't working properly and layout children sizing wasn't consistent between editor and runtimes. Diffs= 1c067cba8 Implement layout scale type in CPP runtime (#7665) Co-authored-by: Philip Chung <philterdesign@gmail.com>
diff --git a/.rive_head b/.rive_head index 0ec88f5..2080b43 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -da1bb77455deeafd48012a8eea5ea946a718fb77 +1c067cba8e291859c02a6d00dfe68033cf3cda8f
diff --git a/dev/defs/layout/layout_component_style.json b/dev/defs/layout/layout_component_style.json index cb46d46..d96f7af 100644 --- a/dev/defs/layout/layout_component_style.json +++ b/dev/defs/layout/layout_component_style.json
@@ -317,12 +317,20 @@ }, "runtime": false }, - "scaleType": { + "layoutWidthScaleType": { "type": "uint", "initialValue": "0", "key": { - "int": 546, - "string": "scaletype" + "int": 655, + "string": "layoutwidthscaletype" + } + }, + "layoutHeightScaleType": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 656, + "string": "layoutheightscaletype" } }, "layoutAlignmentType": {
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index 7abe2d5..9563b20 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp
@@ -651,8 +651,11 @@ case SoloBase::activeComponentIdPropertyKey: object->as<SoloBase>()->activeComponentId(value); break; - case LayoutComponentStyleBase::scaleTypePropertyKey: - object->as<LayoutComponentStyleBase>()->scaleType(value); + case LayoutComponentStyleBase::layoutWidthScaleTypePropertyKey: + object->as<LayoutComponentStyleBase>()->layoutWidthScaleType(value); + break; + case LayoutComponentStyleBase::layoutHeightScaleTypePropertyKey: + object->as<LayoutComponentStyleBase>()->layoutHeightScaleType(value); break; case LayoutComponentStyleBase::layoutAlignmentTypePropertyKey: object->as<LayoutComponentStyleBase>()->layoutAlignmentType(value); @@ -1734,8 +1737,10 @@ return object->as<NestedAnimationBase>()->animationId(); case SoloBase::activeComponentIdPropertyKey: return object->as<SoloBase>()->activeComponentId(); - case LayoutComponentStyleBase::scaleTypePropertyKey: - return object->as<LayoutComponentStyleBase>()->scaleType(); + case LayoutComponentStyleBase::layoutWidthScaleTypePropertyKey: + return object->as<LayoutComponentStyleBase>()->layoutWidthScaleType(); + case LayoutComponentStyleBase::layoutHeightScaleTypePropertyKey: + return object->as<LayoutComponentStyleBase>()->layoutHeightScaleType(); case LayoutComponentStyleBase::layoutAlignmentTypePropertyKey: return object->as<LayoutComponentStyleBase>()->layoutAlignmentType(); case LayoutComponentStyleBase::animationStyleTypePropertyKey: @@ -2439,7 +2444,8 @@ case NestedArtboardBase::artboardIdPropertyKey: case NestedAnimationBase::animationIdPropertyKey: case SoloBase::activeComponentIdPropertyKey: - case LayoutComponentStyleBase::scaleTypePropertyKey: + case LayoutComponentStyleBase::layoutWidthScaleTypePropertyKey: + case LayoutComponentStyleBase::layoutHeightScaleTypePropertyKey: case LayoutComponentStyleBase::layoutAlignmentTypePropertyKey: case LayoutComponentStyleBase::animationStyleTypePropertyKey: case LayoutComponentStyleBase::interpolationTypePropertyKey: @@ -2888,7 +2894,9 @@ return object->is<NestedAnimationBase>(); case SoloBase::activeComponentIdPropertyKey: return object->is<SoloBase>(); - case LayoutComponentStyleBase::scaleTypePropertyKey: + case LayoutComponentStyleBase::layoutWidthScaleTypePropertyKey: + return object->is<LayoutComponentStyleBase>(); + case LayoutComponentStyleBase::layoutHeightScaleTypePropertyKey: return object->is<LayoutComponentStyleBase>(); case LayoutComponentStyleBase::layoutAlignmentTypePropertyKey: return object->is<LayoutComponentStyleBase>();
diff --git a/include/rive/generated/layout/layout_component_style_base.hpp b/include/rive/generated/layout/layout_component_style_base.hpp index a6f0cb5..13003f5 100644 --- a/include/rive/generated/layout/layout_component_style_base.hpp +++ b/include/rive/generated/layout/layout_component_style_base.hpp
@@ -57,7 +57,8 @@ static const uint16_t flexShrinkPropertyKey = 522; static const uint16_t flexBasisPropertyKey = 523; static const uint16_t aspectRatioPropertyKey = 524; - static const uint16_t scaleTypePropertyKey = 546; + static const uint16_t layoutWidthScaleTypePropertyKey = 655; + static const uint16_t layoutHeightScaleTypePropertyKey = 656; static const uint16_t layoutAlignmentTypePropertyKey = 632; static const uint16_t animationStyleTypePropertyKey = 589; static const uint16_t interpolationTypePropertyKey = 590; @@ -132,7 +133,8 @@ float m_FlexShrink = 1.0f; float m_FlexBasis = 1.0f; float m_AspectRatio = 0.0f; - uint32_t m_ScaleType = 0; + uint32_t m_LayoutWidthScaleType = 0; + uint32_t m_LayoutHeightScaleType = 0; uint32_t m_LayoutAlignmentType = 0; uint32_t m_AnimationStyleType = 0; uint32_t m_InterpolationType = 0; @@ -477,15 +479,26 @@ aspectRatioChanged(); } - inline uint32_t scaleType() const { return m_ScaleType; } - void scaleType(uint32_t value) + inline uint32_t layoutWidthScaleType() const { return m_LayoutWidthScaleType; } + void layoutWidthScaleType(uint32_t value) { - if (m_ScaleType == value) + if (m_LayoutWidthScaleType == value) { return; } - m_ScaleType = value; - scaleTypeChanged(); + m_LayoutWidthScaleType = value; + layoutWidthScaleTypeChanged(); + } + + inline uint32_t layoutHeightScaleType() const { return m_LayoutHeightScaleType; } + void layoutHeightScaleType(uint32_t value) + { + if (m_LayoutHeightScaleType == value) + { + return; + } + m_LayoutHeightScaleType = value; + layoutHeightScaleTypeChanged(); } inline uint32_t layoutAlignmentType() const { return m_LayoutAlignmentType; } @@ -1013,7 +1026,8 @@ m_FlexShrink = object.m_FlexShrink; m_FlexBasis = object.m_FlexBasis; m_AspectRatio = object.m_AspectRatio; - m_ScaleType = object.m_ScaleType; + m_LayoutWidthScaleType = object.m_LayoutWidthScaleType; + m_LayoutHeightScaleType = object.m_LayoutHeightScaleType; m_LayoutAlignmentType = object.m_LayoutAlignmentType; m_AnimationStyleType = object.m_AnimationStyleType; m_InterpolationType = object.m_InterpolationType; @@ -1147,8 +1161,11 @@ case aspectRatioPropertyKey: m_AspectRatio = CoreDoubleType::deserialize(reader); return true; - case scaleTypePropertyKey: - m_ScaleType = CoreUintType::deserialize(reader); + case layoutWidthScaleTypePropertyKey: + m_LayoutWidthScaleType = CoreUintType::deserialize(reader); + return true; + case layoutHeightScaleTypePropertyKey: + m_LayoutHeightScaleType = CoreUintType::deserialize(reader); return true; case layoutAlignmentTypePropertyKey: m_LayoutAlignmentType = CoreUintType::deserialize(reader); @@ -1317,7 +1334,8 @@ virtual void flexShrinkChanged() {} virtual void flexBasisChanged() {} virtual void aspectRatioChanged() {} - virtual void scaleTypeChanged() {} + virtual void layoutWidthScaleTypeChanged() {} + virtual void layoutHeightScaleTypeChanged() {} virtual void layoutAlignmentTypeChanged() {} virtual void animationStyleTypeChanged() {} virtual void interpolationTypeChanged() {}
diff --git a/include/rive/layout/layout_component_style.hpp b/include/rive/layout/layout_component_style.hpp index 6327414..cab31c9 100644 --- a/include/rive/layout/layout_component_style.hpp +++ b/include/rive/layout/layout_component_style.hpp
@@ -38,6 +38,13 @@ spaceBetweenEnd }; +enum class LayoutScaleType : uint8_t +{ + fixed, + fill, + hug +}; + class KeyFrameInterpolator; class LayoutComponentStyle : public LayoutComponentStyleBase { @@ -57,6 +64,8 @@ YGDisplay display(); YGPositionType positionType(); LayoutAlignmentType alignmentType(); + LayoutScaleType widthScaleType(); + LayoutScaleType heightScaleType(); YGFlexDirection flexDirection(); YGDirection direction(); @@ -100,6 +109,8 @@ void markLayoutStyleDirty(); void layoutAlignmentTypeChanged() override; + void layoutWidthScaleTypeChanged() override; + void layoutHeightScaleTypeChanged() override; void displayValueChanged() override; void positionTypeValueChanged() override; void overflowValueChanged() override;
diff --git a/include/rive/layout_component.hpp b/include/rive/layout_component.hpp index c0c4bdb..b39a9c3 100644 --- a/include/rive/layout_component.hpp +++ b/include/rive/layout_component.hpp
@@ -56,6 +56,20 @@ Artboard* getArtboard() override { return artboard(); } + LayoutComponent* layoutParent() + { + auto p = parent(); + while (p != nullptr) + { + if (p->is<LayoutComponent>()) + { + return p->as<LayoutComponent>(); + } + p = p->parent(); + } + return nullptr; + } + private: #ifdef WITH_RIVE_LAYOUT protected:
diff --git a/src/layout/layout_component_style.cpp b/src/layout/layout_component_style.cpp index a9310be..504a5bb 100644 --- a/src/layout/layout_component_style.cpp +++ b/src/layout/layout_component_style.cpp
@@ -25,6 +25,16 @@ return LayoutAlignmentType(layoutAlignmentType()); } +LayoutScaleType LayoutComponentStyle::widthScaleType() +{ + return LayoutScaleType(layoutWidthScaleType()); +} + +LayoutScaleType LayoutComponentStyle::heightScaleType() +{ + return LayoutScaleType(layoutHeightScaleType()); +} + YGDisplay LayoutComponentStyle::display() { return YGDisplay(displayValue()); } YGPositionType LayoutComponentStyle::positionType() { return YGPositionType(positionTypeValue()); } @@ -133,6 +143,8 @@ #endif void LayoutComponentStyle::layoutAlignmentTypeChanged() { markLayoutNodeDirty(); } +void LayoutComponentStyle::layoutWidthScaleTypeChanged() { markLayoutNodeDirty(); } +void LayoutComponentStyle::layoutHeightScaleTypeChanged() { markLayoutNodeDirty(); } void LayoutComponentStyle::displayValueChanged() { markLayoutNodeDirty(); } void LayoutComponentStyle::positionTypeValueChanged() { markLayoutNodeDirty(); } void LayoutComponentStyle::overflowValueChanged() { markLayoutNodeDirty(); }
diff --git a/src/layout_component.cpp b/src/layout_component.cpp index 872e88e..a032d8a 100644 --- a/src/layout_component.cpp +++ b/src/layout_component.cpp
@@ -241,6 +241,75 @@ ygStyle.dimensions()[YGDimensionHeight] = YGValueAuto; } + if (layoutParent() != nullptr) + { + bool isRow = layoutParent()->style()->flexDirection() == YGFlexDirectionRow || + layoutParent()->style()->flexDirection() == YGFlexDirectionRowReverse; + switch (m_style->widthScaleType()) + { + case LayoutScaleType::fixed: + if (isRow) + { + ygStyle.flexGrow() = YGFloatOptional(0); + } + break; + case LayoutScaleType::fill: + if (isRow) + { + ygStyle.flexGrow() = YGFloatOptional(1); + } + else + { + ygStyle.alignSelf() = YGAlignStretch; + } + break; + case LayoutScaleType::hug: + if (isRow) + { + ygStyle.flexGrow() = YGFloatOptional(0); + } + else + { + ygStyle.alignSelf() = YGAlignAuto; + } + break; + default: + break; + } + bool isColumn = !isRow; + switch (m_style->heightScaleType()) + { + case LayoutScaleType::fixed: + if (isColumn) + { + ygStyle.flexGrow() = YGFloatOptional(0); + } + break; + case LayoutScaleType::fill: + if (isColumn) + { + ygStyle.flexGrow() = YGFloatOptional(1); + } + else + { + ygStyle.alignSelf() = YGAlignStretch; + } + break; + case LayoutScaleType::hug: + if (isColumn) + { + ygStyle.flexGrow() = YGFloatOptional(0); + } + else + { + ygStyle.alignSelf() = YGAlignAuto; + } + break; + default: + break; + } + } + bool isRowForAlignment = m_style->flexDirection() == YGFlexDirectionRow || m_style->flexDirection() == YGFlexDirectionRowReverse; switch (m_style->alignmentType()) @@ -364,15 +433,8 @@ ygStyle.display() = m_style->display(); ygStyle.positionType() = m_style->positionType(); ygStyle.flex() = YGFloatOptional(m_style->flex()); - ygStyle.flexGrow() = YGFloatOptional(m_style->flexGrow()); - ygStyle.flexShrink() = YGFloatOptional(m_style->flexShrink()); - // ygStyle.flexBasis() = m_style->flexBasis(); ygStyle.flexDirection() = m_style->flexDirection(); ygStyle.flexWrap() = m_style->flexWrap(); - // ygStyle.alignItems() = m_style->alignItems(); - // ygStyle.alignContent() = m_style->alignContent(); - ygStyle.alignSelf() = m_style->alignSelf(); - // ygStyle.justifyContent() = m_style->justifyContent(); ygNode.setStyle(ygStyle); }