mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-13 23:15:09 +01:00
991e48c398
* Reverted default titles path to be /usbloader_gx/ Too many users reported issue with sub-folder. * Added favorite icons to Animated banner Game Window. (Thanks to Suloku for the patch!) * Added GUI settings to choose favorite layout on banners. * Updated French language
727 lines
21 KiB
C++
727 lines
21 KiB
C++
/****************************************************************************
|
|
* Copyright (C) 2012 Dimok
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
****************************************************************************/
|
|
#include <unistd.h>
|
|
#include "BannerWindow.hpp"
|
|
#include "GUI/GuiBannerGrid.h"
|
|
#include "banner/BannerAsync.h"
|
|
#include "banner/CustomBanner.h"
|
|
#include "banner/OpeningBNR.hpp"
|
|
#include "settings/CSettings.h"
|
|
#include "settings/CGameStatistics.h"
|
|
#include "settings/menus/GameSettingsMenu.hpp"
|
|
#include "SystemMenu/SystemMenuResources.h"
|
|
#include "prompts/GameWindow.hpp"
|
|
#include "themes/CTheme.h"
|
|
#include "language/gettext.h"
|
|
#include "menu/menus.h"
|
|
#include "utils/tools.h"
|
|
|
|
// Load only once
|
|
BannerFrame BannerWindow::bannerFrame;
|
|
|
|
BannerWindow::BannerWindow(GameBrowseMenu *m, struct discHdr *header)
|
|
: GuiWindow(screenwidth, screenheight)
|
|
, browserMenu(m)
|
|
, MaxAnimSteps(Settings.BannerZoomDuration)
|
|
{
|
|
ScreenProps.x = screenwidth;
|
|
ScreenProps.y = screenheight;
|
|
|
|
f32 xOffset = Settings.BannerProjectionOffsetX;
|
|
f32 yOffset = Settings.BannerProjectionOffsetY;
|
|
|
|
guMtxIdentity(modelview);
|
|
guMtxTransApply (modelview, modelview, xOffset, yOffset, 0.0F);
|
|
|
|
memcpy(&originalProjection, &FSProjection2D, sizeof(Mtx44));
|
|
|
|
returnVal = -1;
|
|
gameSelected = 0;
|
|
gameSound = NULL;
|
|
dvdheader = NULL;
|
|
reducedVol = false;
|
|
|
|
if(!bannerFrame.IsLoaded())
|
|
bannerFrame.Load(U8Archive(SystemMenuResources::Instance()->GetChanTtlAsh(),
|
|
SystemMenuResources::Instance()->GetChanTtlAshSize()));
|
|
|
|
AnimStep = 0;
|
|
AnimPosX = 0.5f * (ScreenProps.x - fIconWidth);
|
|
AnimPosY = 0.5f * (ScreenProps.y - fIconHeight);
|
|
AnimZoomIn = true;
|
|
AnimationRunning = false;
|
|
|
|
int gameIdx;
|
|
|
|
//! get the game index to this header
|
|
for(gameIdx = 0; gameIdx < gameList.size(); ++gameIdx)
|
|
{
|
|
if(gameList[gameIdx] == header)
|
|
{
|
|
gameSelected = gameIdx;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//! Set dvd header if the header does not match any of the list games
|
|
if(gameIdx == gameList.size())
|
|
dvdheader = header;
|
|
|
|
GuiBannerGrid *bannerBrowser = dynamic_cast<GuiBannerGrid *>(browserMenu->GetGameBrowser());
|
|
if(bannerBrowser)
|
|
bannerBrowser->GetIconCoordinates(gameSelected, &AnimPosX, &AnimPosY);
|
|
|
|
gameBanner = new Banner;
|
|
|
|
imgFavorite = Resources::GetImageData("favorite.png");
|
|
imgNotFavorite = Resources::GetImageData("not_favorite.png");
|
|
imgLeft = Resources::GetImageData("startgame_arrow_left.png");
|
|
imgRight = Resources::GetImageData("startgame_arrow_right.png");
|
|
|
|
trigA = new GuiTrigger;
|
|
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
|
|
trigB = new GuiTrigger;
|
|
trigB->SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B);
|
|
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);
|
|
trigPlus = new GuiTrigger;
|
|
trigPlus->SetButtonOnlyTrigger(-1, WPAD_BUTTON_PLUS | WPAD_CLASSIC_BUTTON_PLUS, PAD_TRIGGER_R);
|
|
trigMinus = new GuiTrigger;
|
|
trigMinus->SetButtonOnlyTrigger(-1, WPAD_BUTTON_MINUS | WPAD_CLASSIC_BUTTON_MINUS, PAD_TRIGGER_L);
|
|
|
|
playcntTxt = new GuiText((char*) NULL, 18, thColor("r=0 g=0 b=0 a=255 - banner window playcount text color"));
|
|
playcntTxt->SetAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
|
|
playcntTxt->SetPosition(thInt("0 - banner window play count pos x"),
|
|
thInt("215 - banner window play count pos y") - Settings.AdjustOverscanY / 2);
|
|
|
|
settingsBtn = new GuiButton(215, 75);
|
|
settingsBtn->SetAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
|
|
settingsBtn->SetSoundOver(btnSoundOver);
|
|
settingsBtn->SetSoundClick(btnSoundClick2);
|
|
settingsBtn->SetPosition(-120, 175);
|
|
settingsBtn->SetTrigger(trigA);
|
|
|
|
startBtn = new GuiButton(215, 75);
|
|
startBtn->SetAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
|
|
startBtn->SetSoundOver(btnSoundOver);
|
|
startBtn->SetSoundClick(btnSoundClick2);
|
|
startBtn->SetPosition(110, 175);
|
|
startBtn->SetTrigger(trigA);
|
|
|
|
backBtn = new GuiButton(215, 75);
|
|
backBtn->SetAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
|
|
backBtn->SetSoundOver(btnSoundOver);
|
|
backBtn->SetSoundClick(btnSoundClick2);
|
|
backBtn->SetPosition(-screenwidth, -screenheight); // set out of screen
|
|
backBtn->SetTrigger(0, trigA);
|
|
backBtn->SetTrigger(1, trigB);
|
|
|
|
// Set favorite button position
|
|
int xPos = -198-(3*27)-14;
|
|
if(Settings.bannerFavIcon == BANNER_FAVICON_SINGLE_LINEA) // push more to the screen border
|
|
xPos += -14;
|
|
int yPos = 175-27;
|
|
float angle = 3*M_PI/2;
|
|
for(int i = 0; i < FAVORITE_STARS; ++i)
|
|
{
|
|
|
|
if(Settings.bannerFavIcon == BANNER_FAVICON_CIRC)
|
|
{
|
|
/*
|
|
Arrangement:
|
|
0
|
|
1
|
|
2
|
|
3
|
|
4
|
|
*/
|
|
|
|
if (i==0 || i == 4){
|
|
xPos = (-180-70 - 40*cos(angle)); //litte adjustment, image looks too far
|
|
}
|
|
else{
|
|
xPos = (-180-65 - 40*cos(angle));
|
|
}
|
|
yPos = (169 + 40*sin(angle));
|
|
angle += M_PI/4;
|
|
|
|
/*
|
|
if (i == 0){
|
|
xPos += 27+14;
|
|
}else if (i < 3){
|
|
xPos += -14;
|
|
yPos += 27;
|
|
} else if (i >= 3){
|
|
xPos += 14;
|
|
yPos += 27;
|
|
}
|
|
*/
|
|
}
|
|
else if(Settings.bannerFavIcon == BANNER_FAVICON_SIN)
|
|
{
|
|
/*
|
|
Arrangement:
|
|
0 2 4
|
|
1 3
|
|
*/
|
|
|
|
xPos += 27;
|
|
xPos += -14;
|
|
if ((i&1)==0)
|
|
{
|
|
yPos += 27;
|
|
}
|
|
else
|
|
{
|
|
yPos -= 27;
|
|
}
|
|
}
|
|
else if(Settings.bannerFavIcon == BANNER_FAVICON_MULTI_LINE)
|
|
{
|
|
/*
|
|
Sequential arrangement, 3 on top, 2 at bottom:
|
|
1 2 3
|
|
4 5
|
|
*/
|
|
|
|
xPos += 27;
|
|
if (i==2){
|
|
xPos += -27-27-14;
|
|
yPos += 27;
|
|
}
|
|
|
|
}
|
|
else if(Settings.bannerFavIcon == BANNER_FAVICON_SINGLE_LINEA)
|
|
{
|
|
/* Arrangement : inline above the settings */
|
|
xPos += 27;
|
|
yPos = 95;
|
|
}
|
|
else if(Settings.bannerFavIcon == BANNER_FAVICON_SINGLE_LINEB)
|
|
{
|
|
/* Arrangement : inline below the settings */
|
|
xPos += 27;
|
|
yPos = 210;
|
|
}
|
|
|
|
FavoriteBtnImg[i] = new GuiImage;
|
|
FavoriteBtnImg[i]->SetWidescreen(Settings.widescreen);
|
|
FavoriteBtn[i] = new GuiButton(imgFavorite->GetWidth(), imgFavorite->GetHeight());
|
|
FavoriteBtn[i]->SetAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
|
|
FavoriteBtn[i]->SetPosition(xPos, yPos);
|
|
FavoriteBtn[i]->SetImage(FavoriteBtnImg[i]);
|
|
FavoriteBtn[i]->SetSoundOver(btnSoundOver);
|
|
FavoriteBtn[i]->SetSoundClick(btnSoundClick2);
|
|
FavoriteBtn[i]->SetTrigger(trigA);
|
|
FavoriteBtn[i]->SetEffectGrow();
|
|
}
|
|
|
|
btnLeftImg = new GuiImage(imgLeft);
|
|
if (Settings.wsprompt) btnLeftImg->SetWidescreen(Settings.widescreen);
|
|
btnLeft = new GuiButton(btnLeftImg, btnLeftImg, ALIGN_LEFT, ALIGN_MIDDLE, 20, -50, trigA, btnSoundOver, btnSoundClick2, 1);
|
|
btnLeft->SetTrigger(trigL);
|
|
btnLeft->SetTrigger(trigMinus);
|
|
|
|
btnRightImg = new GuiImage(imgRight);
|
|
if (Settings.wsprompt) btnRightImg->SetWidescreen(Settings.widescreen);
|
|
btnRight = new GuiButton(btnRightImg, btnRightImg, ALIGN_RIGHT, ALIGN_MIDDLE, -20, -50, trigA, btnSoundOver, btnSoundClick2, 1);
|
|
btnRight->SetTrigger(trigR);
|
|
btnRight->SetTrigger(trigPlus);
|
|
|
|
if (Settings.ShowPlayCount)
|
|
Append(playcntTxt);
|
|
Append(backBtn);
|
|
|
|
if (!dvdheader) //stuff we don't show if it is a DVD mounted
|
|
{
|
|
Append(btnLeft);
|
|
Append(btnRight);
|
|
}
|
|
|
|
bannerFrame.SetButtonBText(tr("Start"));
|
|
|
|
//check if unlocked
|
|
if (Settings.godmode || !(Settings.ParentalBlocks & BLOCK_GAME_SETTINGS))
|
|
{
|
|
bannerFrame.SetButtonAText(tr("Settings"));
|
|
Append(settingsBtn);
|
|
if(Settings.bannerFavIcon != BANNER_FAVICON_OFF)
|
|
for(int i = 0; i < FAVORITE_STARS; ++i)
|
|
Append(FavoriteBtn[i]);
|
|
}
|
|
else
|
|
{
|
|
bannerFrame.SetButtonAText(tr("Back"));
|
|
backBtn->SetPosition(-120, 175);
|
|
}
|
|
|
|
Append(startBtn); //! Appending the disc on top of all
|
|
|
|
ChangeGame(false);
|
|
}
|
|
|
|
BannerWindow::~BannerWindow()
|
|
{
|
|
if(parentElement)
|
|
((GuiWindow * ) parentElement)->Remove(this);
|
|
|
|
RemoveAll();
|
|
|
|
delete trigA;
|
|
delete trigB;
|
|
delete trigL;
|
|
delete trigR;
|
|
delete trigPlus;
|
|
delete trigMinus;
|
|
|
|
delete imgFavorite;
|
|
delete imgNotFavorite;
|
|
delete imgLeft;
|
|
delete imgRight;
|
|
|
|
delete btnLeftImg;
|
|
delete btnRightImg;
|
|
|
|
delete playcntTxt;
|
|
|
|
delete startBtn;
|
|
delete backBtn;
|
|
delete settingsBtn;
|
|
delete btnLeft;
|
|
delete btnRight;
|
|
|
|
for(int i = 0; i < FAVORITE_STARS; ++i)
|
|
{
|
|
delete FavoriteBtnImg[i];
|
|
delete FavoriteBtn[i];
|
|
}
|
|
|
|
if(gameSound) gameSound->Stop();
|
|
delete gameSound;
|
|
bgMusic->SetVolume(Settings.volume);
|
|
|
|
delete gameBanner;
|
|
|
|
memcpy(&FSProjection2D, &originalProjection, sizeof(Mtx44));
|
|
ResumeGui();
|
|
}
|
|
|
|
void BannerWindow::ChangeGame(bool playsound)
|
|
{
|
|
struct discHdr * header = (dvdheader ? dvdheader : gameList[gameSelected]);
|
|
|
|
//! Stop thread because all the extract functions are not thread safe
|
|
//! Let it finish the current loading though
|
|
BannerAsync::HaltThread();
|
|
|
|
Banner *newBanner = NULL;
|
|
// continue playing sound during loading process
|
|
if((header->type == TYPE_GAME_GC_IMG) || (header->type == TYPE_GAME_GC_DISC) || (header->type == TYPE_GAME_GC_EXTRACTED))
|
|
{
|
|
//! try cache file first and if that fails create the default one
|
|
if(BNRInstance::Instance()->Load(header) && BNRInstance::Instance()->Get() != NULL)
|
|
newBanner = new Banner;
|
|
else
|
|
newBanner = BNRInstance::Instance()->CreateGCBanner(header);
|
|
}
|
|
else {
|
|
BNRInstance::Instance()->Load(header);
|
|
newBanner = new Banner;
|
|
}
|
|
|
|
//! remove game sound
|
|
if (gameSound)
|
|
{
|
|
gameSound->Stop();
|
|
delete gameSound;
|
|
gameSound = NULL;
|
|
}
|
|
|
|
playcntTxt->SetTextf("%s: %i", tr( "Play Count" ), GameStatistics.GetPlayCount(header));
|
|
|
|
HaltGui();
|
|
|
|
// set the new banner
|
|
delete gameBanner;
|
|
gameBanner = newBanner;
|
|
|
|
// Do not load stuff on game cube games
|
|
if(BNRInstance::Instance()->Get() != NULL)
|
|
gameBanner->LoadBanner(BNRInstance::Instance()->Get(), BNRInstance::Instance()->GetSize());
|
|
|
|
if (Settings.gamesoundvolume != 0)
|
|
{
|
|
if( (BNRInstance::Instance()->Get() != NULL)
|
|
&& gameBanner->LoadSound(BNRInstance::Instance()->Get(), BNRInstance::Instance()->GetSize())
|
|
&& gameBanner->getSound())
|
|
{
|
|
gameSound = new GuiSound(gameBanner->getSound(), gameBanner->getSoundSize(), Settings.gamesoundvolume);
|
|
}
|
|
else if((header->type == TYPE_GAME_GC_IMG) || (header->type == TYPE_GAME_GC_DISC) || (header->type == TYPE_GAME_GC_EXTRACTED))
|
|
{
|
|
//! on game cube load the default sound
|
|
gameSound = new GuiSound(Resources::GetFile("gc_banner.ogg"), Resources::GetFileSize("gc_banner.ogg"), Settings.gamesoundvolume);
|
|
}
|
|
if(gameSound)
|
|
{
|
|
bgMusic->SetVolume(0);
|
|
if (Settings.gamesound == 2)
|
|
gameSound->SetLoop(1);
|
|
// If the game is changed within window play sound here directly
|
|
if(playsound)
|
|
gameSound->Play();
|
|
}
|
|
}
|
|
|
|
int favoritevar = GameStatistics.GetFavoriteRank(header->id);
|
|
for(int i = 0; i < FAVORITE_STARS; ++i)
|
|
FavoriteBtnImg[i]->SetImage(favoritevar >= i+1 ? imgFavorite : imgNotFavorite);
|
|
|
|
//! Resume all threads
|
|
BannerAsync::ResumeThread();
|
|
ResumeGui();
|
|
}
|
|
|
|
int BannerWindow::Run()
|
|
{
|
|
int choice = -1;
|
|
|
|
while(choice == -1)
|
|
{
|
|
usleep(50000);
|
|
|
|
if (shutdown) //for power button
|
|
Sys_Shutdown();
|
|
else if (reset) //for reset button
|
|
Sys_Reboot();
|
|
|
|
choice = MainLoop();
|
|
}
|
|
|
|
return choice;
|
|
}
|
|
|
|
int BannerWindow::MainLoop()
|
|
{
|
|
if (startBtn->GetState() == STATE_CLICKED)
|
|
{
|
|
// If this function was left then the game start was canceled
|
|
GameWindow::BootGame(dvdheader ? dvdheader : gameList[gameSelected]);
|
|
// If it returns from that function reload the list
|
|
gameList.FilterList();
|
|
startBtn->ResetState();
|
|
}
|
|
|
|
else if (backBtn->GetState() == STATE_CLICKED) //back
|
|
{
|
|
GuiBannerGrid *bannerBrowser = dynamic_cast<GuiBannerGrid *>(browserMenu->GetGameBrowser());
|
|
if(bannerBrowser)
|
|
{
|
|
bannerBrowser->GetIconCoordinates(gameSelected, &AnimPosX, &AnimPosY);
|
|
bannerBrowser->SetPage(gameSelected / 12);
|
|
}
|
|
// activate rendering again
|
|
browserMenu->GetGameBrowser()->SetVisible(true);
|
|
|
|
// finish on going animations first
|
|
while(AnimStep < MaxAnimSteps)
|
|
usleep(1000);
|
|
|
|
// set new animation for zoom out
|
|
AnimZoomIn = false;
|
|
AnimStep = 0;
|
|
|
|
// finish animation
|
|
while(AnimStep < MaxAnimSteps)
|
|
usleep(1000);
|
|
|
|
mainWindow->SetState(STATE_DEFAULT);
|
|
returnVal = 0;
|
|
}
|
|
|
|
else if(settingsBtn->GetState() == STATE_CLICKED) //settings
|
|
{
|
|
this->SetState(STATE_DISABLED);
|
|
|
|
wiilight(0);
|
|
int settret = GameSettingsMenu::Execute(browserMenu, dvdheader ? dvdheader : gameList[gameSelected]);
|
|
|
|
this->SetState(STATE_DEFAULT);
|
|
settingsBtn->ResetState();
|
|
|
|
// Show the window again or return to browser on uninstall
|
|
if (settret == MENU_DISCLIST)
|
|
returnVal = 1;
|
|
}
|
|
|
|
else if (btnRight->GetState() == STATE_CLICKED) //next game
|
|
{
|
|
if(Settings.xflip == XFLIP_YES)
|
|
{
|
|
gameSelected = (gameSelected - 1 + gameList.size()) % gameList.size();
|
|
ChangeGame(true);
|
|
}
|
|
else if(Settings.xflip == XFLIP_SYSMENU)
|
|
{
|
|
gameSelected = (gameSelected + 1) % gameList.size();
|
|
ChangeGame(true);
|
|
}
|
|
else if(Settings.xflip == XFLIP_WTF)
|
|
{
|
|
gameSelected = (gameSelected - 1 + gameList.size()) % gameList.size();
|
|
ChangeGame(true);
|
|
}
|
|
else
|
|
{
|
|
gameSelected = (gameSelected + 1) % gameList.size();
|
|
ChangeGame(true);
|
|
}
|
|
|
|
btnRight->ResetState();
|
|
}
|
|
|
|
else if (btnLeft->GetState() == STATE_CLICKED) //previous game
|
|
{
|
|
if(Settings.xflip == XFLIP_YES)
|
|
{
|
|
gameSelected = (gameSelected + 1) % gameList.size();
|
|
ChangeGame(true);
|
|
}
|
|
else if(Settings.xflip == XFLIP_SYSMENU)
|
|
{
|
|
gameSelected = (gameSelected - 1 + gameList.size()) % gameList.size();
|
|
ChangeGame(true);
|
|
}
|
|
else if(Settings.xflip == XFLIP_WTF)
|
|
{
|
|
gameSelected = (gameSelected + 1) % gameList.size();
|
|
ChangeGame(true);
|
|
}
|
|
else
|
|
{
|
|
gameSelected = (gameSelected - 1 + gameList.size()) % gameList.size();
|
|
ChangeGame(true);
|
|
}
|
|
|
|
btnLeft->ResetState();
|
|
}
|
|
|
|
if (reducedVol)
|
|
{
|
|
if (gameSound)
|
|
{
|
|
if (Settings.gamesound == 1 && !gameSound->IsPlaying())
|
|
{
|
|
bgMusic->SetVolume(Settings.volume);
|
|
reducedVol = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bgMusic->SetVolume(Settings.volume);
|
|
reducedVol = false;
|
|
}
|
|
}
|
|
|
|
for(int i = 0; i < FAVORITE_STARS; ++i)
|
|
{
|
|
if(FavoriteBtn[i]->GetState() == STATE_CLICKED)
|
|
{
|
|
// This button can only be clicked when this is not a dvd header
|
|
struct discHdr * header = gameList[gameSelected];
|
|
int FavoriteRank = (i+1 == GameStatistics.GetFavoriteRank(header->id)) ? 0 : i+1; // Press the current rank to reset the rank
|
|
|
|
GameStatistics.SetFavoriteRank(header->id, FavoriteRank);
|
|
GameStatistics.Save();
|
|
for(int j = 0; j < FAVORITE_STARS; ++j)
|
|
FavoriteBtnImg[j]->SetImage(FavoriteRank >= j+1 ? imgFavorite : imgNotFavorite);
|
|
|
|
FavoriteBtn[i]->ResetState();
|
|
}
|
|
}
|
|
|
|
return returnVal;
|
|
}
|
|
|
|
void BannerWindow::Animate(void)
|
|
{
|
|
// animation is on going
|
|
if(AnimStep < MaxAnimSteps)
|
|
{
|
|
AnimationRunning = true;
|
|
AnimStep++;
|
|
|
|
// zoom in animation
|
|
if(AnimZoomIn) {
|
|
BGAlpha = std::min(255.f * AnimStep * 2.f / MaxAnimSteps, 255.f);
|
|
if(AnimStep < 0.4f * MaxAnimSteps)
|
|
BannerAlpha = 0;
|
|
else
|
|
BannerAlpha = std::min(255.f * (AnimStep - 0.4f * MaxAnimSteps) / (0.6f * MaxAnimSteps), 255.f);
|
|
}
|
|
// zoom out animation
|
|
else {
|
|
BGAlpha = std::min(255.f * (MaxAnimSteps-AnimStep) * 2.f / MaxAnimSteps, 255.f);
|
|
if((MaxAnimSteps - AnimStep) < 0.4f * MaxAnimSteps)
|
|
BannerAlpha = 0;
|
|
else
|
|
BannerAlpha = std::min(255.f * ((MaxAnimSteps - AnimStep) - 0.4f * MaxAnimSteps) / (0.6f * MaxAnimSteps), 255.f);
|
|
}
|
|
|
|
float curAnimStep = AnimZoomIn ? ((float)(MaxAnimSteps - AnimStep)/(float)MaxAnimSteps) : ((float)AnimStep/(float)MaxAnimSteps);
|
|
|
|
float stepx1 = Settings.AdjustOverscanX - AnimPosX;
|
|
float stepy1 = Settings.AdjustOverscanY - AnimPosY;
|
|
float stepx2 = (screenwidth - 1 - Settings.AdjustOverscanX) - (AnimPosX + fIconWidth);
|
|
float stepy2 = (screenheight - 1 - Settings.AdjustOverscanY) - (AnimPosY + fIconHeight);
|
|
|
|
float top = AnimPosY + stepy1 * curAnimStep;
|
|
float bottom = AnimPosY + fIconHeight + stepy2 * curAnimStep;
|
|
float left = AnimPosX + stepx1 * curAnimStep;
|
|
float right = AnimPosX + fIconWidth + stepx2 * curAnimStep;
|
|
|
|
// set main projection of all GUI stuff if we are using the banner browser
|
|
if(dynamic_cast<GuiBannerGrid *>(browserMenu->GetGameBrowser()) != NULL)
|
|
guOrtho(FSProjection2D, top, bottom, left, right, 0, 10000);
|
|
|
|
float xDiff = 0.5f * Settings.BannerProjectionWidth;
|
|
float yDiff = 0.5f * Settings.BannerProjectionHeight;
|
|
|
|
// this just looks better for banner/icon ratio
|
|
float iconWidth = fIconWidth - 20;
|
|
float iconHeight = fIconHeight - 20;
|
|
|
|
f32 ratioX = xDiff * 2.f / iconWidth;
|
|
f32 ratioY = yDiff * 2.f / iconHeight;
|
|
stepx1 = ((ScreenProps.x * 0.5f - xDiff) - (AnimPosX + 0.5f * fIconWidth - 0.5f * iconWidth)) * ratioX;
|
|
stepx2 = ((ScreenProps.x * 0.5f + xDiff) - (AnimPosX + 0.5f * fIconWidth + 0.5f * iconWidth)) * ratioX;
|
|
stepy1 = ((ScreenProps.y * 0.5f - yDiff) - (AnimPosY + 0.5f * fIconHeight - 0.5f * iconHeight)) * ratioY;
|
|
stepy2 = ((ScreenProps.y * 0.5f + yDiff) - (AnimPosY + 0.5f * fIconHeight + 0.5f * iconHeight)) * ratioY;
|
|
|
|
//! This works good for banners
|
|
top = (ScreenProps.y * 0.5f - yDiff) + stepy1 * curAnimStep;
|
|
bottom = (ScreenProps.y * 0.5f + yDiff) + stepy2 * curAnimStep;
|
|
left = (ScreenProps.x * 0.5f - xDiff) + stepx1 * curAnimStep;
|
|
right = (ScreenProps.x * 0.5f + xDiff) + stepx2 * curAnimStep;
|
|
|
|
// set banner projection
|
|
guOrtho(projection,top, bottom, left, right,-100,10000);
|
|
}
|
|
// last animation step
|
|
else if(AnimationRunning)
|
|
{
|
|
// set back original projection and stop animation/render of the browser (save some CPU ;P)
|
|
memcpy(&FSProjection2D, &originalProjection, sizeof(Mtx44));
|
|
browserMenu->GetGameBrowser()->SetVisible(false);
|
|
AnimationRunning = false;
|
|
}
|
|
}
|
|
|
|
void BannerWindow::Draw(void)
|
|
{
|
|
bool btnAGrow = (settingsBtn->GetState() == STATE_SELECTED || backBtn->GetState() == STATE_SELECTED);
|
|
bannerFrame.SetButtonAGrow(btnAGrow);
|
|
bannerFrame.SetButtonBGrow(startBtn->GetState() == STATE_SELECTED);
|
|
|
|
//! Start playing banner sound after last animation frame if animation after zoom is enabled
|
|
//! or on first frame if during zoom is enable
|
|
if( AnimZoomIn && gameSound && (((Settings.BannerAnimStart == BANNER_START_ON_ZOOM) && AnimStep == 0)
|
|
|| ((Settings.BannerAnimStart == BANNER_START_AFTER_ZOOM) && ((AnimStep + 1) == MaxAnimSteps))))
|
|
{
|
|
reducedVol = true;
|
|
gameSound->Play();
|
|
}
|
|
|
|
// Run window animation
|
|
Animate();
|
|
|
|
// draw a black background image first
|
|
Menu_DrawRectangle(0.0f, 0.0f, ScreenProps.x, ScreenProps.y, (GXColor) {0, 0, 0, BGAlpha}, true);
|
|
|
|
// no banner alpha means its the start of the animation
|
|
if(BannerAlpha == 0)
|
|
return;
|
|
|
|
// cut the unneeded crap
|
|
Mtx mv1, mv2, mv3;
|
|
guMtxIdentity (mv2);
|
|
guMtxIdentity (mv3);
|
|
guMtxScaleApply(modelview,mv1, 1.f, -1.f, 1.f);
|
|
guMtxTransApply(mv1,mv1, 0.5f * ScreenProps.x, 0.5f * ScreenProps.y, 0.f);
|
|
guMtxTransApply(mv2,mv2, -0.5f * fBannerWidth, 0.5f * fBannerHeight, 0.f);
|
|
guMtxTransApply(mv3,mv3, 0.5f * fBannerWidth, -0.5f * fBannerHeight, 0.f);
|
|
guMtxConcat (mv1, mv2, mv2);
|
|
guMtxConcat (mv1, mv3, mv3);
|
|
|
|
f32 viewportv[6];
|
|
f32 projectionv[7];
|
|
|
|
GX_GetViewportv(viewportv, vmode);
|
|
GX_GetProjectionv(projectionv, projection, GX_ORTHOGRAPHIC);
|
|
|
|
guVector vecTL;
|
|
guVector vecBR;
|
|
GX_Project(0.0f, 0.0f, 0.0f, mv2, projectionv, viewportv, &vecTL.x, &vecTL.y, &vecTL.z);
|
|
GX_Project(0.0f, 0.0f, 0.0f, mv3, projectionv, viewportv, &vecBR.x, &vecBR.y, &vecBR.z);
|
|
|
|
// round up scissor box offset and round down the size
|
|
u32 scissorX = (u32)(0.5f + std::max(vecTL.x, 0.0f));
|
|
u32 scissorY = (u32)(0.5f + std::max(vecTL.y, 0.0f));
|
|
u32 scissorW = (u32)std::max(vecBR.x - vecTL.x, 0.0f);
|
|
u32 scissorH = (u32)std::max(vecBR.y - vecTL.y, 0.0f);
|
|
|
|
GX_SetScissor( scissorX, scissorY, scissorW, scissorH );
|
|
|
|
// load projection matrix
|
|
GX_LoadProjectionMtx(projection, GX_ORTHOGRAPHIC);
|
|
|
|
if(gameBanner->getBanner())
|
|
{
|
|
gameBanner->getBanner()->Render(modelview, ScreenProps, Settings.widescreen, BannerAlpha);
|
|
|
|
// advance only when animation isnt running on certain options
|
|
if(Settings.BannerAnimStart != BANNER_START_AFTER_ZOOM || !AnimationRunning)
|
|
{
|
|
gameBanner->getBanner()->AdvanceFrame();
|
|
|
|
// skip every 6th frame on PAL50 since all banners are 60 Hz
|
|
if(Settings.PAL50 && (frameCount % 6 == 0)) {
|
|
gameBanner->getBanner()->AdvanceFrame();
|
|
}
|
|
}
|
|
}
|
|
|
|
// render big frame and animate button over effects
|
|
bannerFrame.Render(modelview, ScreenProps, Settings.widescreen, BannerAlpha);
|
|
bannerFrame.AdvanceFrame();
|
|
|
|
// Setup GX
|
|
ReSetup_GX();
|
|
|
|
if(AnimationRunning) {
|
|
// remove scissors again as we draw the background layout too
|
|
GX_SetScissor(0, 0, vmode->fbWidth, vmode->efbHeight);
|
|
|
|
// only render gui stuff when animation is done
|
|
return;
|
|
}
|
|
|
|
GuiWindow::Draw();
|
|
}
|