20 # error This is a userspace-only header, not allowed by the current build.
23 #include <sifteo/menu/types.h>
32 inline void Menu::changeState(
MenuState newstate)
34 stateFinished =
false;
35 currentState = newstate;
37 MENU_LOG(
"STATE: -> ");
38 switch(currentState) {
39 case MENU_STATE_START:
43 case MENU_STATE_STATIC:
47 case MENU_STATE_TILTING:
48 MENU_LOG(
"tilting\n");
51 case MENU_STATE_INERTIA:
52 MENU_LOG(
"inertia\n");
55 case MENU_STATE_FINISH:
59 case MENU_STATE_HOP_UP:
63 case MENU_STATE_PAN_TARGET:
64 MENU_LOG(
"pan target\n");
80 inline void Menu::transToStart()
85 inline void Menu::stateStart()
90 vid->bg0.erase(*assets->background);
94 const AssetImage& label = items[startingItem].label ? *items[startingItem].label : *assets->header;
95 vid->bg1.fillMask(
vec(0,0), label.tileSize());
96 vid->bg1.image(
vec(0,0), label);
101 const AssetImage& footer = assets->tips[0] ? *assets->tips[0] : *assets->footer;
102 Int2 topLeft = { 0, kNumVisibleTilesY - footer.tileHeight() };
103 vid->bg1.fillMask(topLeft, footer.tileSize());
104 vid->bg1.image(topLeft, footer);
112 stateFinished =
true;
115 inline void Menu::transFromStart()
123 hasBeenStarted =
true;
125 position = stoppingPositionFor(startingItem);
126 prev_ut = computeCurrentTile() + kNumTilesX;
130 neighbors[i].neighborSide =
NO_SIDE;
132 neighbors[i].masterSide =
NO_SIDE;
136 targetItem != -1 && startingItem != targetItem ?
137 MENU_STATE_PAN_TARGET :
156 inline void Menu::transToStatic()
159 prevTouch = vid->cube().isTouching();
161 currentEvent.type = MENU_ITEM_ARRIVE;
162 currentEvent.item = computeSelected();
166 const AssetImage& label = items[currentEvent.item].label ? *items[currentEvent.item].label : *assets->header;
167 vid->bg1.image(
vec(0,0), label);
171 inline void Menu::stateStatic()
176 inline void Menu::transFromStatic()
178 if (
abs(accel.x) < kAccelThresholdOn || isTiltingAtEdge()) {
182 changeState(MENU_STATE_TILTING);
184 currentEvent.type = MENU_ITEM_DEPART;
185 currentEvent.direction = accel.x > 0 ? 1 : -1;
189 const AssetImage& label = *assets->header;
190 vid->bg1.image(
vec(0,0), label);
204 inline void Menu::transToTilting()
206 ASSERT(
abs(accel.x) > kAccelThresholdOn);
209 inline void Menu::stateTilting()
212 const int max_x = stoppingPositionFor(numItems - 1);
213 const float kInertiaThreshold = 10.f;
215 velocity += (accel.x * frameclock.delta() * kTimeDilator) * velocityMultiplier();
218 if (
abs(velocity) > maxVelocity()) {
219 velocity = (velocity < 0 ? 0 - maxVelocity() : maxVelocity());
223 if ((position > 0.f && velocity < 0) || (position < max_x && velocity > 0) ||
abs(velocity) > kInertiaThreshold) {
224 position += velocity * frameclock.delta() * kTimeDilator;
231 inline void Menu::transFromTilting()
233 const bool outOfBounds = (position < -0.05f) || (position > kItemPixelWidth()*(numItems-1) + kEndCapPadding + 0.05f);
234 if (
abs(accel.x) < kAccelThresholdOff || outOfBounds) {
235 changeState(MENU_STATE_INERTIA);
250 inline void Menu::transToInertia()
252 stopping_position = stoppingPositionFor(computeSelected());
253 if (
abs(accel.x) > kAccelThresholdOff) {
254 tiltDirection = (kAccelScalingFactor * accel.x < 0) ? 1 : -1;
260 inline void Menu::stateInertia()
264 const float stiffness = 0.333f;
267 if (
abs(accel.x) < kAccelThresholdOff) {
271 if ((tiltDirection < 0 && velocity >= 0.f) || (tiltDirection > 0 && velocity <= 0.f)) {
275 velocity += stopping_position - position;
276 velocity *= stiffness;
277 position += velocity * frameclock.delta() * kTimeDilator;
278 position = lerp(position, stopping_position, 0.15f);
280 stateFinished =
abs(velocity) < 1.0f &&
abs(stopping_position - position) < 0.5f;
283 position = stopping_position;
289 inline void Menu::transFromInertia()
291 if (
abs(accel.x) > kAccelThresholdOn &&
292 !((tiltDirection < 0 && accel.x < 0.f) || (tiltDirection > 0 && accel.x > 0.f))) {
293 changeState(MENU_STATE_TILTING);
296 changeState(MENU_STATE_STATIC);
311 inline void Menu::transToFinish()
319 vid->bg0.setPanning(
vec(0, 0));
320 vid->bg0.erase(*assets->background);
322 if (assets->header) {
324 vid->bg0.image(vec, *assets->header);
326 if (assets->footer) {
327 Int2 vec = { 0, kNumVisibleTilesY - assets->footer->tileHeight() };
328 vid->bg0.image(vec, *assets->footer);
331 const AssetImage* icon = items[computeSelected()].icon;
332 vid->bg1.eraseMask();
333 vid->bg1.fillMask(
vec(0,0), icon->tileSize());
334 vid->bg1.image(
vec(0,0), *icon);
337 currentEvent.type = MENU_PREPAINT;
340 inline void Menu::stateFinish()
346 float u = finishIteration/33.f;
348 offset = int(12*(1.f-u*u));
349 vid->bg1.setPanning(
vec(-kEndCapPadding, offset + kIconYOffset));
350 currentEvent.type = MENU_PREPAINT;
352 if (offset <= -128) {
353 currentEvent.type = MENU_EXIT;
354 currentEvent.item = computeSelected();
355 stateFinished =
true;
359 inline void Menu::transFromFinish()
363 changeState(MENU_STATE_START);
384 inline void Menu::transToHopUp()
388 vid->bg0.setPanning(
vec(0, 0));
389 vid->bg0.erase(*assets->background);
391 if (assets->header) {
393 vid->bg0.image(vec, *assets->header);
395 if (assets->footer) {
396 Int2 vec = { 0, kNumVisibleTilesY - assets->footer->tileHeight() };
397 vid->bg0.image(vec, *assets->footer);
400 const AssetImage* icon = items[computeSelected()].icon;
401 vid->bg1.eraseMask();
402 vid->bg1.fillMask(
vec(0,0), icon->tileSize());
403 vid->bg1.image(
vec(0,0), *icon);
405 finishIteration = 30;
407 hasBeenStarted =
true;
410 inline void Menu::stateHopUp()
416 float u = finishIteration/33.f;
418 offset = int(12*(1.f-u*u));
419 vid->bg1.setPanning(
vec(-kEndCapPadding, offset + kIconYOffset));
420 currentEvent.type = MENU_PREPAINT;
423 stateFinished =
true;
427 inline void Menu::transFromHopUp()
431 changeState(MENU_STATE_START);
452 inline void Menu::transToPanTarget()
454 stopping_position = stoppingPositionFor(targetItem);
455 panDelay = kPanDelayMilliseconds;
458 inline void Menu::statePanTarget()
461 panDelay -= frameclock.delta().milliseconds();
463 float delta = kPanEasingRate * (stopping_position - position);
464 float kPanMaxSpeed = 7.5f;
465 position +=
clamp(delta, -kPanMaxSpeed, kPanMaxSpeed);
466 if (
abs(position - stopping_position) < 1.1f) {
467 position = stopping_position;
469 stateFinished = position == stopping_position;
489 inline void Menu::transFromPanTarget()
493 changeState(MENU_STATE_STATIC);