mirror of https://github.com/AxioDL/metaforce.git
257 lines
8.6 KiB
C++
257 lines
8.6 KiB
C++
#include "Runtime/MP1/CCredits.hpp"
|
|
#include "Runtime/CArchitectureMessage.hpp"
|
|
#include "Runtime/CArchitectureQueue.hpp"
|
|
#include "Runtime/Graphics/CGraphics.hpp"
|
|
#include "Runtime/Graphics/CMoviePlayer.hpp"
|
|
#include "Runtime/GuiSys/CRasterFont.hpp"
|
|
#include "Runtime/GuiSys/CStringTable.hpp"
|
|
#include "Runtime/GuiSys/CGuiTextSupport.hpp"
|
|
#include "Runtime/Input/CFinalInput.hpp"
|
|
#include "Runtime/MP1/CPlayMovie.hpp"
|
|
#include "Runtime/GameGlobalObjects.hpp"
|
|
#include "Runtime/CSimplePool.hpp"
|
|
#include "Runtime/Graphics/CBooRenderer.hpp"
|
|
|
|
namespace metaforce::MP1 {
|
|
namespace {
|
|
logvisor::Module Log("CCredits");
|
|
}
|
|
CCredits::CCredits()
|
|
: CIOWin("Credits")
|
|
, x18_creditsTable(g_SimplePool->GetObj(g_tweakGui->GetCreditsTable()))
|
|
, x20_creditsFont(g_SimplePool->GetObj(g_tweakGui->GetJapaneseCreditsFont()))
|
|
, x54_(g_tweakGui->x30c_) {
|
|
x18_creditsTable.Lock();
|
|
x20_creditsFont.Lock();
|
|
}
|
|
|
|
CIOWin::EMessageReturn CCredits::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) {
|
|
switch (msg.GetType()) {
|
|
case EArchMsgType::UserInput: {
|
|
return ProcessUserInput(MakeMsg::GetParmUserInput(msg).x4_parm);
|
|
break;
|
|
case EArchMsgType::TimerTick: {
|
|
return Update(MakeMsg::GetParmTimerTick(msg).x4_parm, queue);
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return EMessageReturn::Normal;
|
|
}
|
|
|
|
void CCredits::Draw() {
|
|
if (x14_ != 3) {
|
|
return;
|
|
}
|
|
SCOPED_GRAPHICS_DEBUG_GROUP("CCredits::Draw", zeus::skGreen);
|
|
DrawVideo();
|
|
DrawText();
|
|
}
|
|
|
|
CIOWin::EMessageReturn CCredits::Update(float dt, CArchitectureQueue& queue) {
|
|
switch (x14_) {
|
|
case 0: {
|
|
if (!x18_creditsTable || !x20_creditsFont) {
|
|
return EMessageReturn::Exit;
|
|
}
|
|
if (x30_text.empty()) {
|
|
for (size_t i = 0; i < x18_creditsTable->GetStringCount(); ++i) {
|
|
x30_text.emplace_back(std::make_unique<CGuiTextSupport>(
|
|
g_ResFactory->GetResourceIdByName(g_tweakGui->GetCreditsFont())->id,
|
|
CGuiTextProperties(true, true, EJustification::Center, EVerticalJustification::Top),
|
|
g_tweakGui->GetCreditsTextFontColor(), g_tweakGui->GetCreditsTextBorderColor(),
|
|
zeus::skWhite, g_Viewport.x8_width - 64, 0, g_SimplePool,
|
|
CGuiWidget::EGuiModelDrawFlags::Alpha),
|
|
zeus::CVector2i(0, 0));
|
|
x30_text.back().first->SetText(x18_creditsTable->GetString(i));
|
|
}
|
|
|
|
// auto tmp = std::make_pair(std::make_unique<CGuiTextSupport>(
|
|
// g_ResFactory->GetResourceIdByName(g_tweakGui->GetCreditsFont())->id,
|
|
// CGuiTextProperties(true, true, EJustification::Center,
|
|
// EVerticalJustification::Top), g_tweakGui->GetCreditsTextFontColor(),
|
|
// g_tweakGui->GetCreditsTextBorderColor(), zeus::skWhite, g_Viewport.x8_width
|
|
// - 64, 0, g_SimplePool, CGuiWidget::EGuiModelDrawFlags::Alpha),
|
|
// zeus::CVector2i(0, 0));
|
|
// tmp.first->SetText(
|
|
// "\n&push;&font=C29C51F1;&main-color=#89D6FF;URDE DEVELOPMENT TEAM&pop;\n"
|
|
// "&push;&main-color=#89D6FF;LEAD REVERSE ENGINEERING TEAM&pop\n;"
|
|
// "Jack \"Cirrus\" Andersen\n"
|
|
// "Phillip \"Antidote\" Stephens\n"
|
|
// "Luke \"encounter\" Street\n\n"
|
|
// "&push;&main-color=#89D6FF;C++ COMPLIANCE & CLEANUP&pop;\n"
|
|
// "Lioncache\n");
|
|
// x30_text.insert(x30_text.end() - 1, std::move(tmp));
|
|
// x30_text.back().first->SetOutlineColor(g_tweakGui->GetCreditsTextBorderColor());
|
|
}
|
|
|
|
for (const auto& [text, offset] : x30_text) {
|
|
if (!text->GetIsTextSupportFinishedLoading()) {
|
|
return EMessageReturn::Exit;
|
|
}
|
|
}
|
|
|
|
int scaleY = 0;
|
|
for (auto& [text, offset] : x30_text) {
|
|
auto bounds = text->GetBounds();
|
|
offset.y = (bounds.second.y - bounds.first.y);
|
|
offset.x = scaleY;
|
|
text->SetExtentX(g_Viewport.x8_width - 1280);
|
|
text->SetExtentY((bounds.second.y - bounds.first.y));
|
|
scaleY += (bounds.second.y - bounds.first.y);
|
|
}
|
|
|
|
x4c_ = float(scaleY + g_Viewport.xc_height - 896); // * 0.5f;
|
|
const float divVal = std::max(g_tweakGui->x310_, g_tweakGui->x30c_);
|
|
x50_ = x4c_ / (g_tweakGui->x308_ - divVal);
|
|
x14_ = 1;
|
|
break;
|
|
}
|
|
case 1: {
|
|
if (!x28_) {
|
|
x28_ = std::make_unique<CMoviePlayer>("Video/creditBG.thp", 0.f, true, true);
|
|
}
|
|
x14_ = 2;
|
|
break;
|
|
}
|
|
case 2: {
|
|
if (!x2c_) {
|
|
x2c_ = std::make_unique<CStaticAudioPlayer>("Audio/ending3.rsf", 0, 0x5d7c00);
|
|
}
|
|
if (!x2c_->IsReady()) {
|
|
return EMessageReturn::Exit;
|
|
}
|
|
x2c_->SetVolume(1.f);
|
|
x2c_->StartMixing();
|
|
x14_ = 3;
|
|
}
|
|
[[fallthrough]];
|
|
case 3: {
|
|
m_videoFilter.Update(dt);
|
|
m_textFilter.Update(dt);
|
|
// if (!x28_->PumpIndexLoad())
|
|
// break;
|
|
x28_->Update(dt);
|
|
if (x5c_24_) {
|
|
x5c_28_ = true;
|
|
if (x5c_27_) {
|
|
x5c_27_ = false;
|
|
x58_ = g_tweakGui->x310_ - x58_;
|
|
}
|
|
}
|
|
if (x5c_27_ || x5c_28_) {
|
|
x58_ = zeus::clamp(0.f, x58_ + dt, g_tweakGui->x310_);
|
|
if (x58_ == g_tweakGui->x310_) {
|
|
if (x5c_27_) {
|
|
x5c_27_ = false;
|
|
x58_ = 0.f;
|
|
} else if (x5c_28_) {
|
|
x5c_25_ = true;
|
|
}
|
|
}
|
|
|
|
if (x58_ != 0.f && x5c_28_) {
|
|
const float volume = zeus::clamp(0.f, 1.f - x58_ / g_tweakGui->x310_, 1.f);
|
|
x2c_->SetVolume(volume);
|
|
}
|
|
}
|
|
x48_ = std::min(x4c_, (dt * x50_) + x48_);
|
|
|
|
if (x48_ == x4c_ || x5c_24_) {
|
|
x5c_24_ = true;
|
|
x54_ = std::max(0.f, x54_ - dt);
|
|
const float alpha = x54_ / g_tweakGui->x30c_;
|
|
for (const auto& [text, offset] : x30_text) {
|
|
zeus::CColor col = zeus::skWhite;
|
|
col.a() *= alpha;
|
|
text->SetGeometryColor(col);
|
|
}
|
|
if (x54_ <= 0.f) {
|
|
x5c_26_ = true;
|
|
}
|
|
}
|
|
|
|
if (x5c_26_ && x5c_25_) {
|
|
queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11,
|
|
std::make_shared<CPlayMovie>(CPlayMovie::EWhichMovie::AfterCredits)));
|
|
return EMessageReturn::RemoveIOWinAndExit;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return EMessageReturn::Exit;
|
|
}
|
|
|
|
CIOWin::EMessageReturn CCredits::ProcessUserInput(const CFinalInput& input) {
|
|
if (input.DA()) {
|
|
x48_ = zeus::clamp(0.f, x48_ - ((x50_ * input.DeltaTime())), x4c_);
|
|
} else {
|
|
float leftY = input.ALeftY();
|
|
float offset = 0.f;
|
|
if (leftY < 0.f) {
|
|
offset = -leftY;
|
|
leftY = 0.f;
|
|
}
|
|
x48_ = zeus::clamp(0.f, x48_ - (leftY - offset) * 10.f * x50_ * input.DeltaTime(), x4c_);
|
|
}
|
|
return EMessageReturn::Exit;
|
|
}
|
|
void CCredits::DrawVideo() {
|
|
/* Correct movie aspect ratio */
|
|
float hPad, vPad;
|
|
if (g_Viewport.aspect >= 1.78f) {
|
|
hPad = 1.78f / g_Viewport.aspect;
|
|
vPad = 1.78f / 1.33f;
|
|
} else {
|
|
hPad = 1.f;
|
|
vPad = g_Viewport.aspect / 1.33f;
|
|
}
|
|
|
|
if (x28_ && x28_->GetIsFullyCached()) {
|
|
/* Render movie */
|
|
x28_->SetFrame(hPad, vPad);
|
|
x28_->DrawFrame();
|
|
if (x5c_27_ || x5c_28_) {
|
|
float alpha = x58_ / g_tweakGui->x310_;
|
|
if (x5c_27_) {
|
|
alpha = 1.f - alpha;
|
|
}
|
|
|
|
alpha = zeus::clamp(0.f, alpha, 1.f);
|
|
zeus::CColor filterCol = zeus::skBlack;
|
|
filterCol.a() = alpha;
|
|
m_videoFilter.SetFilter(EFilterType::Blend, EFilterShape::Fullscreen, 1.f, filterCol, {});
|
|
m_videoFilter.Draw();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCredits::DrawText() {
|
|
float width = 896.f * g_Viewport.aspect;
|
|
CGraphics::SetOrtho(0.f, width, 896.f, 0.f, -4096.f, 4096.f);
|
|
auto region =
|
|
std::make_pair<zeus::CVector2f, zeus::CVector2f>(zeus::CVector2f{0.f, 0.f}, zeus::CVector2f{width, 896.f});
|
|
CGraphics::SetViewPointMatrix(zeus::CTransform());
|
|
CGraphics::SetModelMatrix(zeus::CTransform::Translate((width - 1280.f) / 2.f, 0.f, 896.f));
|
|
float dVar5 = (x48_ - (region.second.y() - region.first.y()));
|
|
for (const auto& [text, offset] : x30_text) {
|
|
if (offset.y + offset.x >= dVar5 && offset.x <= x48_) {
|
|
DrawText(*text, {0.5f * (region.second.x() - text->GetExtentX()), 0.f, x48_ - offset.x});
|
|
}
|
|
}
|
|
m_textFilter.SetFilter(EFilterType::Multiply, EFilterShape::CinemaBars, 1.f, zeus::skBlack, {});
|
|
m_textFilter.Draw();
|
|
}
|
|
|
|
void CCredits::DrawText(CGuiTextSupport& text, const zeus::CVector3f& translation) {
|
|
// auto region = g_Renderer->SetViewportOrtho(false, -4096, 4096);
|
|
zeus::CTransform xf = zeus::CTransform::Translate(translation);
|
|
g_Renderer->SetModelMatrix(xf);
|
|
text.Render();
|
|
}
|
|
|
|
} // namespace metaforce::MP1
|