blob: 18d8999e0dd3d2eff30ab8080e79ddc201a3e2f6 [file] [log] [blame]
#ifndef _RIVE_LAYOUT_COMPONENT_HPP_
#define _RIVE_LAYOUT_COMPONENT_HPP_
#include "rive/drawable.hpp"
#include "rive/generated/layout_component_base.hpp"
#include "rive/layout/layout_component_style.hpp"
#include "rive/layout/layout_measure_mode.hpp"
#include "rive/math/raw_path.hpp"
#include "rive/shapes/rectangle.hpp"
#include "rive/shapes/shape_paint_container.hpp"
#ifdef WITH_RIVE_LAYOUT
#include "yoga/YGNode.h"
#include "yoga/YGStyle.h"
#include "yoga/Yoga.h"
#endif
namespace rive
{
class AABB;
class KeyFrameInterpolator;
struct LayoutData
{
#ifdef WITH_RIVE_LAYOUT
YGNode node;
YGStyle style;
#endif
};
struct LayoutAnimationData
{
float elapsedSeconds = 0;
AABB fromBounds = AABB();
AABB toBounds = AABB();
};
class LayoutComponent : public LayoutComponentBase, public ProxyDrawing, public ShapePaintContainer
{
protected:
LayoutComponentStyle* m_style = nullptr;
std::unique_ptr<LayoutData> m_layoutData;
float m_layoutSizeWidth = 0;
float m_layoutSizeHeight = 0;
float m_layoutLocationX = 0;
float m_layoutLocationY = 0;
LayoutAnimationData m_animationData;
KeyFrameInterpolator* m_inheritedInterpolator;
LayoutStyleInterpolation m_inheritedInterpolation = LayoutStyleInterpolation::hold;
float m_inheritedInterpolationTime = 0;
Rectangle* m_backgroundRect = new Rectangle();
rcp<RenderPath> m_backgroundPath;
rcp<RenderPath> m_clipPath;
DrawableProxy m_proxy;
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:
float m_widthOverride = NAN;
int m_widthUnitValueOverride = -1;
float m_heightOverride = NAN;
int m_heightUnitValueOverride = -1;
bool m_parentIsRow = true;
#ifdef WITH_RIVE_LAYOUT
protected:
YGNode& layoutNode() { return m_layoutData->node; }
YGStyle& layoutStyle() { return m_layoutData->style; }
void syncLayoutChildren();
void propagateSizeToChildren(ContainerComponent* component);
bool applyInterpolation(double elapsedSeconds);
protected:
void calculateLayout();
#endif
public:
LayoutComponentStyle* style() { return m_style; }
void style(LayoutComponentStyle* style) { m_style = style; }
void draw(Renderer* renderer) override;
void drawProxy(Renderer* renderer) override;
Core* hitTest(HitInfo*, const Mat2D&) override;
DrawableProxy* proxy() { return &m_proxy; };
virtual void updateRenderPath();
void update(ComponentDirt value) override;
void onDirty(ComponentDirt value) override;
AABB layoutBounds()
{
return AABB::fromLTWH(m_layoutLocationX,
m_layoutLocationY,
m_layoutSizeWidth,
m_layoutSizeHeight);
}
AABB localBounds() const override
{
return AABB::fromLTWH(0.0f, 0.0f, m_layoutSizeWidth, m_layoutSizeHeight);
}
// We provide a way for nested artboards (or other objects) to override this layout's
// width/height and unit values.
void widthOverride(float width, int unitValue = 1, bool isRow = true);
void heightOverride(float height, int unitValue = 1, bool isRow = true);
virtual bool canHaveOverrides() { return false; }
bool mainAxisIsRow();
bool mainAxisIsColumn();
#ifdef WITH_RIVE_LAYOUT
LayoutComponent() : m_layoutData(std::unique_ptr<LayoutData>(new LayoutData())), m_proxy(this)
{
layoutNode().getConfig()->setPointScaleFactor(0);
}
~LayoutComponent() { delete m_backgroundRect; }
void syncStyle();
virtual void propagateSize();
void updateLayoutBounds();
StatusCode onAddedDirty(CoreContext* context) override;
StatusCode onAddedClean(CoreContext* context) override;
bool advance(double elapsedSeconds);
bool animates();
LayoutAnimationStyle animationStyle();
KeyFrameInterpolator* interpolator();
LayoutStyleInterpolation interpolation();
float interpolationTime();
void cascadeAnimationStyle(LayoutStyleInterpolation inheritedInterpolation,
KeyFrameInterpolator* inheritedInterpolator,
float inheritedInterpolationTime);
void setInheritedInterpolation(LayoutStyleInterpolation inheritedInterpolation,
KeyFrameInterpolator* inheritedInterpolator,
float inheritedInterpolationTime);
void clearInheritedInterpolation();
#else
LayoutComponent() : m_layoutData(std::unique_ptr<LayoutData>(new LayoutData())), m_proxy(this)
{}
#endif
void buildDependencies() override;
void markLayoutNodeDirty();
void markLayoutStyleDirty();
void clipChanged() override;
void widthChanged() override;
void heightChanged() override;
void styleIdChanged() override;
Vec2D measureLayout(float width,
LayoutMeasureMode widthMode,
float height,
LayoutMeasureMode heightMode) override;
};
} // namespace rive
#endif