/**************************************************************************** * 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 . ****************************************************************************/ #include #include "BannerWindow.hpp" #include "gx_addons.h" #include "gecko/gecko.hpp" #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; // 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::ToggleZoom(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, 0xFF}); 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 == 200) DrawRectangle(0.0f, 0.0f, m_vid.width(), m_vid.height(), (GXColor) {0, 0, 0, Brightness}); } void BannerWindow::ToggleGameSettings() { ToggleZoom(); Brightness = (Brightness == 200 ? 0 : 200); } 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); }