blob: b76c7e8914a90810301cf6fe51996acdb518ff30 [file]
#ifndef _RIVE_SCROLL_CONSTRAINT_HPP_
#define _RIVE_SCROLL_CONSTRAINT_HPP_
#include "rive/generated/constraints/scrolling/scroll_constraint_base.hpp"
#include "rive/advance_flags.hpp"
#include "rive/advancing_component.hpp"
#include "rive/constraints/layout_constraint.hpp"
#include "rive/constraints/scrolling/scroll_physics.hpp"
#include "rive/layout_component.hpp"
#include "rive/math/math_types.hpp"
#include "rive/math/transform_components.hpp"
#include <stdio.h>
namespace rive
{
class LayoutNodeProvider;
class ScrollVirtualizer;
class ScrollConstraint : public ScrollConstraintBase,
public AdvancingComponent,
public LayoutConstraint
{
private:
ScrollPhysics* m_physics;
ScrollVirtualizer* m_virtualizer = nullptr;
std::vector<LayoutNodeProvider*> m_layoutChildren;
TransformComponents m_componentsA;
TransformComponents m_componentsB;
Mat2D m_scrollTransform;
float m_offsetX = 0;
float m_offsetY = 0;
float m_lastFrameOffsetX = 0;
float m_lastFrameOffsetY = 0;
int m_childConstraintAppliedCount = 0;
bool m_isDragging = false;
bool m_isScrollBarDragging = false;
bool m_hasListChildren = false;
AABB boundsForFlatIndex(size_t index);
Vec2D positionAtIndex(float index);
float indexAtPosition(Vec2D pos);
float maxOffsetXForPercent();
float maxOffsetYForPercent();
bool isBoundsCollapsed(AABB bounds);
std::vector<Vec2D> collectSnapPoints();
public:
~ScrollConstraint();
void constrain(TransformComponent* component) override;
std::vector<DraggableProxy*> draggables() override;
void buildDependencies() override;
StatusCode import(ImportStack& importStack) override;
StatusCode onAddedDirty(CoreContext* context) override;
Core* clone() const override;
void dragView(Vec2D delta, float timeStamp);
void runPhysics();
void constrainChild(LayoutNodeProvider* child) override;
void addLayoutChild(LayoutNodeProvider* child) override;
Constraint* constraint() override { return this; }
void constrainVirtualized(bool force = false);
bool advanceComponent(float elapsedSeconds,
AdvanceFlags flags = AdvanceFlags::Animate |
AdvanceFlags::NewFrame) override;
ScrollPhysics* physics() const { return m_physics; }
void physics(ScrollPhysics* physics) { m_physics = physics; }
void initPhysics();
void stopPhysics();
void clearVelocity();
ScrollPhysicsType physicsType() const
{
return ScrollPhysicsType(physicsTypeValue());
}
LayoutComponent* content() { return parent()->as<LayoutComponent>(); }
LayoutComponent* viewport()
{
return parent()->parent()->as<LayoutComponent>();
}
float contentWidth();
float contentHeight();
float viewportWidth();
float viewportHeight();
float visibleWidthRatio();
float visibleHeightRatio();
float minOffsetX();
float minOffsetY();
float maxOffsetX();
float maxOffsetY();
float clampedOffsetX();
float clampedOffsetY();
float offsetX() { return m_offsetX; }
float offsetY() { return m_offsetY; }
void offsetX(float value);
void offsetY(float value);
void scrollOffsetXChanged() override { offsetX(scrollOffsetX()); }
void scrollOffsetYChanged() override { offsetY(scrollOffsetY()); }
float scrollPercentX() override;
float scrollPercentY() override;
float scrollIndex() override;
void setScrollPercentX(float value) override;
void setScrollPercentY(float value) override;
void setScrollIndex(float value) override;
float velocityX() override;
float velocityY() override;
void setVelocityX(float value) override {}
void setVelocityY(float value) override {}
bool scrollActive() override;
void setScrollActive(bool value) override {}
bool isScrollBarDragging() const { return m_isScrollBarDragging; }
void isScrollBarDragging(bool value)
{
if (!m_isScrollBarDragging && value)
{
// Prime the snapshot so the first advance comparison is
// meaningful (otherwise a stale value falsely flags motion).
m_lastFrameOffsetX = scrollOffsetX();
m_lastFrameOffsetY = scrollOffsetY();
}
m_isScrollBarDragging = value;
}
size_t scrollItemCount();
std::vector<LayoutNodeProvider*>& scrollChildren()
{
return m_layoutChildren;
}
Vec2D gap();
bool mainAxisIsColumn();
/// Animate scroll to the target position using the physics settling
/// animation.
void scrollToPosition(float targetX, float targetY);
/// Given a target offset reached by scrolling from current, return the
/// nearest snap offset in the direction of travel, or target unchanged
/// if snap() is false, no snap points exist, or none lie in the scroll
/// direction. The returned snap is at least as far as target — so an
/// element brought into view by target stays in view.
Vec2D nearestSnapOffsetInDirection(Vec2D current, Vec2D target);
/// Get the effective scroll offset X (target if animating, current
/// otherwise). Use this to check element visibility during rapid focus
/// changes.
float effectiveScrollOffsetX();
/// Get the effective scroll offset Y (target if animating, current
/// otherwise). Use this to check element visibility during rapid focus
/// changes.
float effectiveScrollOffsetY();
};
} // namespace rive
#endif