mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-25 12:46:53 +01:00
a0182d0c4c
* ogg decoder added (old oggplayer removed) * mp3 decoder added (mp3's cane use as backgroundsounds) * WAVE decoder added (but only uncompressed WAVE's) * AIFF decoder added (only uncrompressed) * BNS decoder added all soundformats can use as backgroundsounds dimoks GameSound class removed it is replaced with the new GuiSound stuff * Many small fixes and other changes
966 lines
25 KiB
C++
966 lines
25 KiB
C++
/****************************************************************************
|
|
* libwiigui
|
|
*
|
|
* gui_gameGrid.cpp
|
|
*
|
|
* GUI class definitions
|
|
***************************************************************************/
|
|
|
|
#include "gui.h"
|
|
#include "../wpad.h"
|
|
|
|
#include <unistd.h>
|
|
#include "gui_gamegrid.h"
|
|
#include "gui_image_async.h"
|
|
#include "../settings/cfg.h"
|
|
#include "../prompts/PromptWindows.h"
|
|
#include "../language/gettext.h"
|
|
#include "../menu.h"
|
|
#include "fatmounter.h"
|
|
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <sstream>
|
|
|
|
//#define SCALE 0.8f
|
|
//#define DEG_OFFSET 7
|
|
#define RADIUS 780
|
|
//#define IN_SPEED 175
|
|
//#define SHIFT_SPEED 100
|
|
//#define SPEED_STEP 4
|
|
//#define SAFETY 320
|
|
#define goSteps 10
|
|
#include "../main.h"
|
|
|
|
|
|
|
|
|
|
extern const int vol;
|
|
|
|
static int Skew1[7][8] = {
|
|
{-14,-66,14,-34,14,34,-14,66},
|
|
{-10,-44,10,-26,10,26,-10,44},
|
|
{-6,-22,6,-14,6,14,-6,22},
|
|
{0,-11,0,-11,0,11,0,11},
|
|
{-6,-14,6,-22,6,22,-6,14},
|
|
{-10,-26,10,-44,10,44,-10,26},
|
|
{-14,-34,14,-66,14,66,-14,34}
|
|
};
|
|
static int Pos1[7][2][2] = {
|
|
// {{16:9 x,y},{ 4:3 x,y}}
|
|
{{-230,74}, {-320,74}},
|
|
{{-70,74}, {-130,74}},
|
|
{{88,74}, {60,74}},
|
|
{{239,74}, {239,74}},
|
|
{{390,74}, {420,74}},
|
|
{{550,74}, {612,74}},
|
|
{{710,74}, {772,74}}
|
|
};
|
|
static int Skew2[18][8] = {
|
|
{-5,-49,5,-27,5,0,-5,0},
|
|
{-5,0,5,0,5,27,-5,49},
|
|
|
|
{-5,-49,5,-27,5,0,-5,0},
|
|
{-5,0,5,0,5,27,-5,49},
|
|
|
|
{-4,-22,4,-14,4,0,-4,0},
|
|
{-4,0,4,0,4,14,-4,22},
|
|
|
|
{0,-9,0,-5,0,0,0,0},
|
|
{0,0,0,0,0,5,0,9},
|
|
|
|
{0,0,0,0,0,0,0,0},
|
|
{0,0,0,0,0,0,0,0},
|
|
|
|
{0,-5,0,-9,0,0,0,0},
|
|
{0,0,0,0,0,9,0,5},
|
|
|
|
{-4,-14,4,-22,4,0,-4,0},
|
|
{-4,0,4,0,4,22,-4,14},
|
|
|
|
{-5,-27,5,-49,5,0,-5,0},
|
|
{-5,0,5,0,5,49,-5,27},
|
|
|
|
{-5,-27,5,-49,5,0,-5,0},
|
|
{-5,0,5,0,5,49,-5,27}
|
|
};
|
|
static int Pos2[18][2][2] = {
|
|
// {{16:9 x,y},{ 4:3 x,y}}
|
|
{{-91,50}, {-166,50}},
|
|
{{-91,193},{-166,193}},
|
|
|
|
{{3,50}, {-54,50}},
|
|
{{3,193}, {-54,193}},
|
|
|
|
{{97,50}, {58,50}},
|
|
{{97,193}, {58,193}},
|
|
|
|
{{187,50}, {166,50}},
|
|
{{187,193}, {166,193}},
|
|
|
|
{{272,50}, {272,50}},
|
|
{{272,193}, {272,193}},
|
|
|
|
{{358,50}, {378,50}},
|
|
{{358,193}, {378,193}},
|
|
|
|
{{449,50}, {487,50}},
|
|
{{449,193}, {487,193}},
|
|
|
|
{{545,50}, {599,50}},
|
|
{{545,193}, {599,193}},
|
|
|
|
{{641,50}, {700,50}},
|
|
{{641,193}, {700,193}}
|
|
};
|
|
static int Skew3[45][8] = {
|
|
{-38,-110,15,-42,15,65,-38,32},
|
|
{-38,-75,15,-48,15,45,-38,72},
|
|
{-38,-52,15,-70,15,27,-38,100},
|
|
|
|
{-38,-110,15,-42,15,65,-38,32},
|
|
{-38,-75,15,-48,15,45,-38,72},
|
|
{-38,-52,15,-70,15,27,-38,100},
|
|
|
|
{-38,-70,15,-24,15,40,-38,27},
|
|
{-38,-50,15,-35,15,40,-38,50},
|
|
{-38,-34,15,-47,15,24,-38,58},
|
|
|
|
{-27,-55,19,-22,19,30,-27,22},
|
|
{-27,-40,19,-30,19,30,-27,40},
|
|
{-27,-20,19,-30,19,20,-27,50},
|
|
|
|
{-19,-28,0,-17,0,15,-19,10},
|
|
{-19,-30,0,-20,0,12,-19,30},
|
|
{-19,-15,0,-20,0,10,-19,24},
|
|
|
|
{-10,-20,3,-13,3,14,-10,10},
|
|
{-10,-20,3,-18,3,18,-10,20},
|
|
{-10,-10,3,-10,3,0,-10,10},
|
|
|
|
{-10,-15,3,-12,3,13,-10,13},
|
|
{-10,-17,3,-10,3,10,-10,17},
|
|
{-10,-10,3,-15,3,10,-10,10},
|
|
|
|
{-10,-10,3,-10,3,14,-10,14},
|
|
{-10,-10,3,-10,3,10,-10,10},//middle
|
|
{-10,-10,3,-10,3,10,-10,10},
|
|
|
|
{-14,-10,4,-20,3,10,-14,10},
|
|
{-14,-10,4,-17,3,17,-14,10},
|
|
{-14,-10,4,-10,3,10,-14,10},
|
|
|
|
{-10,-13,3,-20,3,14,-10,10},
|
|
{-10,-18,3,-20,3,20,-10,18},
|
|
{-10,-10,3,-10,3,20,-10,5},
|
|
|
|
{-19,-17,0,-28,0,10,-19,15},
|
|
{-19,-20,0,-30,0,30,-19,12},
|
|
{-19,-20,0,-15,0,30,-19,10},
|
|
|
|
{-27,-22,19,-55,19,22,-27,30},
|
|
{-27,-30,19,-40,19,40,-27,30},
|
|
{-27,-30,19,-20,19,55,-27,20},
|
|
|
|
{-38,-24,15,-70,15,27,-38,40},
|
|
{-38,-35,15,-50,15,50,-38,40},
|
|
{-38,-47,15,-34,15,58,-38,24},
|
|
|
|
{-38,-42,15,-110,15,32,-38,60},
|
|
{-38,-48,15,-75,15,70,-38,45},
|
|
{-38,-70,15,-52,15,100,-38,27},
|
|
|
|
{-38,-42,15,-110,15,32,-38,60},
|
|
{-38,-48,15,-75,15,70,-38,45},
|
|
{-38,-70,15,-52,15,100,-38,27}
|
|
};
|
|
static int Pos3[45][2][2] = {
|
|
// {{16:9 x,y},{ 4:3 x,y}}
|
|
{{-42,49}, {-91,49}},
|
|
{{-42,153},{-91,153}},
|
|
{{-42,261},{-91,261}},
|
|
|
|
{{13,58}, {-29,58}},
|
|
{{13,153}, {-29,153}},
|
|
{{13,250}, {-29,250}},
|
|
|
|
{{68,67}, {33,67}},
|
|
{{68,153}, {33,153}},
|
|
{{68,239}, {33,239}},
|
|
|
|
{{120,74}, {92,74}},
|
|
{{120,153}, {92,153}},
|
|
{{120,232}, {92,232}},
|
|
|
|
{{170,78}, {149,78}},
|
|
{{170,153}, {149,153}},
|
|
{{170,228}, {149,228}},
|
|
|
|
{{214,80}, {200,80}},
|
|
{{214,153}, {200,153}},
|
|
{{214,226}, {200,226}},
|
|
|
|
{{258,81}, {251,81}},
|
|
{{258,153}, {251,153}},
|
|
{{258,224}, {251,224}},
|
|
|
|
{{302,81}, {302,81}},
|
|
{{302,153}, {302,153}},
|
|
{{302,223}, {302,223}},
|
|
|
|
{{346,81}, {353,81}},
|
|
{{346,153}, {353,153}},
|
|
{{346,223}, {353,223}},
|
|
|
|
{{390,80}, {404,80}},
|
|
{{390,153}, {404,153}},
|
|
{{390,225}, {404,225}},
|
|
|
|
{{434,77}, {457,77}},
|
|
{{434,153}, {457,153}},
|
|
{{434,227}, {457,227}},
|
|
|
|
{{484,73}, {512,73}},
|
|
{{484,153}, {512,153}},
|
|
{{484,231}, {512,231}},
|
|
|
|
{{537,67}, {572,67}},
|
|
{{537,153}, {572,153}},
|
|
{{537,239}, {572,239}},
|
|
|
|
{{591,58}, {633,58}},
|
|
{{591,153}, {633,153}},
|
|
{{591,250}, {633,250}},
|
|
|
|
{{645,58}, {633,58}},
|
|
{{645,153}, {633,153}},
|
|
{{645,250}, {633,250}}
|
|
|
|
};
|
|
#define VALUE4ROWS(rows, val1, val2, val3) (rows==3 ? val3 : (rows==2 ? val2 : val1))
|
|
#define ROWS2PAGESIZE(rows) (rows==3 ? 45 : (rows==2 ? 18 : 7))
|
|
static inline int OFFSETLIMIT(int Offset, int rows, int gameCnt)
|
|
{
|
|
gameCnt += ( rows - ( gameCnt % rows ) ) % rows; // add count of skiped Entries at end if List
|
|
while(Offset > gameCnt) Offset -= gameCnt;
|
|
while(Offset < 0) Offset += gameCnt;
|
|
return Offset;
|
|
}
|
|
|
|
// Help-Function to Calc GameIndex
|
|
static int GetGameIndex(int pageEntry, int rows, int listOffset, int gameCnt)
|
|
{
|
|
int skip = ( rows - ( gameCnt % rows ) ) % rows; // count of skiped Entries at end if List
|
|
int pagesize = ROWS2PAGESIZE(rows);
|
|
|
|
if( gameCnt < (pagesize-2*rows) )
|
|
{
|
|
int listStart = (pagesize-gameCnt)>>1; // align list on the center
|
|
listStart = listStart - (listStart%rows); // align listStart to the top row
|
|
if(pageEntry < listStart || pageEntry >= listStart + gameCnt)
|
|
return -1;
|
|
return pageEntry - listStart;
|
|
}
|
|
else
|
|
{
|
|
listOffset = listOffset - (listOffset%rows); // align listOffset to the top row
|
|
listOffset = listOffset - 2*rows; // align listOffset to the left full visible column
|
|
if(listOffset < 0)
|
|
listOffset += gameCnt + skip; // set the correct Offset
|
|
pageEntry = (listOffset + pageEntry) % (gameCnt + skip); // get offset of pageEntry
|
|
if(pageEntry >= gameCnt)
|
|
return -1;
|
|
return pageEntry;
|
|
}
|
|
}
|
|
static GuiImageData *GameGridLoadCoverImage(void * Arg)
|
|
{
|
|
return LoadCoverImage((struct discHdr *)Arg, false, false);
|
|
}
|
|
/**
|
|
* Constructor for the GuiGamegrid class.
|
|
*/
|
|
GuiGameGrid::GuiGameGrid(int w, int h, struct discHdr * l, int count, const char *themePath, const u8 *imagebg, int selected, int offset) :
|
|
noCover(nocoverFlat_png)
|
|
{
|
|
width = w;
|
|
height = h;
|
|
// gameCnt = count; will be set later in Reload
|
|
// gameList = l; will be set later in Reload
|
|
// listOffset = 0; will be set later in Reload
|
|
// goLeft = 0; will be set later in Reload
|
|
// goRight = 0; will be set later in Reload
|
|
|
|
selectable = true;
|
|
focus = 1; // allow focus
|
|
// selectedItem = -1; will be set later in Reload
|
|
// clickedItem = -1; will be set later in Reload
|
|
/* will be set later in Reload
|
|
rows = Settings.gridRows;
|
|
if ((count<45)&&(rows==3))rows=2;
|
|
if ((count<18)&&(rows==2))rows=1;
|
|
|
|
pagesize = ROWS2PAGESIZE(rows);
|
|
*/
|
|
trigA = new GuiTrigger;
|
|
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
|
|
trigL = new GuiTrigger;
|
|
trigL->SetButtonOnlyTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT);
|
|
trigR = new GuiTrigger;
|
|
trigR->SetButtonOnlyTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT);
|
|
trig1 = new GuiTrigger;
|
|
trig1->SetButtonOnlyTrigger(-1, WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_X, PAD_BUTTON_X);
|
|
trig2 = new GuiTrigger;
|
|
trig2->SetButtonOnlyTrigger(-1, WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_Y, PAD_BUTTON_Y);
|
|
trigPlus = new GuiTrigger;
|
|
trigPlus->SetButtonOnlyTrigger(-1, WPAD_BUTTON_PLUS | WPAD_CLASSIC_BUTTON_PLUS, 0);
|
|
trigMinus = new GuiTrigger;
|
|
trigMinus->SetButtonOnlyTrigger(-1, WPAD_BUTTON_MINUS | WPAD_CLASSIC_BUTTON_MINUS, 0);
|
|
|
|
btnSoundClick = new GuiSound(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume);
|
|
btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, Settings.sfxvolume);
|
|
|
|
int btnHeight = (int) lround(sqrt(RADIUS*RADIUS - 90000)-RADIUS-50);
|
|
|
|
// Button Left
|
|
btnLeft = new GuiButton(0,0);
|
|
btnLeft->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
|
btnLeft->SetPosition(20, btnHeight);
|
|
btnLeft->SetParent(this);
|
|
btnLeft->SetSoundOver(btnSoundOver);
|
|
btnLeft->SetTrigger(trigL);
|
|
btnLeft->SetTrigger(trigMinus);
|
|
|
|
// Button Right
|
|
btnRight = new GuiButton(0,0);
|
|
btnRight->SetParent(this);
|
|
btnRight->SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE);
|
|
btnRight->SetPosition(-20, btnHeight);
|
|
btnRight->SetSoundOver(btnSoundOver);
|
|
btnRight->SetTrigger(trigR);
|
|
btnRight->SetTrigger(trigPlus);
|
|
|
|
// Button RowUp
|
|
btnRowUp = new GuiButton(0,0);
|
|
btnRowUp->SetParent(this);
|
|
btnRowUp->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
|
btnRowUp->SetPosition(0,0);
|
|
btnRowUp->SetTrigger(trig2);
|
|
|
|
// Button RowDown
|
|
btnRowDown = new GuiButton(0,0);
|
|
btnRowDown->SetParent(this);
|
|
btnRowDown->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
|
|
btnRowDown->SetPosition(0,0);
|
|
btnRowDown->SetTrigger(trig1);
|
|
|
|
// Page-Stuff
|
|
gameIndex = NULL;
|
|
titleTT = NULL;
|
|
// cover = NULL;
|
|
coverImg = NULL;
|
|
game = NULL;
|
|
|
|
Reload(l, count, Settings.gridRows, 0);
|
|
}
|
|
|
|
|
|
/**
|
|
* Destructor for the GuiGameGrid class.
|
|
*/
|
|
GuiGameGrid::~GuiGameGrid()
|
|
{
|
|
|
|
delete btnRight;
|
|
delete btnLeft;
|
|
delete btnRowUp;
|
|
delete btnRowDown;
|
|
|
|
delete trigA;
|
|
delete trigL;
|
|
delete trigR;
|
|
delete trigPlus;
|
|
delete trigMinus;
|
|
delete trig1;
|
|
delete trig2;
|
|
delete btnSoundClick;
|
|
delete btnSoundOver;
|
|
|
|
for(int i=pagesize-1; i>=0; i--)
|
|
{
|
|
delete game[i];
|
|
delete coverImg[i];
|
|
delete titleTT[i];
|
|
}
|
|
|
|
delete [] gameIndex;
|
|
delete [] game;
|
|
delete [] coverImg;
|
|
delete [] titleTT;
|
|
}
|
|
|
|
|
|
void GuiGameGrid::SetFocus(int f)
|
|
{
|
|
LOCK(this);
|
|
if(!gameCnt)
|
|
return;
|
|
|
|
focus = f;
|
|
|
|
for(int i=0; i<pagesize; i++)
|
|
game[i]->ResetState();
|
|
|
|
if(f == 1 && selectedItem >= 0)
|
|
game[selectedItem]->SetState(STATE_SELECTED);
|
|
}
|
|
|
|
|
|
void GuiGameGrid::ResetState()
|
|
{
|
|
LOCK(this);
|
|
if(state != STATE_DISABLED)
|
|
{
|
|
state = STATE_DEFAULT;
|
|
stateChan = -1;
|
|
}
|
|
|
|
for(int i=0; i<pagesize; i++) {
|
|
game[i]->ResetState();
|
|
}
|
|
}
|
|
|
|
|
|
int GuiGameGrid::GetOffset()
|
|
{
|
|
LOCK(this);
|
|
return listOffset;
|
|
}
|
|
|
|
|
|
int GuiGameGrid::GetClickedOption()
|
|
{
|
|
LOCK(this);
|
|
int found = -1;
|
|
if (clickedItem>=0)
|
|
{
|
|
game[clickedItem]->SetState(STATE_SELECTED);
|
|
found = gameIndex[clickedItem];
|
|
clickedItem=-1;
|
|
}
|
|
return found;
|
|
}
|
|
|
|
|
|
int GuiGameGrid::GetSelectedOption()
|
|
{
|
|
LOCK(this);
|
|
int found = -1;
|
|
for(int i=0; i<pagesize; i++)
|
|
{
|
|
if(game[i]->GetState() == STATE_SELECTED)
|
|
{
|
|
game[i]->SetState(STATE_SELECTED);
|
|
found = gameIndex[i];
|
|
break;
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
/**
|
|
* Draw the button on screen
|
|
*/
|
|
void GuiGameGrid::Draw()
|
|
{
|
|
LOCK(this);
|
|
if(!this->IsVisible() || !gameCnt)
|
|
return;
|
|
|
|
if(goLeft>0)
|
|
{
|
|
goLeft--;
|
|
int wsi = CFG.widescreen ? 0:1;
|
|
float f2 = ((float)goLeft)/goSteps;
|
|
float f1 = 1.0-f2;
|
|
int (*Pos)[2][2] = VALUE4ROWS(rows, Pos1, Pos2, Pos3);
|
|
int (*Skew)[8] = VALUE4ROWS(rows, Skew1, Skew2, Skew3);
|
|
|
|
for(int i=0; i<pagesize-rows; i++)
|
|
{
|
|
game[i]->SetPosition( Pos[i][wsi][0]*f1 + Pos[i+rows][wsi][0]*f2+THEME.gamegrid_x,
|
|
Pos[i][wsi][1]*f1 + Pos[i+rows][wsi][1]*f2+THEME.gamegrid_y);
|
|
|
|
game[i]->SetSkew( Skew[i][0]*f1 + Skew[i+rows][0]*f2,
|
|
Skew[i][1]*f1 + Skew[i+rows][1]*f2,
|
|
Skew[i][2]*f1 + Skew[i+rows][2]*f2,
|
|
Skew[i][3]*f1 + Skew[i+rows][3]*f2,
|
|
Skew[i][4]*f1 + Skew[i+rows][4]*f2,
|
|
Skew[i][5]*f1 + Skew[i+rows][5]*f2,
|
|
Skew[i][6]*f1 + Skew[i+rows][6]*f2,
|
|
Skew[i][7]*f1 + Skew[i+rows][7]*f2);
|
|
}
|
|
}
|
|
else if(goRight>0)
|
|
{
|
|
goRight--;
|
|
int wsi = CFG.widescreen ? 0:1;
|
|
float f2 = ((float)goRight)/goSteps;
|
|
float f1 = 1.0-f2;
|
|
int (*Pos)[2][2] = VALUE4ROWS(rows, Pos1, Pos2, Pos3);
|
|
int (*Skew)[8] = VALUE4ROWS(rows, Skew1, Skew2, Skew3);
|
|
for(int i=rows; i<pagesize; i++)
|
|
{
|
|
game[i]->SetPosition( Pos[i][wsi][0]*f1 + Pos[i-rows][wsi][0]*f2+THEME.gamegrid_x,
|
|
Pos[i][wsi][1]*f1 + Pos[i-rows][wsi][1]*f2+THEME.gamegrid_y);
|
|
|
|
game[i]->SetSkew( Skew[i][0]*f1 + Skew[i-rows][0]*f2,
|
|
Skew[i][1]*f1 + Skew[i-rows][1]*f2,
|
|
Skew[i][2]*f1 + Skew[i-rows][2]*f2,
|
|
Skew[i][3]*f1 + Skew[i-rows][3]*f2,
|
|
Skew[i][4]*f1 + Skew[i-rows][4]*f2,
|
|
Skew[i][5]*f1 + Skew[i-rows][5]*f2,
|
|
Skew[i][6]*f1 + Skew[i-rows][6]*f2,
|
|
Skew[i][7]*f1 + Skew[i-rows][7]*f2);
|
|
}
|
|
}
|
|
|
|
for(int i=0; i<pagesize; i++)
|
|
game[i]->Draw();
|
|
if(gameCnt > pagesize-2*rows)
|
|
{
|
|
btnRight->Draw();
|
|
btnLeft->Draw();
|
|
}
|
|
|
|
btnRowUp->Draw();
|
|
btnRowDown->Draw();
|
|
|
|
if (focus && Settings.tooltips == TooltipsOn)
|
|
for(int i=0; i<pagesize; i++)
|
|
game[i]->DrawTooltip();
|
|
|
|
this->UpdateEffects();
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Change the number of rows
|
|
*/
|
|
void GuiGameGrid::ChangeRows(int n)
|
|
{
|
|
LOCK(this);
|
|
if(n != rows)
|
|
Reload(gameList, gameCnt, n, -1);
|
|
}
|
|
|
|
|
|
void GuiGameGrid::Update(GuiTrigger * t)
|
|
{
|
|
LOCK(this);
|
|
if(state == STATE_DISABLED || !t || !gameCnt)
|
|
return;
|
|
|
|
if(!(game[0]->GetEffect() || game[0]->GetEffectOnOver()))
|
|
{
|
|
for(int i=0; i<pagesize; i++)
|
|
game[i]->SetEffectGrow();
|
|
}
|
|
|
|
btnRight->Update(t);
|
|
btnLeft->Update(t);
|
|
btnRowUp->Update(t);
|
|
btnRowDown->Update(t);
|
|
|
|
selectedItem = -1;
|
|
clickedItem = -1;
|
|
for(int i=0; i<pagesize; i++)
|
|
{
|
|
game[i]->Update(t);
|
|
if(game[i]->GetState() == STATE_SELECTED)
|
|
{
|
|
selectedItem = i;
|
|
}
|
|
if(game[i]->GetState() == STATE_CLICKED)
|
|
{
|
|
clickedItem = i;
|
|
}
|
|
|
|
}
|
|
// navigation
|
|
if(focus && gameCnt >= (pagesize-2*rows) && goLeft==0 && goRight==0)
|
|
{
|
|
// Left/Right Navigation
|
|
|
|
if (btnLeft->GetState() == STATE_CLICKED)
|
|
{
|
|
WPAD_ScanPads();
|
|
u16 buttons = 0;
|
|
for(int i=0; i<4; i++)
|
|
buttons |= WPAD_ButtonsHeld(i);
|
|
if(!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_MINUS) || t->Left()))
|
|
{
|
|
btnLeft->ResetState();
|
|
return;
|
|
}
|
|
|
|
if (Settings.xflip==sysmenu || Settings.xflip==yes || Settings.xflip==disk3d)
|
|
goRight = goSteps;
|
|
else
|
|
goLeft = goSteps;
|
|
}
|
|
else if(btnRight->GetState() == STATE_CLICKED)
|
|
{
|
|
WPAD_ScanPads();
|
|
u16 buttons = 0;
|
|
for(int i=0; i<4; i++)
|
|
buttons |= WPAD_ButtonsHeld(i);
|
|
if(!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_PLUS) || t->Right()))
|
|
{
|
|
btnRight->ResetState();
|
|
return;
|
|
}
|
|
if (Settings.xflip==sysmenu ||Settings.xflip==yes || Settings.xflip==disk3d)
|
|
goLeft = goSteps;
|
|
else
|
|
goRight = goSteps;
|
|
}
|
|
|
|
if (goLeft == goSteps)
|
|
{
|
|
GuiButton *tmpButton[rows];
|
|
GuiTooltip *tmpTooltip[rows];
|
|
listOffset = OFFSETLIMIT(listOffset + rows, rows, gameCnt); // set the new listOffset
|
|
// Save left Tooltip & Button and destroy left Image + Image-Data
|
|
for (int i=0; i<rows; i++)
|
|
{
|
|
delete coverImg[i]; coverImg[i] = NULL;game[i]->SetImage(NULL);
|
|
tmpTooltip[i] = titleTT[i];
|
|
tmpButton[i] = game[i];
|
|
}
|
|
// Move all Page-Entries one step left
|
|
for (int i=0; i<(pagesize-rows); i++)
|
|
{
|
|
titleTT[i] = titleTT[i+rows];
|
|
coverImg[i] = coverImg[i+rows];
|
|
game[i] = game[i+rows];
|
|
gameIndex[i] = gameIndex[i+rows];
|
|
}
|
|
// set saved Tooltip, Button & gameIndex to right
|
|
int wsi = CFG.widescreen ? 0:1;
|
|
int (*Pos)[2][2] = VALUE4ROWS(rows, Pos1, Pos2, Pos3);
|
|
int (*Skew)[8] = VALUE4ROWS(rows, Skew1, Skew2, Skew3);
|
|
|
|
for (int i=0; i<rows; i++)
|
|
{
|
|
int ii = i+pagesize-rows;
|
|
gameIndex[ii] = GetGameIndex(ii, rows, listOffset, gameCnt);
|
|
titleTT[ii] = tmpTooltip[i];
|
|
coverImg[ii] = NULL;
|
|
if(gameIndex[ii] != -1)
|
|
{
|
|
coverImg[ii] = new GuiImageAsync(GameGridLoadCoverImage, &gameList[gameIndex[ii]], sizeof(struct discHdr), &noCover);
|
|
if(coverImg[ii])
|
|
{
|
|
coverImg[ii] ->SetWidescreen(CFG.widescreen);
|
|
coverImg[ii] ->SetScale(VALUE4ROWS(rows, 1.0, 0.6, 0.26));
|
|
coverImg[ii] ->SetPosition(0,VALUE4ROWS(rows, 0, -50, -80));
|
|
}
|
|
titleTT[ii] ->SetText(get_title(&gameList[gameIndex[ii]]));
|
|
}
|
|
else
|
|
{
|
|
titleTT[ii] ->SetText(NULL);
|
|
}
|
|
|
|
game[ii] = tmpButton[i];
|
|
game[ii] ->SetImage(coverImg[ii]);
|
|
game[ii] ->SetPosition(Pos[ii][wsi][0], Pos[ii][wsi][1]);
|
|
game[ii] ->SetSkew(&Skew[ii][0]);
|
|
game[ii] ->RemoveToolTip();
|
|
if(gameIndex[ii] != -1)
|
|
{
|
|
game[ii] ->SetClickable(true);
|
|
game[ii] ->SetVisible(true);
|
|
}
|
|
else
|
|
{
|
|
game[ii] ->SetVisible(false);
|
|
game[ii] ->SetClickable(false);
|
|
game[ii] ->RemoveSoundOver();
|
|
}
|
|
}
|
|
// Set Tooltip-Position
|
|
int ttoffset_x = CFG.widescreen ? VALUE4ROWS(rows, 70, 35, 0) : VALUE4ROWS(rows, 150, 55, 25);
|
|
int ttoffset_y = -VALUE4ROWS(rows, 224, 133, 68)/4;
|
|
for (int i=0; i<pagesize; i++)
|
|
{
|
|
switch((i*3)/pagesize)
|
|
{
|
|
case 0:
|
|
game[i]->SetToolTip(titleTT[i], ttoffset_x, ttoffset_y, ALIGN_LEFT, ALIGN_MIDDLE);
|
|
break;
|
|
case 1:
|
|
game[i]->SetToolTip(titleTT[i], 0, ttoffset_y, ALIGN_CENTRE, ALIGN_MIDDLE);
|
|
break;
|
|
case 2:
|
|
game[i]->SetToolTip(titleTT[i], -ttoffset_x, ttoffset_y, ALIGN_RIGHT, ALIGN_MIDDLE);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (goRight == goSteps)
|
|
{
|
|
GuiButton *tmpButton[rows];
|
|
GuiTooltip *tmpTooltip[rows];
|
|
listOffset = OFFSETLIMIT(listOffset - rows, rows, gameCnt); // set the new listOffset
|
|
// Save right Button & Tooltip and destroy right Image-Data
|
|
for (int i=0; i<rows; i++)
|
|
{
|
|
int ii = i+pagesize-rows;
|
|
delete coverImg[ii]; coverImg[ii] = NULL; game[ii]->SetImage(NULL);
|
|
tmpTooltip[i] = titleTT[ii];
|
|
tmpButton[i] = game[ii];
|
|
}
|
|
// Move all Page-Entries one step right
|
|
for (int i=pagesize-1; i>=rows; i--)
|
|
{
|
|
titleTT[i] = titleTT[i-rows];
|
|
coverImg[i] = coverImg[i-rows];
|
|
game[i] = game[i-rows];
|
|
gameIndex[i] = gameIndex[i-rows];
|
|
}
|
|
// set saved Image, Button & gameIndex to left
|
|
int wsi = CFG.widescreen ? 0:1;
|
|
int (*Pos)[2][2] = VALUE4ROWS(rows, Pos1, Pos2, Pos3);
|
|
int (*Skew)[8] = VALUE4ROWS(rows, Skew1, Skew2, Skew3);
|
|
|
|
for (int i=0; i<rows; i++)
|
|
{
|
|
gameIndex[i] = GetGameIndex(i, rows, listOffset, gameCnt);
|
|
titleTT[i] = tmpTooltip[i];
|
|
coverImg[i] = NULL;
|
|
if(gameIndex[i] != -1)
|
|
{
|
|
coverImg[i] = new GuiImageAsync(GameGridLoadCoverImage, &gameList[gameIndex[i]], sizeof(struct discHdr), &noCover);
|
|
if(coverImg[i])
|
|
{
|
|
coverImg[i] ->SetWidescreen(CFG.widescreen);
|
|
coverImg[i] ->SetScale(VALUE4ROWS(rows, 1.0, 0.6, 0.26));
|
|
coverImg[i] ->SetPosition(0,VALUE4ROWS(rows, 0, -50, -80));
|
|
}
|
|
titleTT[i] ->SetText(get_title(&gameList[gameIndex[i]]));
|
|
}
|
|
else
|
|
{
|
|
titleTT[i] ->SetText(NULL);
|
|
}
|
|
game[i] = tmpButton[i];
|
|
game[i] ->SetImage(coverImg[i]);
|
|
game[i] ->SetPosition(Pos[i][wsi][0], Pos[i][wsi][1]);
|
|
game[i] ->SetSkew(&Skew[i][0]);
|
|
game[i] ->RemoveToolTip();
|
|
if(gameIndex[i] != -1)
|
|
{
|
|
game[i] ->SetClickable(true);
|
|
game[i] ->SetVisible(true);
|
|
}
|
|
else
|
|
{
|
|
game[i] ->SetVisible(false);
|
|
game[i] ->SetClickable(false);
|
|
game[i] ->RemoveSoundOver();
|
|
}
|
|
}
|
|
// Set Tooltip-Position
|
|
int ttoffset_x = CFG.widescreen ? VALUE4ROWS(rows, 70, 35, 0) : VALUE4ROWS(rows, 150, 55, 25);
|
|
int ttoffset_y = -VALUE4ROWS(rows, 224, 133, 68)/4;
|
|
for (int i=0; i< pagesize; i++)
|
|
{
|
|
switch((i*3)/pagesize)
|
|
{
|
|
case 0:
|
|
game[i]->SetToolTip(titleTT[i], ttoffset_x, ttoffset_y, ALIGN_LEFT, ALIGN_MIDDLE);
|
|
break;
|
|
case 1:
|
|
game[i]->SetToolTip(titleTT[i], 0, ttoffset_y, ALIGN_CENTRE, ALIGN_MIDDLE);
|
|
break;
|
|
case 2:
|
|
game[i]->SetToolTip(titleTT[i], -ttoffset_x, ttoffset_y, ALIGN_RIGHT, ALIGN_MIDDLE);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((btnRowUp->GetState() == STATE_CLICKED))
|
|
{
|
|
if ((rows==1)&&(gameCnt>=18))this->ChangeRows(2);
|
|
else if ((rows==2)&&(gameCnt>=45))this->ChangeRows(3);
|
|
btnRowUp->ResetState();
|
|
return;
|
|
}
|
|
|
|
if ((btnRowDown->GetState() == STATE_CLICKED))
|
|
{
|
|
if (rows==3)this->ChangeRows(2);
|
|
else if (rows==2)this->ChangeRows(1);
|
|
btnRowDown->ResetState();
|
|
return;
|
|
}
|
|
|
|
if(updateCB)
|
|
updateCB(this);
|
|
}
|
|
|
|
|
|
void GuiGameGrid::Reload(struct discHdr * l, int count, int Rows, int ListOffset)
|
|
{
|
|
LOCK(this);
|
|
|
|
// CleanUp
|
|
if(game)
|
|
for(int i=pagesize-1; i>=0; i--)
|
|
delete game[i];
|
|
|
|
if(coverImg)
|
|
for(int i=pagesize-1; i>=0; i--)
|
|
delete coverImg[i];
|
|
|
|
// if(cover)
|
|
// for(int i=pagesize-1; i>=0; i--)
|
|
// delete cover[i];
|
|
|
|
if(titleTT)
|
|
for(int i=pagesize-1; i>=0; i--)
|
|
delete titleTT[i];
|
|
|
|
delete [] gameIndex;
|
|
delete [] game;
|
|
delete [] coverImg;
|
|
// delete [] cover;
|
|
delete [] titleTT;
|
|
|
|
gameList = l;
|
|
gameCnt = count;
|
|
goLeft = 0;
|
|
goRight = 0;
|
|
|
|
rows = Rows > 3 ? 3 : (Rows < 1 ? 1 : Rows);
|
|
if ((count<45)&&(rows==3))rows=2;
|
|
if ((count<18)&&(rows==2))rows=1;
|
|
|
|
if(ListOffset>=0) // if ListOffset < 0 then no change
|
|
listOffset = ListOffset;
|
|
listOffset = OFFSETLIMIT(listOffset, rows, gameCnt);
|
|
|
|
selectedItem = -1;
|
|
clickedItem = -1;
|
|
|
|
pagesize = ROWS2PAGESIZE(rows);
|
|
|
|
// Page-Stuff
|
|
gameIndex = new int[pagesize];
|
|
titleTT = new GuiTooltip *[pagesize];
|
|
// cover = new GuiImageData *[pagesize];
|
|
coverImg = new GuiImageAsync *[pagesize];
|
|
game = new GuiButton *[pagesize];
|
|
|
|
|
|
int wsi = CFG.widescreen ? 0:1;
|
|
int (*Pos)[2][2] = VALUE4ROWS(rows, Pos1, Pos2, Pos3);
|
|
int (*Skew)[8] = VALUE4ROWS(rows, Skew1, Skew2, Skew3);
|
|
|
|
int ttoffset_x = CFG.widescreen ? VALUE4ROWS(rows, 70, 35, 0) : VALUE4ROWS(rows, 150, 55, 25);
|
|
int ttoffset_y = -VALUE4ROWS(rows, 224, 133, 68)/4;
|
|
|
|
for(int i=0; i < pagesize; i++)
|
|
{
|
|
//------------------------
|
|
// Index
|
|
//------------------------
|
|
gameIndex[i] = GetGameIndex(i, rows, listOffset, gameCnt);
|
|
|
|
//------------------------
|
|
// Tooltip
|
|
//------------------------
|
|
if( gameIndex[i] != -1 )
|
|
titleTT[i] = new GuiTooltip(get_title(&gameList[gameIndex[i]]), THEME.tooltipAlpha);
|
|
else
|
|
titleTT[i] = new GuiTooltip(NULL, THEME.tooltipAlpha);
|
|
|
|
//------------------------
|
|
// ImageData
|
|
//------------------------
|
|
// if( gameIndex[i] != -1 )
|
|
// cover[i] = LoadCoverImage(&gameList[gameIndex[i]], false /*bool Prefere3D*/);
|
|
// else
|
|
// cover[i] = new GuiImageData(NULL);
|
|
|
|
//------------------------
|
|
// Image
|
|
//------------------------
|
|
coverImg[i] = NULL;
|
|
if( gameIndex[i] != -1 )
|
|
{
|
|
coverImg[i] = new GuiImageAsync(GameGridLoadCoverImage, &gameList[gameIndex[i]], sizeof(struct discHdr), &noCover);
|
|
if(coverImg[i])
|
|
{
|
|
coverImg[i]->SetWidescreen(CFG.widescreen);
|
|
// if ( rows == 2 ) coverImg[i]->SetScale(.6); //these are the numbers for 2 rows
|
|
// else if ( rows == 3 ) coverImg[i]->SetScale(.26); //these are the numbers for 3 rows
|
|
coverImg[i]->SetScale(VALUE4ROWS(rows, 1.0, 0.6, 0.26));
|
|
coverImg[i]->SetPosition(0,VALUE4ROWS(rows, 0, -50, -80));
|
|
}
|
|
}
|
|
|
|
//------------------------
|
|
// GameButton
|
|
//------------------------
|
|
game[i] = new GuiButton(VALUE4ROWS(rows, 160, 75, 35), VALUE4ROWS(rows, 224, 133, 68));
|
|
game[i]->SetParent(this);
|
|
game[i]->SetImage(coverImg[i]);
|
|
game[i]->SetAlignment(ALIGN_TOP,ALIGN_LEFT);
|
|
game[i]->SetPosition(Pos[i][wsi][0]+THEME.gamegrid_x, Pos[i][wsi][1]+THEME.gamegrid_y);
|
|
game[i]->SetSkew(&Skew[i][0]);
|
|
game[i]->SetTrigger(trigA);
|
|
game[i]->SetSoundOver(btnSoundOver);
|
|
game[i]->SetSoundClick(btnSoundClick);
|
|
game[i]->SetRumble(false);
|
|
switch((i*3)/pagesize)
|
|
{
|
|
case 0:
|
|
game[i]->SetToolTip(titleTT[i], ttoffset_x, ttoffset_y, ALIGN_LEFT, ALIGN_MIDDLE);
|
|
break;
|
|
case 1:
|
|
game[i]->SetToolTip(titleTT[i], 0, ttoffset_y, ALIGN_CENTRE, ALIGN_MIDDLE);
|
|
break;
|
|
case 2:
|
|
game[i]->SetToolTip(titleTT[i], -ttoffset_x, ttoffset_y, ALIGN_RIGHT, ALIGN_MIDDLE);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if(gameIndex[i] >= 0)
|
|
{
|
|
game[i]->SetClickable(true);
|
|
game[i]->SetVisible(true);
|
|
}
|
|
else
|
|
{
|
|
game[i]->SetVisible(false);
|
|
game[i]->SetClickable(false);
|
|
// game[i]->RemoveSoundOver();
|
|
}
|
|
}
|
|
Settings.gridRows = rows;
|
|
if(isInserted(bootDevice))
|
|
cfg_save_global();
|
|
}
|
|
|