1
0
mirror of git://projects.qi-hardware.com/gmenu2x.git synced 2024-07-02 18:05:26 +03:00

Animate section header changes

This commit is contained in:
Maarten ter Huurne 2013-08-11 05:16:03 +02:00
parent f414ce4685
commit 8de59b5c04
2 changed files with 76 additions and 5 deletions

View File

@ -43,6 +43,29 @@
using namespace std;
Menu::Animation::Animation()
: curr(0)
{
}
void Menu::Animation::adjust(int delta)
{
curr += delta;
}
void Menu::Animation::step()
{
if (curr == 0) {
ERROR("Computing step past animation end\n");
} else if (curr < 0) {
const int v = ((1 << 16) - curr) / 32;
curr = std::min(0, curr + v);
} else {
const int v = ((1 << 16) + curr) / 32;
curr = std::max(0, curr - v);
}
}
Menu::Menu(GMenu2X *gmenu2x, Touchscreen &ts)
: gmenu2x(gmenu2x)
, ts(ts)
@ -148,7 +171,18 @@ void Menu::calcSectionRange(int &leftSection, int &rightSection) {
rightSection - numSections + 1);
}
void Menu::runAnimations() {
if (sectionAnimation.isRunning()) {
sectionAnimation.step();
if (!sectionAnimation.isRunning()) {
stopAnimating();
}
}
}
void Menu::paint(Surface &s) {
runAnimations();
const uint width = s.width(), height = s.height();
Font &font = *gmenu2x->font;
SurfaceCollection &sc = gmenu2x->sc;
@ -160,19 +194,37 @@ void Menu::paint(Surface &s) {
const int linkHeight = skinConfInt["linkHeight"];
RGBAColor &selectionBgColor = gmenu2x->skinConfColors[COLOR_SELECTION_BG];
// Paint section headers.
// Apply section header animation.
int leftSection, rightSection;
calcSectionRange(leftSection, rightSection);
int sectionFP = sectionAnimation.currentValue();
int sectionDelta = (sectionFP * linkWidth + (1 << 15)) >> 16;
int centerSection = iSection - sectionDelta / linkWidth;
sectionDelta %= linkWidth;
if (sectionDelta < 0) {
rightSection++;
} else if (sectionDelta > 0) {
leftSection--;
}
// Paint section headers.
s.box(width / 2 - linkWidth / 2, 0, linkWidth, topBarHeight, selectionBgColor);
const uint sectionLinkPadding = (topBarHeight - 32 - font.getHeight()) / 3;
const uint numSections = sections.size();
for (int i = leftSection; i <= rightSection; i++) {
uint j = (iSection + numSections + i) % numSections;
uint j = (centerSection + numSections + i) % numSections;
string sectionIcon = "skin:sections/" + sections[j] + ".png";
Surface *icon = sc.exists(sectionIcon)
? sc[sectionIcon]
: sc.skinRes("icons/section.png");
const int x = width / 2 + i * linkWidth;
int x = width / 2 + i * linkWidth + sectionDelta;
if (i == leftSection) {
int t = sectionDelta > 0 ? linkWidth - sectionDelta : -sectionDelta;
x -= (((t * t) / linkWidth) * t) / linkWidth;
} else if (i == rightSection) {
int t = sectionDelta < 0 ? sectionDelta + linkWidth : sectionDelta;
x += (((t * t) / linkWidth) * t) / linkWidth;
}
icon->blit(&s, x - 16, sectionLinkPadding, 32, 32);
s.write(&font, sections[j], x, topBarHeight - sectionLinkPadding,
Font::HAlignCenter, Font::VAlignBottom);
@ -318,11 +370,15 @@ vector<Link*> *Menu::sectionLinks(int i) {
}
void Menu::decSectionIndex() {
setSectionIndex(iSection-1);
sectionAnimation.adjust(-1 << 16);
startAnimating();
setSectionIndex(iSection - 1);
}
void Menu::incSectionIndex() {
setSectionIndex(iSection+1);
sectionAnimation.adjust(1 << 16);
startAnimating();
setSectionIndex(iSection + 1);
}
int Menu::selSectionIndex() {

View File

@ -42,6 +42,17 @@ Handles the menu structure
*/
class Menu : public Layer {
private:
class Animation {
public:
Animation();
bool isRunning() { return curr != 0; }
int currentValue() { return curr; }
void adjust(int delta);
void step();
private:
int curr;
};
GMenu2X *gmenu2x;
Touchscreen &ts;
std::unique_ptr<IconButton> btnContextMenu;
@ -52,6 +63,10 @@ private:
uint linkColumns, linkRows;
Animation sectionAnimation;
void runAnimations();
/**
* Determine which section headers are visible.
* The output values are relative to the middle section at 0.