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:
76 inline void Menu::transToStart()
81 inline void Menu::stateStart()
86 vid->bg0.erase(*assets->background);
90 const AssetImage& label = items[startingItem].label ? *items[startingItem].label : *assets->header;
91 vid->bg1.fillMask(
vec(0,0), label.tileSize());
92 vid->bg1.image(
vec(0,0), label);
97 const AssetImage& footer = assets->tips[0] ? *assets->tips[0] : *assets->footer;
98 Int2 topLeft = { 0, kNumVisibleTilesY - footer.tileHeight() };
99 vid->bg1.fillMask(topLeft, footer.tileSize());
100 vid->bg1.image(topLeft, footer);
108 stateFinished =
true;
111 inline void Menu::transFromStart()
114 hasBeenStarted =
true;
116 position = stoppingPositionFor(startingItem);
117 prev_ut = computeCurrentTile() + kNumTilesX;
121 neighbors[i].neighborSide =
NO_SIDE;
123 neighbors[i].masterSide =
NO_SIDE;
126 changeState(MENU_STATE_STATIC);
142 inline void Menu::transToStatic()
145 prevTouch = vid->cube().isTouching();
147 currentEvent.type = MENU_ITEM_ARRIVE;
148 currentEvent.item = computeSelected();
152 const AssetImage& label = items[currentEvent.item].label ? *items[currentEvent.item].label : *assets->header;
153 vid->bg1.image(
vec(0,0), label);
157 inline void Menu::stateStatic()
162 inline void Menu::transFromStatic()
164 if (
abs(accel.x) < kAccelThresholdOn)
171 int8_t direction = accel.x > 0 ? 1 : -1;
172 if ((currentEvent.item == 0 && direction < 0) ||
173 (currentEvent.item == numItems - 1 && direction > 0))
176 changeState(MENU_STATE_TILTING);
178 currentEvent.type = MENU_ITEM_DEPART;
179 currentEvent.direction = direction;
183 const AssetImage& label = *assets->header;
184 vid->bg1.image(
vec(0,0), label);
198 inline void Menu::transToTilting()
200 ASSERT(
abs(accel.x) > kAccelThresholdOn);
203 inline void Menu::stateTilting()
206 const int max_x = stoppingPositionFor(numItems - 1);
207 const float kInertiaThreshold = 10.f;
209 velocity += (accel.x * frameclock.delta() * kTimeDilator) * velocityMultiplier();
212 if (
abs(velocity) > maxVelocity()) {
213 velocity = (velocity < 0 ? 0 - maxVelocity() : maxVelocity());
217 if ((position > 0.f && velocity < 0) || (position < max_x && velocity > 0) ||
abs(velocity) > kInertiaThreshold) {
218 position += velocity * frameclock.delta() * kTimeDilator;
225 inline void Menu::transFromTilting()
227 const bool outOfBounds = (position < -0.05f) || (position > kItemPixelWidth()*(numItems-1) + kEndCapPadding + 0.05f);
228 if (
abs(accel.x) < kAccelThresholdOff || outOfBounds) {
229 changeState(MENU_STATE_INERTIA);
244 inline void Menu::transToInertia()
246 stopping_position = stoppingPositionFor(computeSelected());
247 if (
abs(accel.x) > kAccelThresholdOff) {
248 tiltDirection = (kAccelScalingFactor * accel.x < 0) ? 1 : -1;
254 inline void Menu::stateInertia()
258 const float stiffness = 0.333f;
261 if (
abs(accel.x) < kAccelThresholdOff) {
265 if ((tiltDirection < 0 && velocity >= 0.f) || (tiltDirection > 0 && velocity <= 0.f)) {
269 velocity += stopping_position - position;
270 velocity *= stiffness;
271 position += velocity * frameclock.delta() * kTimeDilator;
272 position = lerp(position, stopping_position, 0.15f);
274 stateFinished =
abs(velocity) < 1.0f &&
abs(stopping_position - position) < 0.5f;
277 position = stopping_position;
283 inline void Menu::transFromInertia()
285 if (
abs(accel.x) > kAccelThresholdOn &&
286 !((tiltDirection < 0 && accel.x < 0.f) || (tiltDirection > 0 && accel.x > 0.f))) {
287 changeState(MENU_STATE_TILTING);
290 changeState(MENU_STATE_STATIC);
305 inline void Menu::transToFinish()
313 vid->bg0.setPanning(
vec(0, 0));
314 vid->bg0.erase(*assets->background);
316 if (assets->header) {
318 vid->bg0.image(vec, *assets->header);
320 if (assets->footer) {
321 Int2 vec = { 0, kNumVisibleTilesY - assets->footer->tileHeight() };
322 vid->bg0.image(vec, *assets->footer);
325 const AssetImage* icon = items[computeSelected()].icon;
326 vid->bg1.eraseMask();
327 vid->bg1.fillMask(
vec(0,0), icon->tileSize());
328 vid->bg1.image(
vec(0,0), *icon);
331 currentEvent.type = MENU_PREPAINT;
334 inline void Menu::stateFinish()
340 float u = finishIteration/33.f;
342 offset = int(12*(1.f-u*u));
343 vid->bg1.setPanning(
vec(-kEndCapPadding, offset + kIconYOffset));
344 currentEvent.type = MENU_PREPAINT;
346 if (offset <= -128) {
347 currentEvent.type = MENU_EXIT;
348 currentEvent.item = computeSelected();
349 stateFinished =
true;
353 inline void Menu::transFromFinish()
357 changeState(MENU_STATE_START);
378 inline void Menu::transToHopUp()
382 vid->bg0.setPanning(
vec(0, 0));
383 vid->bg0.erase(*assets->background);
385 if (assets->header) {
387 vid->bg0.image(vec, *assets->header);
389 if (assets->footer) {
390 Int2 vec = { 0, kNumVisibleTilesY - assets->footer->tileHeight() };
391 vid->bg0.image(vec, *assets->footer);
394 const AssetImage* icon = items[computeSelected()].icon;
395 vid->bg1.eraseMask();
396 vid->bg1.fillMask(
vec(0,0), icon->tileSize());
397 vid->bg1.image(
vec(0,0), *icon);
399 finishIteration = 30;
401 hasBeenStarted =
true;
404 inline void Menu::stateHopUp()
410 float u = finishIteration/33.f;
412 offset = int(12*(1.f-u*u));
413 vid->bg1.setPanning(
vec(-kEndCapPadding, offset + kIconYOffset));
414 currentEvent.type = MENU_PREPAINT;
417 stateFinished =
true;
421 inline void Menu::transFromHopUp()
425 changeState(MENU_STATE_START);