MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ track()

Scrollable & MayaFlux::Portal::Forma::Scrollable::track ( Layer &  layer,
uint32_t  id,
Kinesis::AABB2D  base_bounds,
std::function< void(Kinesis::AABB2D)>  reposition,
const FormaTarget &  clip_buf = {} 
)

Register an element for scroll reflow.

Expands scroll->content_bounds to include base_bounds, so the clamp in scroll_by() always reflects everything tracked so far - no manual content-height bookkeeping needed. On every scroll, this element's bounds_hint is updated to base_bounds.translated(offset) and reposition is called with that same shifted region: reposition owns whatever resubmission its own content needs (a raw buffer resubmit, rebuilding a Mapped<T>'s geometry, anything). Scrollable does not inspect or constrain what kind of content id is.

base_bounds is normalized against the current offset before it is stored, so it is always safe to pass cursor_out.advance()'s return directly - that return is already shifted by whatever offset is live right now (that is the whole point of LayoutCursor::bind_scroll: an element placed after scrolling already happened lands in the right spot immediately). Without this normalization an element tracked while scrolled would have that offset baked into its anchor and drift further out of place on every scroll after.

Parameters
layerLayer both the viewport and id were registered on. relate()s id under viewport_id so a cascading Layer::remove(viewport_id) tears this element down too - no separate tracked-ids bookkeeping needed.
idElement id, already registered on the same Layer place() used.
base_boundsThis element's current on-screen NDC bounds - the direct return of cursor_out.advance(), scrolled or not.
repositionCalled with the scrolled bounds on every scroll.
clip_bufOptional. When given, Kinesis::Scissor::from(viewport_bounds) is set on its render processor immediately, so the element is clipped to the viewport from the start.
Returns
*this, so place()/track()/indicator() can chain into one expression for the common case of a single tracked item - see Portal::Forma::TextField::scrollable() for exactly that.

Definition at line 98 of file Scrollable.cpp.

104{
105 if (!scroll || !m_tracked)
106 return *this;
107
108 base_bounds = base_bounds.translated(-scroll->offset);
109
110 scroll->content_bounds.min = glm::min(scroll->content_bounds.min, base_bounds.min);
111 scroll->content_bounds.max = glm::max(scroll->content_bounds.max, base_bounds.max);
112
113 if (clip_buf) {
114 if (auto render = clip_buf->get_render_processor())
115 render->set_scissor(Kinesis::Scissor::from(viewport_bounds));
116 }
117
118 layer.relate(viewport_id, id);
119
120 m_tracked->push_back({ .id = id, .base_bounds = base_bounds, .reposition = std::move(reposition) });
121 layer.set_clip(id, viewport_bounds);
122
123 if (m_indicator && m_indicator->state) {
124 m_indicator->state->write(scroll_extent(*scroll));
125 m_indicator->sync();
126 }
127
128 return *this;
129}
static Scissor from(AABB2D ndc_bounds) noexcept
Construct directly from an NDC AABB2D.
Definition Scissor.hpp:37
Kinesis::AABB2D viewport_bounds
NDC region occupied by the viewport. Valid after place().
std::shared_ptr< Mapped< glm::vec2 > > m_indicator
uint32_t viewport_id
Element id of the viewport background. Valid after place().
std::shared_ptr< std::vector< Tracked > > m_tracked
std::shared_ptr< Kinesis::ScrollState > scroll
Clamped scroll offset and content/viewport extents. Valid after place().

References MayaFlux::Kinesis::Scissor::from(), MayaFlux::Buffers::VKBuffer::get_render_processor(), m_indicator, m_tracked, MayaFlux::Kinesis::AABB2D::max, MayaFlux::Kinesis::AABB2D::min, MayaFlux::Portal::Forma::Layer::relate(), scroll, MayaFlux::Portal::Forma::Layer::set_clip(), MayaFlux::Kinesis::AABB2D::translated(), viewport_bounds, and viewport_id.

Referenced by indicator(), and MayaFlux::Portal::Forma::TextField::scrollable().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: