Nugget
Loading...
Searching...
No Matches
Classes | Public Member Functions | Static Public Attributes | List of all members
psyqo::HelixSelector Class Reference

A helix selector, seen down its own axis. More...

#include <psyqo/helix-selector.hh>

Classes

struct  Config
 
struct  Cursor
 The cursor marker, as a triangle you can draw directly. More...
 
struct  Event
 
struct  Slot
 One visible item. More...
 

Public Member Functions

void setup (unsigned itemCount, const Config &config)
 
void setOnEvent (eastl::function< void(Event)> &&callback)
 
void setStickAngle (Angle a)
 Crank by an absolute stick angle.
 
void step (int32_t items)
 Crank by whole items. This is the d-pad adapter.
 
void activate ()
 Your confirm button's rising edge.
 
void update (const Trig<> &trig)
 Settle one frame and rebuild the visible slots.
 
unsigned currentIndex () const
 
unsigned visibleCount () const
 
const Slotslot (unsigned n) const
 Slot 0 is the furthest from the camera. Draw them in order.
 
const Cursorcursor () const
 Where to draw the cursor marker, just inside the ring at the cursor angle.
 
Angle cursorAngle () const
 The cursor's current angle, if you want to orient the marker you draw.
 

Static Public Attributes

static constexpr unsigned c_maxSlots = 48
 

Detailed Description

A helix selector, seen down its own axis.

Items are laid out along a helix wrapped around a cylinder, and the camera looks straight down the helix axis, so the screen shows a spiral of annular sectors.

EVERY ITEM OWNS A FIXED SPOKE. Item i sits at angle i * 2pi / itemsPerTurn and never leaves it. What the crank moves is the CURSOR, which sweeps around the circle; items slide IN AND OUT along their own spokes as it approaches or passes them. So this is a dial, not a carousel: a is always in the same place on screen, and the user gets muscle memory for free.

It follows that item i and item i + itemsPerTurn share a spoke exactly, at different radii. That is the far-side doubling that shows what is coming, and it falls out of the geometry rather than being tuned in.

It also means the analog adapter is ABSOLUTE: the stick angle IS the cursor angle. Only the lap needs unwrapping, which setStickAngle does for you.

This class owns the geometry and the selection state and nothing else. It has no idea what a glyph is, what a character is, or that capital letters exist. It hands back quad corners plus a centre point per visible item and reports what got selected or activated; drawing, atlases, casing, text buffers and what "enter" means are all yours.

The helix is infinite and the item list is CYCLIC on it: the item at helix offset d is (cursor + d) mod itemCount, so cranking never hits an end, and one turn out from the first item is whatever the atlas has last.

Member Function Documentation

◆ activate()

void psyqo::HelixSelector::activate ( )

Your confirm button's rising edge.

If the helix is still settling this snaps it to the target first and then fires, so a confirm is never swallowed mid-animation.

◆ currentIndex()

unsigned psyqo::HelixSelector::currentIndex ( ) const
inline

◆ cursor()

const Cursor & psyqo::HelixSelector::cursor ( ) const
inline

Where to draw the cursor marker, just inside the ring at the cursor angle.

◆ cursorAngle()

Angle psyqo::HelixSelector::cursorAngle ( ) const
inline

The cursor's current angle, if you want to orient the marker you draw.

◆ setOnEvent()

void psyqo::HelixSelector::setOnEvent ( eastl::function< void(Event)> &&  callback)
inline

◆ setStickAngle()

void psyqo::HelixSelector::setStickAngle ( Angle  a)

Crank by an absolute stick angle.

Feed this the raw stick direction every frame the stick is deflected enough to mean something, and simply stop calling it when it re-centres; the cursor stays where it was. The stick angle IS the cursor angle, so pointing somewhere new puts the cursor there directly. The only thing accumulated is the LAP: crossing the +/-pi seam moves you one turn along the helix rather than jumping the cursor to the far side of the dial.

◆ setup()

void psyqo::HelixSelector::setup ( unsigned  itemCount,
const Config config 
)

◆ slot()

const Slot & psyqo::HelixSelector::slot ( unsigned  n) const
inline

Slot 0 is the furthest from the camera. Draw them in order.

◆ step()

void psyqo::HelixSelector::step ( int32_t  items)
inline

Crank by whole items. This is the d-pad adapter.

◆ update()

void psyqo::HelixSelector::update ( const Trig<> &  trig)

Settle one frame and rebuild the visible slots.

◆ visibleCount()

unsigned psyqo::HelixSelector::visibleCount ( ) const
inline

Member Data Documentation

◆ c_maxSlots

constexpr unsigned psyqo::HelixSelector::c_maxSlots = 48
staticconstexpr

The documentation for this class was generated from the following files: