Fix layout shape hug in CPP Diffs= 35a52873c Fix layout shape hug in CPP (#7770) Co-authored-by: Philip Chung <philterdesign@gmail.com>
diff --git a/.rive_head b/.rive_head index 17eacd6..db3938f 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -949c70600a6c30bfe3ef6e59685235407af1a323 +35a52873cf0adabbda2670673762a36c91822e96
diff --git a/include/rive/shapes/parametric_path.hpp b/include/rive/shapes/parametric_path.hpp index 477b9e2..a7469fe 100644 --- a/include/rive/shapes/parametric_path.hpp +++ b/include/rive/shapes/parametric_path.hpp
@@ -12,6 +12,7 @@ float height, LayoutMeasureMode heightMode) override; void controlSize(Vec2D size) override; + void markPathDirty(bool sendToLayout = true) override; protected: void widthChanged() override;
diff --git a/include/rive/shapes/path.hpp b/include/rive/shapes/path.hpp index 59cc59b..0984138 100644 --- a/include/rive/shapes/path.hpp +++ b/include/rive/shapes/path.hpp
@@ -58,7 +58,7 @@ bool canDeferPathUpdate(); void addVertex(PathVertex* vertex); - virtual void markPathDirty(); + virtual void markPathDirty(bool sendToLayout = true); virtual bool isPathClosed() const { return true; } void onDirty(ComponentDirt dirt) override; inline bool isHidden() const { return (pathFlags() & 0x1) == 0x1; }
diff --git a/include/rive/shapes/points_path.hpp b/include/rive/shapes/points_path.hpp index fd91881..743bf9c 100644 --- a/include/rive/shapes/points_path.hpp +++ b/include/rive/shapes/points_path.hpp
@@ -10,7 +10,7 @@ bool isPathClosed() const override { return isClosed(); } void buildDependencies() override; void update(ComponentDirt value) override; - void markPathDirty() override; + void markPathDirty(bool sendToLayout = true) override; void markSkinDirty() override; const Mat2D& pathTransform() const override; };
diff --git a/include/rive/shapes/shape.hpp b/include/rive/shapes/shape.hpp index e55f794..cfb2d26 100644 --- a/include/rive/shapes/shape.hpp +++ b/include/rive/shapes/shape.hpp
@@ -69,6 +69,10 @@ AABB computeWorldBounds(const Mat2D* xform = nullptr) const; AABB computeLocalBounds() const; + Vec2D measureLayout(float width, + LayoutMeasureMode widthMode, + float height, + LayoutMeasureMode heightMode) override; }; } // namespace rive
diff --git a/src/shapes/parametric_path.cpp b/src/shapes/parametric_path.cpp index b854cdf..aa39cf3 100644 --- a/src/shapes/parametric_path.cpp +++ b/src/shapes/parametric_path.cpp
@@ -1,5 +1,8 @@ +#include "rive/layout_component.hpp" #include "rive/math/aabb.hpp" +#include "rive/node.hpp" #include "rive/shapes/parametric_path.hpp" +#include "rive/shapes/shape.hpp" using namespace rive; @@ -8,32 +11,13 @@ float height, LayoutMeasureMode heightMode) { - float measuredWidth, measuredHeight; - switch (widthMode) - { - case LayoutMeasureMode::atMost: - measuredWidth = std::max(ParametricPath::width(), width); - break; - case LayoutMeasureMode::exactly: - measuredWidth = width; - break; - case LayoutMeasureMode::undefined: - measuredWidth = ParametricPath::width(); - break; - } - switch (heightMode) - { - case LayoutMeasureMode::atMost: - measuredHeight = std::max(ParametricPath::height(), height); - break; - case LayoutMeasureMode::exactly: - measuredHeight = height; - break; - case LayoutMeasureMode::undefined: - measuredHeight = ParametricPath::height(); - break; - } - return Vec2D(measuredWidth, measuredHeight); + return Vec2D( + std::min( + (widthMode == LayoutMeasureMode::undefined ? std::numeric_limits<float>::max() : width), + ParametricPath::width()), + std::min((heightMode == LayoutMeasureMode::undefined ? std::numeric_limits<float>::max() + : height), + ParametricPath::height())); } void ParametricPath::controlSize(Vec2D size) @@ -41,6 +25,35 @@ width(size.x); height(size.y); markWorldTransformDirty(); + markPathDirty(false); +} + +void ParametricPath::markPathDirty(bool sendToLayout) +{ + Super::markPathDirty(); +#ifdef WITH_RIVE_LAYOUT + if (sendToLayout) + { + for (ContainerComponent* p = parent(); p != nullptr; p = p->parent()) + { + if (p->is<LayoutComponent>()) + { + p->as<LayoutComponent>()->markLayoutNodeDirty(); + break; + } + // If we're in a group we break out because objects in groups do + // not affect nor are affected by parent LayoutComponents + if (p->is<Node>()) + { + if (p->is<Shape>() && p->as<Shape>() == shape()) + { + continue; + } + break; + } + } + } +#endif } void ParametricPath::widthChanged() { markPathDirty(); }
diff --git a/src/shapes/path.cpp b/src/shapes/path.cpp index f5898fe..44784db 100644 --- a/src/shapes/path.cpp +++ b/src/shapes/path.cpp
@@ -228,7 +228,7 @@ } } -void Path::markPathDirty() +void Path::markPathDirty(bool sendToLayout) { addDirt(ComponentDirt::Path); if (m_Shape != nullptr)
diff --git a/src/shapes/points_path.cpp b/src/shapes/points_path.cpp index a23b0ca..5795357 100644 --- a/src/shapes/points_path.cpp +++ b/src/shapes/points_path.cpp
@@ -37,7 +37,7 @@ Super::update(value); } -void PointsPath::markPathDirty() +void PointsPath::markPathDirty(bool sendToLayout) { if (skin() != nullptr) {
diff --git a/src/shapes/shape.cpp b/src/shapes/shape.cpp index d69648b..68ccf59 100644 --- a/src/shapes/shape.cpp +++ b/src/shapes/shape.cpp
@@ -302,4 +302,18 @@ const Mat2D& world = worldTransform(); Mat2D inverseWorld = world.invertOrIdentity(); return computeWorldBounds(&inverseWorld); +} + +Vec2D Shape::measureLayout(float width, + LayoutMeasureMode widthMode, + float height, + LayoutMeasureMode heightMode) +{ + Vec2D size = Vec2D(); + for (auto path : m_Paths) + { + Vec2D measured = path->measureLayout(width, widthMode, height, heightMode); + size = Vec2D(std::max(size.x, measured.x), std::max(size.y, measured.y)); + } + return size; } \ No newline at end of file