mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-12-25 03:11:58 +01:00
b2fdc18998
-added alpha channel handling to covers up to 640x480 (homebrew icons should look fine now)
259 lines
7.5 KiB
C++
259 lines
7.5 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 "gx_addons.h"
|
|
#include "gecko/gecko.h"
|
|
#include "loader/utils.h"
|
|
#include "menu/menu.hpp"
|
|
|
|
BannerWindow m_banner;
|
|
|
|
extern const u8 custombanner_bin[];
|
|
extern const u32 custombanner_bin_size;
|
|
|
|
void BannerWindow::Init(u8 *font1, u8 *font2)
|
|
{
|
|
MaxAnimSteps = 30;
|
|
returnVal = -1;
|
|
reducedVol = false;
|
|
ScreenProps.x = 620; //620
|
|
ScreenProps.y = 400; //400
|
|
sysFont1 = font1;
|
|
sysFont2 = font2;
|
|
ShowBanner = true;
|
|
|
|
guMtxIdentity(modelview);
|
|
guMtxTransApply(modelview, modelview, (!m_vid.wide() || m_vid.vid_50hz()) ? 0.0f : 2.0f, m_vid.vid_50hz() ? -1.0f : 0.0f, 0.0F);
|
|
|
|
AnimPosX = 0.5f * (ScreenProps.x - fIconWidth);
|
|
AnimPosY = 0.5f * (ScreenProps.y - fIconHeight);
|
|
AnimationRunning = false;
|
|
Brightness = 0.f;
|
|
|
|
// this just looks better for banner/icon ratio
|
|
xDiff = 0.5f * (m_vid.wide() ? (m_vid.vid_50hz() ? 616 : 620.0f) : 608.0f);
|
|
yDiff = 0.5f * (m_vid.vid_50hz() ? 448.0f : 470.0f);
|
|
|
|
iconWidth = fIconWidth - 20;
|
|
iconHeight = fIconHeight - 20;
|
|
|
|
ratioX = xDiff * 2.f / iconWidth;
|
|
ratioY = yDiff * 2.f / iconHeight;
|
|
|
|
stepx1 = ((ScreenProps.x * 0.1f - xDiff) - (AnimPosX + 0.5f * fIconWidth - 0.5f * iconWidth)) * ratioX;
|
|
stepx2 = ((ScreenProps.x * 0.1f + xDiff) - (AnimPosX + 0.5f * fIconWidth + 0.5f * iconWidth)) * ratioX;
|
|
stepy1 = ((ScreenProps.y * 0.9f - yDiff) - (AnimPosY + 0.5f * fIconHeight - 0.5f * iconHeight)) * ratioY;
|
|
stepy2 = ((ScreenProps.y * 0.9f + yDiff) - (AnimPosY + 0.5f * fIconHeight + 0.5f * iconHeight)) * ratioY;
|
|
|
|
gameBanner.Clear();
|
|
if(!FontLoaded)
|
|
{
|
|
gameBanner.LoadFont(sysFont1, sysFont2);
|
|
FontLoaded = true;
|
|
}
|
|
}
|
|
|
|
void BannerWindow::LoadBanner(u8 *font1, u8 *font2)
|
|
{
|
|
changing = true;
|
|
Init(font1, font2);
|
|
gameBanner.LoadBanner();
|
|
gameSelected = 1;
|
|
changing = false;
|
|
ShowBanner = true;
|
|
}
|
|
|
|
void BannerWindow::DeleteBanner(bool gamechange)
|
|
{
|
|
if(!gamechange)
|
|
gameSelected = 0;
|
|
gameBanner.Clear();
|
|
}
|
|
|
|
BannerWindow::BannerWindow()
|
|
{
|
|
ShowBanner = true;
|
|
FontLoaded = false;
|
|
changing = false;
|
|
AnimZoom = false;
|
|
AnimStep = 20;
|
|
gameSelected = 0;
|
|
}
|
|
|
|
void BannerWindow::LoadBannerBin(u8 *bnr, u32 bnr_size, u8 *font1, u8 *font2)
|
|
{
|
|
changing = true;
|
|
Init(font1, font2);
|
|
gameBanner.LoadBannerBin(bnr, bnr_size);
|
|
gameSelected = 1;
|
|
changing = false;
|
|
ShowBanner = true;
|
|
}
|
|
|
|
void BannerWindow::CreateGCBanner(u8 *bnr, u8 *font1, u8 *font2, const wchar_t *title)
|
|
{
|
|
GC_OpeningBnr *openingBnr = (GC_OpeningBnr *)bnr;
|
|
LoadBannerBin((u8*)custombanner_bin, (u32)custombanner_bin_size, font1, font2);
|
|
gameBanner.SetBannerTexture("GCIcon.tpl", openingBnr->tpl_data, 96, 32, GX_TF_RGB5A3);
|
|
gameBanner.SetBannerText("T_GameTitle", title);
|
|
}
|
|
|
|
bool BannerWindow::ToogleZoom(void)
|
|
{
|
|
if(AnimZoom)
|
|
{
|
|
AnimStep = 30;
|
|
AnimZoom = false;
|
|
}
|
|
else
|
|
{
|
|
AnimStep = 20;
|
|
AnimZoom = true;
|
|
}
|
|
return AnimZoom;
|
|
}
|
|
|
|
void BannerWindow::Animate(void)
|
|
{
|
|
// animation is on going
|
|
if(AnimStep <= MaxAnimSteps)
|
|
{
|
|
AnimationRunning = true;
|
|
if(AnimZoom && AnimStep < MaxAnimSteps)
|
|
AnimStep++;
|
|
else if(!AnimZoom && AnimStep > 20)
|
|
AnimStep--;
|
|
float curAnimStep = ((float)(MaxAnimSteps - AnimStep)/(float)MaxAnimSteps);
|
|
|
|
//! This works good for banners
|
|
float top = (ScreenProps.y * 0.5f - yDiff) + stepy1 * curAnimStep;
|
|
float bottom = (ScreenProps.y * 0.5f + yDiff) + stepy2 * curAnimStep;
|
|
float left = (ScreenProps.x * 0.5f - xDiff) + stepx1 * curAnimStep;
|
|
float 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)
|
|
AnimationRunning = false;
|
|
}
|
|
|
|
void BannerWindow::Draw(void)
|
|
{
|
|
if(!ShowBanner)
|
|
return;
|
|
|
|
// draw a black background image first
|
|
if(AnimStep >= MaxAnimSteps)
|
|
DrawRectangle(0.0f, 0.0f, m_vid.width(), m_vid.height(), (GXColor) {0, 0, 0, 255.f});
|
|
|
|
if(changing)
|
|
return;
|
|
|
|
// Run window animation
|
|
Animate();
|
|
|
|
// 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 + 104.f, 0.f);
|
|
guMtxConcat(mv1, mv2, mv2);
|
|
guMtxConcat(mv1, mv3, mv3);
|
|
|
|
f32 viewportv[6];
|
|
f32 projectionv[7];
|
|
|
|
GX_GetViewportv(viewportv, m_vid.vid_mode());
|
|
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, m_vid.wide(), 255.f);
|
|
gameBanner.getBanner()->AdvanceFrame();
|
|
}
|
|
|
|
// Setup GX
|
|
ReSetup_GX();
|
|
GX_SetScissor(0, 0, m_vid.width(), m_vid.height());
|
|
|
|
// Clear and back to previous projection
|
|
m_vid.setup2DProjection();
|
|
|
|
// If wanted
|
|
if(Brightness > 1.f)
|
|
DrawRectangle(0.0f, 0.0f, m_vid.width(), m_vid.height(), (GXColor) {0, 0, 0, Brightness});
|
|
}
|
|
|
|
void BannerWindow::ToogleGameSettings()
|
|
{
|
|
ToogleZoom();
|
|
Brightness = (Brightness > 1.f ? 0.f : 200.f);
|
|
}
|
|
|
|
void BannerWindow::ReSetup_GX(void)
|
|
{
|
|
// channel control
|
|
GX_SetNumChans(1);
|
|
GX_SetChanCtrl(GX_COLOR0A0,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
|
|
|
|
// texture gen.
|
|
GX_SetNumTexGens(1);
|
|
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
|
|
// texture environment
|
|
GX_SetNumTevStages(1);
|
|
GX_SetNumIndStages(0);
|
|
for(u8 i = 0; i < m_vid.getAA(); i++)
|
|
{
|
|
GX_SetTevOp(i, GX_MODULATE);
|
|
GX_SetTevOrder(i, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
|
GX_SetTevSwapMode(i, GX_TEV_SWAP0, GX_TEV_SWAP0);
|
|
GX_SetTevKColorSel(i, GX_TEV_KCSEL_1_4);
|
|
GX_SetTevKAlphaSel(i, GX_TEV_KASEL_1);
|
|
GX_SetTevDirect(i);
|
|
}
|
|
// swap table
|
|
GX_SetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
|
|
GX_SetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA);
|
|
GX_SetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA);
|
|
GX_SetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA);
|
|
// alpha compare and blend mode
|
|
GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
|
|
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
|
|
}
|