mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-03 18:15:06 +01:00
9e79c9d99b
* code cleanup
972 lines
30 KiB
C++
972 lines
30 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 "usbloader/GameList.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}},
|
|
|
|
{{660, 58}, {660, 58}},
|
|
{{660, 153}, {660, 153}},
|
|
{{660, 250}, {660, 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, 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( 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 ( !gameList.size() )
|
|
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() || !gameList.size() )
|
|
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 ( gameList.size() > 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( n, -1 );
|
|
}
|
|
|
|
|
|
void GuiGameGrid::Update( GuiTrigger * t )
|
|
{
|
|
LOCK( this );
|
|
if ( state == STATE_DISABLED || !t || !gameList.size() )
|
|
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 && gameList.size() >= ( 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, gameList.size() ); // 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, gameList.size() );
|
|
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, gameList.size() ); // 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, gameList.size() );
|
|
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 ) && ( gameList.size() >= 18 ) )this->ChangeRows( 2 );
|
|
else if ( ( rows == 2 ) && ( gameList.size() >= 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( 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;
|
|
|
|
goLeft = 0;
|
|
goRight = 0;
|
|
|
|
rows = Rows > 3 ? 3 : ( Rows < 1 ? 1 : Rows );
|
|
if ( ( gameList.size() < 45 ) && ( rows == 3 ) )rows = 2;
|
|
if ( ( gameList.size() < 18 ) && ( rows == 2 ) )rows = 1;
|
|
|
|
if ( ListOffset >= 0 ) // if ListOffset < 0 then no change
|
|
listOffset = ListOffset;
|
|
listOffset = OFFSETLIMIT( listOffset, rows, gameList.size() );
|
|
|
|
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, gameList.size() );
|
|
|
|
//------------------------
|
|
// 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();
|
|
}
|
|
|