usbloadergx/source/prompts/BannerWindow.cpp
wiidev 6d240872bb Display banners correctly on Korean consoles
This is a workaround. Ideally a lightweight Korean banner font should be loaded.
2021-08-01 18:00:20 +01:00

806 lines
23 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/GameTitles.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);
if (strcmp(Settings.db_language, "KO") == 0)
{
settingsBtnTxt = new GuiText(tr("Settings"), 35, thColor("r=0 g=0 b=0 a=255 - game window size text color"));
settingsBtn->SetPosition(Settings.widescreen ? -113 : -131, 161);
settingsBtn->SetLabel(settingsBtnTxt);
}
startBtn = new GuiButton(215, 75);
startBtn->SetAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
startBtn->SetSoundOver(btnSoundOver);
startBtn->SetSoundClick(btnSoundClick2);
startBtn->SetPosition(110, 175);
startBtn->SetTrigger(trigA);
if (strcmp(Settings.db_language, "KO") == 0)
{
startBtnTxt = new GuiText(tr("Start"), 35, thColor("r=0 g=0 b=0 a=255 - game window size text color"));
startBtn->SetPosition(Settings.widescreen ? 114 : 132, 161);
startBtn->SetLabel(startBtnTxt);
}
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);
if (strcmp(Settings.db_language, "KO") == 0)
{
backBtnTxt = new GuiText(tr("Back"), 35, thColor("r=0 g=0 b=0 a=255 - game window size text color"));
backBtn->SetLabel(backBtnTxt);
}
// 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);
}
if (strcmp(Settings.db_language, "KO") == 0)
{
bannerFrame.SetButtonAText(" ");
bannerFrame.SetButtonBText(" ");
}
else
bannerFrame.SetButtonBText(tr("Start"));
//check if unlocked
if (Settings.godmode || !(Settings.ParentalBlocks & BLOCK_GAME_SETTINGS))
{
if (strcmp(Settings.db_language, "KO") != 0)
bannerFrame.SetButtonAText(tr("Settings"));
Append(settingsBtn);
if(Settings.bannerFavIcon != BANNER_FAVICON_OFF)
for(int i = 0; i < FAVORITE_STARS; ++i)
Append(FavoriteBtn[i]);
}
else
{
if (strcmp(Settings.db_language, "KO") == 0)
{
backBtn->SetPosition(Settings.widescreen ? -113 : -131, 161);
}
else
{
bannerFrame.SetButtonAText(tr("Back"));
backBtn->SetPosition(-120, 175);
}
}
Append(startBtn); //! Appending the disc on top of all
if (strcmp(Settings.db_language, "KO") == 0)
{
titleName = new GuiText((char *) NULL, 29, (GXColor) {255, 255, 255, 255});
titleName->SetFontSize(29);
titleName->SetScale(0.8f);
}
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;
if (strcmp(Settings.db_language, "KO") == 0)
{
delete startBtnTxt;
delete backBtnTxt;
delete settingsBtnTxt;
delete titleName;
}
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;
if (strcmp(Settings.db_language, "KO") == 0)
{
Remove(titleName);
titleName->SetText(GameTitles.GetTitle(header));
}
// 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);
if (strcmp(Settings.db_language, "KO") == 0)
{
titleName->SetAlignment(ALIGN_CENTER, ALIGN_BOTTOM);
titleName->SetPosition(0, -170);
Append(titleName);
}
}
}
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);
if (strcmp(Settings.db_language, "KO") == 0)
{
Pane *yearPane = gameBanner->getBanner()->FindPanePartial("YearLine");
if (yearPane)
yearPane->SetVisible(false);
Pane *playersPane = gameBanner->getBanner()->FindPanePartial("PlayLine");
if (playersPane)
playersPane->SetVisible(false);
Pane *titlePane = gameBanner->getBanner()->FindPanePartial("T_VCTitle");
if (titlePane)
{
titlePane->SetVisible(false);
titleName->SetAlignment(ALIGN_CENTER, ALIGN_BOTTOM);
titleName->SetPosition(0, -170);
Append(titleName);
}
}
//! 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();
}