Add selection 'highlight', ease movement
This commit is contained in:
parent
03cb418d63
commit
bec441bd96
@ -14,6 +14,7 @@ add_executable(mtgcard
|
||||
src/flash.cpp
|
||||
src/cardslot.cpp
|
||||
src/icons.cpp
|
||||
src/menu.cpp
|
||||
src/manamenu.cpp
|
||||
|
||||
src/usb_descriptors.c
|
||||
|
||||
@ -50,6 +50,7 @@ public:
|
||||
|
||||
private:
|
||||
uint8_t current;
|
||||
uint8_t previous;
|
||||
bool going_left;
|
||||
float progress;
|
||||
};
|
||||
|
||||
179
src/manamenu.cpp
179
src/manamenu.cpp
@ -9,20 +9,72 @@ namespace
|
||||
|
||||
constexpr uint8_t COLORS[] = { 0, 0b1, 0b10, 0b100, 0b1000, 0b10000 };
|
||||
|
||||
// adapted from easings.net
|
||||
float easeInOutElastic(float x)
|
||||
{
|
||||
constexpr float c5 = (2 * 3.1415926f) / 4.5f;
|
||||
|
||||
if (x == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (x == 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (x < 0.5)
|
||||
{
|
||||
return -powf(2, 20 * x - 10) * sinf((20 * x - 11.125f) * c5) / 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return powf(2, -20 * x + 10) * sinf((20 * x - 11.25f) * c5) / 2.0f + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// adapted from easings.net
|
||||
float easeOutElastic(float x)
|
||||
{
|
||||
constexpr float c4 = (2 * 3.1415926f) / 3;
|
||||
|
||||
if (x == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (x == 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return powf(2, -10 * x) * sinf((x * 10 - 0.75f) * c4) + 1;
|
||||
}
|
||||
|
||||
// adapted from easings.net
|
||||
float easeInElastic(float x)
|
||||
{
|
||||
constexpr float c4 = (2 * 3.1415926f) / 3;
|
||||
|
||||
if (x == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (x == 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -powf(2, 10 * x - 10) * sinf((x * 10 - 10.75f) * c4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace menus;
|
||||
|
||||
Menu::Menu(lib::Display& display) :
|
||||
display(&display)
|
||||
{
|
||||
}
|
||||
|
||||
ManaMenu::ManaMenu(lib::Display& display) :
|
||||
Menu(display),
|
||||
current(0),
|
||||
previous(0),
|
||||
going_left(false),
|
||||
progress(0.999f)
|
||||
progress(0.99f)
|
||||
{
|
||||
}
|
||||
|
||||
@ -30,11 +82,51 @@ void ManaMenu::onTick(float dt)
|
||||
{
|
||||
constexpr float PI = 3.1415926f;
|
||||
constexpr float STEP = 2 * PI / 6.0f;
|
||||
constexpr float RADIUS = 80;
|
||||
constexpr float RADIUS = 75;
|
||||
constexpr float CENTER_X = 120;
|
||||
constexpr float CENTER_Y = 190;
|
||||
constexpr float MAX_OFFSET = RADIUS / 1.5f;
|
||||
constexpr float DT_SCALE_ROTATE = 1.1f;
|
||||
constexpr float DT_SCALE_UPDOWN = 1.6f;
|
||||
constexpr uint8_t ERASE_DATA[38 * 5 * 3] = {};
|
||||
|
||||
if (progress < 1.0f)
|
||||
{
|
||||
const float offset = (going_left ? -1 : 1) * STEP * progress + STEP / 2.0f;
|
||||
const float offset
|
||||
= (1.0f - easeOutElastic(progress)) * MAX_OFFSET + RADIUS;
|
||||
|
||||
// erase old
|
||||
{
|
||||
display->set_update_area(CENTER_X - 20, CENTER_Y - 20 - offset, 38, 5);
|
||||
auto pixels = display->pixels();
|
||||
pixels.write(ERASE_DATA, 38 * 5 * 3);
|
||||
}
|
||||
{
|
||||
display->set_update_area(CENTER_X - 20, CENTER_Y - 15 + 30 - offset, 38,
|
||||
5);
|
||||
auto pixels = display->pixels();
|
||||
pixels.write(ERASE_DATA, 38 * 5 * 3);
|
||||
}
|
||||
|
||||
// write new
|
||||
{
|
||||
display->set_update_area(CENTER_X - 15, CENTER_Y - 15 - offset, 31, 32);
|
||||
auto pixels = display->pixels();
|
||||
const uint8_t* data = icon::wubrgc(COLORS[previous]);
|
||||
pixels.write(data, icon::LENGTH);
|
||||
}
|
||||
|
||||
progress += dt * DT_SCALE_UPDOWN;
|
||||
if (progress > 0.75f)
|
||||
{
|
||||
progress = 1.0f;
|
||||
}
|
||||
}
|
||||
else if (progress < 2.0f)
|
||||
{
|
||||
const float offset
|
||||
= (going_left ? -1 : 1) * STEP * easeOutElastic(progress - 1)
|
||||
+ STEP / 2.0f;
|
||||
|
||||
// erase previous
|
||||
for (int i = 0; i < sizeof(COLORS) / sizeof(*COLORS); i++)
|
||||
@ -44,54 +136,42 @@ void ManaMenu::onTick(float dt)
|
||||
const float x = cosf(angle) * RADIUS;
|
||||
const float y = sinf(angle) * RADIUS;
|
||||
|
||||
const int left = x - 20 + 120;
|
||||
const int top = y - 20 + 160;
|
||||
const int left = x - 20 + CENTER_X;
|
||||
const int top = y - 20 + CENTER_Y;
|
||||
|
||||
// top rectangle
|
||||
{
|
||||
display->set_update_area(left, top, 38, 5);
|
||||
auto pixels = display->pixels();
|
||||
for (int pixel = 0; pixel < 38 * 5; pixel++)
|
||||
{
|
||||
pixels.write(0, 0, 0);
|
||||
}
|
||||
pixels.write(ERASE_DATA, 38 * 5 * 3);
|
||||
}
|
||||
|
||||
// bottom rectangle
|
||||
{
|
||||
display->set_update_area(left, top + 36, 38, 5);
|
||||
auto pixels = display->pixels();
|
||||
for (int pixel = 0; pixel < 38 * 5; pixel++)
|
||||
{
|
||||
pixels.write(0, 0, 0);
|
||||
}
|
||||
pixels.write(ERASE_DATA, 38 * 5 * 3);
|
||||
}
|
||||
|
||||
// left rectangle
|
||||
{
|
||||
display->set_update_area(left, top + 3, 5, 38);
|
||||
auto pixels = display->pixels();
|
||||
for (int pixel = 0; pixel < 5 * 38; pixel++)
|
||||
{
|
||||
pixels.write(0, 0, 0);
|
||||
}
|
||||
pixels.write(ERASE_DATA, 38 * 5 * 3);
|
||||
}
|
||||
|
||||
// right rectangle
|
||||
{
|
||||
display->set_update_area(left + 36, top + 3, 5, 38);
|
||||
auto pixels = display->pixels();
|
||||
for (int pixel = 0; pixel < 5 * 38; pixel++)
|
||||
{
|
||||
pixels.write(0, 0, 0);
|
||||
}
|
||||
pixels.write(ERASE_DATA, 38 * 5 * 3);
|
||||
}
|
||||
}
|
||||
|
||||
progress += dt * 2.0f;
|
||||
if (progress > 1.0f)
|
||||
progress += dt * DT_SCALE_ROTATE;
|
||||
if (progress > 1.75f)
|
||||
{
|
||||
progress = 1.0f;
|
||||
progress = 2.0f;
|
||||
}
|
||||
|
||||
// write new
|
||||
@ -102,28 +182,58 @@ void ManaMenu::onTick(float dt)
|
||||
const float x = cosf(angle) * RADIUS;
|
||||
const float y = sinf(angle) * RADIUS;
|
||||
|
||||
const int left = x - 15 + 120;
|
||||
const int top = y - 15 + 160;
|
||||
const int left = x - 15 + CENTER_X;
|
||||
const int top = y - 15 + CENTER_Y;
|
||||
|
||||
display->set_update_area(left, top, 31, 32);
|
||||
auto pixels = display->pixels();
|
||||
const uint8_t* data = icon::wubrgc(COLORS[i]);
|
||||
pixels.write(data, icon::LENGTH);
|
||||
}
|
||||
}
|
||||
else if (progress < 3.0f)
|
||||
{
|
||||
const float offset = easeOutElastic(progress - 2.0f) * MAX_OFFSET + RADIUS;
|
||||
|
||||
sleep_ms(1);
|
||||
// erase old
|
||||
{
|
||||
display->set_update_area(CENTER_X - 20, CENTER_Y - 20 - offset, 38, 5);
|
||||
auto pixels = display->pixels();
|
||||
pixels.write(ERASE_DATA, 38 * 5 * 3);
|
||||
}
|
||||
{
|
||||
display->set_update_area(CENTER_X - 20, CENTER_Y - 15 + 30 - offset, 38,
|
||||
5);
|
||||
auto pixels = display->pixels();
|
||||
pixels.write(ERASE_DATA, 38 * 5 * 3);
|
||||
}
|
||||
|
||||
// write new
|
||||
{
|
||||
display->set_update_area(CENTER_X - 15, CENTER_Y - 15 - offset, 31, 32);
|
||||
auto pixels = display->pixels();
|
||||
const uint8_t* data = icon::wubrgc(COLORS[current]);
|
||||
pixels.write(data, icon::LENGTH);
|
||||
}
|
||||
|
||||
progress += dt * DT_SCALE_UPDOWN;
|
||||
if (progress > 2.75f)
|
||||
{
|
||||
progress = 3.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ManaMenu::onLeftPressed()
|
||||
{
|
||||
if (progress < 1.0f)
|
||||
if (progress < 3.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
going_left = true;
|
||||
|
||||
previous = current;
|
||||
if (current == 0)
|
||||
{
|
||||
current = 5;
|
||||
@ -142,13 +252,14 @@ void ManaMenu::onMenuHeld() {}
|
||||
|
||||
void ManaMenu::onRightPressed()
|
||||
{
|
||||
if (progress < 1.0f)
|
||||
if (progress < 3.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
going_left = false;
|
||||
|
||||
previous = current;
|
||||
if (current == 5)
|
||||
{
|
||||
current = 0;
|
||||
|
||||
6
src/menu.cpp
Normal file
6
src/menu.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "menu.h"
|
||||
|
||||
Menu::Menu(lib::Display& display) :
|
||||
display(&display)
|
||||
{
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user