39 # error This is a userspace-only header, not allowed by the current build.
42 #include <sifteo/menu/types.h>
51 inline void Menu::changeState(
MenuState newstate)
53 stateFinished =
false;
54 currentState = newstate;
56 MENU_LOG(
"STATE: -> ");
57 switch(currentState) {
58 case MENU_STATE_START:
62 case MENU_STATE_STATIC:
66 case MENU_STATE_TILTING:
67 MENU_LOG(
"tilting\n");
70 case MENU_STATE_INERTIA:
71 MENU_LOG(
"inertia\n");
74 case MENU_STATE_FINISH:
78 case MENU_STATE_HOP_UP:
82 case MENU_STATE_PAN_TARGET:
83 MENU_LOG(
"pan target\n");
99 inline void Menu::transToStart()
104 inline void Menu::stateStart()
109 vid->bg0.erase(*assets->background);
113 const AssetImage& label = items[startingItem].label ? *items[startingItem].label : *assets->header;
114 vid->bg1.fillMask(
vec(0,0), label.tileSize());
115 vid->bg1.image(
vec(0,0), label);
120 const AssetImage& footer = assets->tips[0] ? *assets->tips[0] : *assets->footer;
121 Int2 topLeft = { 0, kNumVisibleTilesY - footer.tileHeight() };
122 vid->bg1.fillMask(topLeft, footer.tileSize());
123 vid->bg1.image(topLeft, footer);
131 stateFinished =
true;
134 inline void Menu::transFromStart()
142 hasBeenStarted =
true;
144 position = stoppingPositionFor(startingItem);
145 prev_ut = computeCurrentTile() + kNumTilesX;
149 neighbors[i].neighborSide =
NO_SIDE;
151 neighbors[i].masterSide =
NO_SIDE;
155 targetItem != -1 && startingItem != targetItem ?
156 MENU_STATE_PAN_TARGET :
175 inline void Menu::transToStatic()
178 prevTouch = vid->cube().isTouching();
180 currentEvent.type = MENU_ITEM_ARRIVE;
181 currentEvent.item = computeSelected();
185 const AssetImage& label = items[currentEvent.item].label ? *items[currentEvent.item].label : *assets->header;
186 vid->bg1.image(
vec(0,0), label);
190 inline void Menu::stateStatic()
195 inline void Menu::transFromStatic()
197 if (
abs(accel.x) < kAccelThresholdOn || isTiltingAtEdge()) {
201 changeState(MENU_STATE_TILTING);
203 currentEvent.type = MENU_ITEM_DEPART;
204 currentEvent.direction = accel.x > 0 ? 1 : -1;
208 const AssetImage& label = *assets->header;
209 vid->bg1.image(
vec(0,0), label);
223 inline void Menu::transToTilting()
225 ASSERT(
abs(accel.x) > kAccelThresholdOn);
228 inline void Menu::stateTilting()
231 const int max_x = stoppingPositionFor(numItems - 1);
232 const float kInertiaThreshold = 10.f;
234 velocity += (accel.x * frameclock.delta() * kTimeDilator) * velocityMultiplier();
237 if (
abs(velocity) > maxVelocity()) {
238 velocity = (velocity < 0 ? 0 - maxVelocity() : maxVelocity());
242 if ((position > 0.f && velocity < 0) || (position < max_x && velocity > 0) ||
abs(velocity) > kInertiaThreshold) {
243 position += velocity * frameclock.delta() * kTimeDilator;
250 inline void Menu::transFromTilting()
252 const bool outOfBounds = (position < -0.05f) || (position > kItemPixelWidth()*(numItems-1) + kEndCapPadding + 0.05f);
253 if (
abs(accel.x) < kAccelThresholdOff || outOfBounds) {
254 changeState(MENU_STATE_INERTIA);
269 inline void Menu::transToInertia()
271 stopping_position = stoppingPositionFor(computeSelected());
272 if (
abs(accel.x) > kAccelThresholdOff) {
273 tiltDirection = (kAccelScalingFactor * accel.x < 0) ? 1 : -1;
279 inline void Menu::stateInertia()
283 const float stiffness = 0.333f;
286 if (
abs(accel.x) < kAccelThresholdOff) {
290 if ((tiltDirection < 0 && velocity >= 0.f) || (tiltDirection > 0 && velocity <= 0.f)) {
294 velocity += stopping_position - position;
295 velocity *= stiffness;
296 position += velocity * frameclock.delta() * kTimeDilator;
297 position = lerp(position, stopping_position, 0.15f);
299 stateFinished =
abs(velocity) < 1.0f &&
abs(stopping_position - position) < 0.5f;
302 position = stopping_position;
308 inline void Menu::transFromInertia()
310 if (
abs(accel.x) > kAccelThresholdOn &&
311 !((tiltDirection < 0 && accel.x < 0.f) || (tiltDirection > 0 && accel.x > 0.f))) {
312 changeState(MENU_STATE_TILTING);
315 changeState(MENU_STATE_STATIC);
330 inline void Menu::transToFinish()
338 vid->bg0.setPanning(
vec(0, 0));
339 vid->bg0.erase(*assets->background);
341 if (assets->header) {
343 vid->bg0.image(vec, *assets->header);
345 if (assets->footer) {
346 Int2 vec = { 0, kNumVisibleTilesY - assets->footer->tileHeight() };
347 vid->bg0.image(vec, *assets->footer);
350 const AssetImage* icon = items[computeSelected()].icon;
351 vid->bg1.eraseMask();
352 vid->bg1.fillMask(
vec(0,0), icon->tileSize());
353 vid->bg1.image(
vec(0,0), *icon);
356 currentEvent.type = MENU_PREPAINT;
359 inline void Menu::stateFinish()
365 float u = finishIteration/33.f;
367 offset = int(12*(1.f-u*u));
368 vid->bg1.setPanning(
vec(-kEndCapPadding, offset + kIconYOffset));
369 currentEvent.type = MENU_PREPAINT;
371 if (offset <= -128) {
372 currentEvent.type = MENU_EXIT;
373 currentEvent.item = computeSelected();
374 stateFinished =
true;
378 inline void Menu::transFromFinish()
382 changeState(MENU_STATE_START);
403 inline void Menu::transToHopUp()
407 vid->bg0.setPanning(
vec(0, 0));
408 vid->bg0.erase(*assets->background);
410 if (assets->header) {
412 vid->bg0.image(vec, *assets->header);
414 if (assets->footer) {
415 Int2 vec = { 0, kNumVisibleTilesY - assets->footer->tileHeight() };
416 vid->bg0.image(vec, *assets->footer);
419 const AssetImage* icon = items[computeSelected()].icon;
420 vid->bg1.eraseMask();
421 vid->bg1.fillMask(
vec(0,0), icon->tileSize());
422 vid->bg1.image(
vec(0,0), *icon);
424 finishIteration = 30;
426 hasBeenStarted =
true;
429 inline void Menu::stateHopUp()
435 float u = finishIteration/33.f;
437 offset = int(12*(1.f-u*u));
438 vid->bg1.setPanning(
vec(-kEndCapPadding, offset + kIconYOffset));
439 currentEvent.type = MENU_PREPAINT;
442 stateFinished =
true;
446 inline void Menu::transFromHopUp()
450 changeState(MENU_STATE_START);
471 inline void Menu::transToPanTarget()
473 stopping_position = stoppingPositionFor(targetItem);
474 panDelay = kPanDelayMilliseconds;
477 inline void Menu::statePanTarget()
480 panDelay -= frameclock.delta().milliseconds();
482 float delta = kPanEasingRate * (stopping_position - position);
483 float kPanMaxSpeed = 7.5f;
484 position +=
clamp(delta, -kPanMaxSpeed, kPanMaxSpeed);
485 if (
abs(position - stopping_position) < 1.1f) {
486 position = stopping_position;
488 stateFinished = position == stopping_position;
508 inline void Menu::transFromPanTarget()
512 changeState(MENU_STATE_STATIC);
static SystemTime now()
Returns a new SystemTime representing the current system clock value.
Definition: time.h:269
#define ASSERT(_x)
Runtime debug assertion.
Definition: macros.h:205
Vector2< int > Int2
Typedef for a 2-vector of ints.
Definition: math.h:641
T abs(const T &value)
For any type, return the absolute value.
Definition: math.h:90
Nil value (-1)
Definition: cube.h:60
static void finish()
Wait for any previous paint() to finish.
Definition: system.h:170
BG0 background, 8 sprites, BG1 overlay.
Definition: video.h:88
Total number of sides (4)
Definition: cube.h:59
T clamp(const T &value, const T &low, const T &high)
For any type, clamp a value to the extremes 'low' and 'high'.
Definition: math.h:72
static const _SYSCubeID UNDEFINED
A reserved ID, used to mark undefined CubeIDs.
Definition: cube.h:92
Vector2< T > vec(T x, T y)
Create a Vector2, from a set of (x,y) coordinates.
Definition: math.h:658