Implement CCredits, minor text parser fixes

This commit is contained in:
Phillip Stephens 2020-05-03 19:27:48 -07:00
parent 0f92b8d8c5
commit 0c6813d952
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
9 changed files with 321 additions and 13 deletions

View File

@ -125,6 +125,11 @@ struct ITweakGui : ITweak {
virtual float GetHudLightAttMulConstant() const = 0; virtual float GetHudLightAttMulConstant() const = 0;
virtual float GetHudLightAttMulLinear() const = 0; virtual float GetHudLightAttMulLinear() const = 0;
virtual float GetHudLightAttMulQuadratic() const = 0; virtual float GetHudLightAttMulQuadratic() const = 0;
virtual std::string_view GetCreditsTable() const = 0;
virtual std::string_view GetCreditsFont() const =0;
virtual std::string_view GetJapaneseCreditsFont() const=0;
virtual const zeus::CColor& GetCreditsTextFontColor() const=0;
virtual const zeus::CColor& GetCreditsTextBorderColor() const=0;
static float FaceReflectionDistanceDebugValueToActualValue(float v) { return 0.015f * v + 0.2f; } static float FaceReflectionDistanceDebugValueToActualValue(float v) { return 0.015f * v + 0.2f; }
static float FaceReflectionHeightDebugValueToActualValue(float v) { return 0.005f * v - 0.05f; } static float FaceReflectionHeightDebugValueToActualValue(float v) { return 0.005f * v - 0.05f; }

View File

@ -160,9 +160,9 @@ struct CTweakGui final : ITweakGui {
Value<float> x2c0_hudLightAttMulQuadratic; Value<float> x2c0_hudLightAttMulQuadratic;
Value<atUint32> m_scanSpeedsCount; Value<atUint32> m_scanSpeedsCount;
Vector<float, AT_DNA_COUNT(m_scanSpeedsCount)> x2c4_scanSpeeds; Vector<float, AT_DNA_COUNT(m_scanSpeedsCount)> x2c4_scanSpeeds;
String<-1> x2d0_; String<-1> x2d0_creditsTable;
String<-1> x2e0_; String<-1> x2e0_creditsFont;
String<-1> x2f0_; String<-1> x2f0_japaneseCreditsFont;
DNAColor x300_; DNAColor x300_;
DNAColor x304_; DNAColor x304_;
Value<float> x308_; Value<float> x308_;
@ -301,6 +301,11 @@ struct CTweakGui final : ITweakGui {
float GetHudLightAttMulConstant() const override { return x2b8_hudLightAttMulConstant; } float GetHudLightAttMulConstant() const override { return x2b8_hudLightAttMulConstant; }
float GetHudLightAttMulLinear() const override { return x2bc_hudLightAttMulLinear; } float GetHudLightAttMulLinear() const override { return x2bc_hudLightAttMulLinear; }
float GetHudLightAttMulQuadratic() const override { return x2c0_hudLightAttMulQuadratic; } float GetHudLightAttMulQuadratic() const override { return x2c0_hudLightAttMulQuadratic; }
std::string_view GetCreditsTable() const override { return x2d0_creditsTable; }
std::string_view GetCreditsFont() const override { return x2e0_creditsFont; }
std::string_view GetJapaneseCreditsFont() const override { return x2f0_japaneseCreditsFont; }
const zeus::CColor& GetCreditsTextFontColor() const override { return x300_; }
const zeus::CColor& GetCreditsTextBorderColor() const override { return x304_; }
float GetScanSpeed(int idx) const override { float GetScanSpeed(int idx) const override {
if (idx < 0 || size_t(idx) >= x2c4_scanSpeeds.size()) if (idx < 0 || size_t(idx) >= x2c4_scanSpeeds.size())

View File

@ -129,6 +129,17 @@ public:
void SetVerticalJustification(EVerticalJustification j); void SetVerticalJustification(EVerticalJustification j);
void SetImageBaseline(bool b); void SetImageBaseline(bool b);
bool GetIsTextSupportFinishedLoading(); bool GetIsTextSupportFinishedLoading();
float GetCurTimeMod900() const { return x10_curTimeMod900; }
s32 GetExtentX() const { return x34_extentX; }
void SetExtentX(s32 extent) {
x34_extentX = extent;
ClearRenderBuffer();
}
s32 GetExtentY() const { return x38_extentY; }
void SetExtentY(s32 extent) {
x38_extentY = extent;
ClearRenderBuffer();
}
float GetCurTime() const { return x3c_curTime; } float GetCurTime() const { return x3c_curTime; }
void SetCurTime(float t) { x3c_curTime = t; } void SetCurTime(float t) { x3c_curTime = t; }
std::u16string_view GetString() const { return x0_string; } std::u16string_view GetString() const { return x0_string; }

View File

@ -162,7 +162,13 @@ void CLineSpacingInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer*
void CLineSpacingInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); } void CLineSpacingInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); }
void CPopStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { state.PopState(); } void CPopStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const {
const auto& oldFont = state.GetFont();
state.PopState();
if (oldFont.GetObj() != state.GetFont().GetObj()) {
buf->AddFontChange(state.GetFont());
}
}
void CPopStateInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); } void CPopStateInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); }

View File

@ -35,6 +35,7 @@ protected:
public: public:
CSaveableState() : x54_colors(3, zeus::skBlack), x64_colorOverrides(16) {} CSaveableState() : x54_colors(3, zeus::skBlack), x64_colorOverrides(16) {}
const TLockedToken<CRasterFont>& GetFont() const { return x48_font; }
bool IsFinishedLoading() const; bool IsFinishedLoading() const;
}; };

View File

@ -229,7 +229,7 @@ void CTextExecuteBuffer::MoveWordLTR() {
->get()); ->get());
// Dunno what's up with this in the original; seems fine without // Dunno what's up with this in the original; seems fine without
// x0_instList.emplace(xa8_curWordIt, std::make_shared<CWordInstruction>()); x0_instList.emplace(xa8_curWordIt, std::make_shared<CWordInstruction>());
++xa0_curBlock->x34_lineCount; ++xa0_curBlock->x34_lineCount;
} }
@ -263,7 +263,7 @@ void CTextExecuteBuffer::TerminateLine() {
} }
void CTextExecuteBuffer::TerminateLineLTR() { void CTextExecuteBuffer::TerminateLineLTR() {
if (!xa4_curLine->xc_curY /*&& x18_textState.IsFinishedLoading()*/) { if (!xa4_curLine->xc_curY && x18_textState.IsFinishedLoading()) {
xa4_curLine->xc_curY = std::max(xa4_curLine->GetHeight(), x18_textState.x48_font->GetCarriageAdvance()); xa4_curLine->xc_curY = std::max(xa4_curLine->GetHeight(), x18_textState.x48_font->GetCarriageAdvance());
} }
@ -280,7 +280,7 @@ void CTextExecuteBuffer::AddPopState() {
x18_textState = xc4_stateStack.back(); x18_textState = xc4_stateStack.back();
xc4_stateStack.pop_back(); xc4_stateStack.pop_back();
if (!xa4_curLine->x8_curX) { if (xa4_curLine->x8_curX == 0) {
xa4_curLine->x28_just = x18_textState.x80_just; xa4_curLine->x28_just = x18_textState.x80_just;
xa4_curLine->x2c_vjust = x18_textState.x84_vjust; xa4_curLine->x2c_vjust = x18_textState.x84_vjust;
} }

View File

@ -1,17 +1,252 @@
#include "Runtime/MP1/CCredits.hpp" #include "Runtime/MP1/CCredits.hpp"
#include "Runtime/CArchitectureMessage.hpp"
#include "Runtime/CArchitectureQueue.hpp"
#include "Runtime/Graphics/CGraphics.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 metaforce::MP1 {
namespace {
CCredits::CCredits() : CIOWin("Credits") {} 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) { 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; return EMessageReturn::Normal;
} }
void CCredits::Draw() { void CCredits::Draw() {
if (x14_ != 3) {
return;
}
SCOPED_GRAPHICS_DEBUG_GROUP("CCredits::Draw", zeus::skGreen); 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));
x30_text.back().first->SetOutlineColor(g_tweakGui->GetCreditsTextBorderColor());
}
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 - 64);
text->SetExtentY((bounds.second.y - bounds.first.y));
scaleY += (bounds.second.y - bounds.first.y);
}
x4c_ = float(scaleY + g_Viewport.xc_height); // * 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_28_ = 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, 0.f}, {-hPad, -vPad, 0.f}, {hPad, -vPad, 0.f}, {hPad, vPad, 0.f});
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() {
auto region = g_Renderer->SetViewportOrtho(false, -4096, 4096);
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 } // namespace metaforce::MP1

View File

@ -1,15 +1,53 @@
#pragma once #pragma once
#include "Runtime/CIOWin.hpp" #include "Runtime/CIOWin.hpp"
#include "Runtime/CToken.hpp"
#include "Runtime/Audio/CStaticAudioPlayer.hpp"
#include "Runtime/Camera/CCameraFilter.hpp"
namespace metaforce::MP1 { #include "zeus/CVector2i.hpp"
namespace metaforce {
class CGuiTextSupport;
class CStringTable;
class CRasterFont;
class CMoviePlayer;
struct CFinalInput;
namespace MP1 {
class CCredits : public CIOWin { class CCredits : public CIOWin {
u32 x14_ = 0;
TLockedToken<CStringTable> x18_creditsTable;
TLockedToken<CRasterFont> x20_creditsFont;
std::unique_ptr<CMoviePlayer> x28_;
std::unique_ptr<CStaticAudioPlayer> x2c_;
std::vector<std::pair<std::unique_ptr<CGuiTextSupport>, zeus::CVector2i>> x30_text;
int x44_textSupport = 0;
float x48_ = 0.f;
float x4c_ = 0.f;
float x50_ = 8.f;
float x54_;
float x58_ = 0.f;
bool x5c_24_ : 1 = false;
bool x5c_25_ : 1 = false;
bool x5c_26_ : 1 = false;
bool x5c_27_ : 1 = true;
bool x5c_28_ : 1 = false;
void DrawVideo();
void DrawText();
static void DrawText(CGuiTextSupport&, const zeus::CVector3f& translation);
CCameraFilterPassPoly m_videoFilter;
CCameraFilterPassPoly m_textFilter;
public: public:
CCredits(); CCredits();
EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&) override; EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&) override;
bool GetIsContinueDraw() const override { return false; } bool GetIsContinueDraw() const override { return false; }
void Draw() override; void Draw() override;
};
} // namespace metaforce::MP1 EMessageReturn Update(float, CArchitectureQueue& queue);
EMessageReturn ProcessUserInput(const CFinalInput& input);
};
} // namespace MP1
} // namespace metaforce

View File

@ -70,6 +70,9 @@
#include <DataSpec/DNAMP1/SFX/Weapons.h> #include <DataSpec/DNAMP1/SFX/Weapons.h>
#include <DataSpec/DNAMP1/SFX/ZZZ.h> #include <DataSpec/DNAMP1/SFX/ZZZ.h>
#include "Runtime/MP1/CCredits.hpp"
#include <discord_rpc.h> #include <discord_rpc.h>
namespace metaforce::MP1 { namespace metaforce::MP1 {
@ -106,6 +109,9 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi
CStreamAudioManager::SetMusicVolume(0x7f); CStreamAudioManager::SetMusicVolume(0x7f);
m->ResetGameState(); m->ResetGameState();
std::shared_ptr<CIOWin> credits = std::make_shared<CCredits>();
x58_ioWinManager.AddIOWin(credits, 1000, 10000);
/*
if (!g_tweakGame->GetSplashScreensDisabled()) { if (!g_tweakGame->GetSplashScreensDisabled()) {
std::shared_ptr<CIOWin> splash = std::make_shared<CSplashScreen>(CSplashScreen::ESplashScreen::Nintendo); std::shared_ptr<CIOWin> splash = std::make_shared<CSplashScreen>(CSplashScreen::ESplashScreen::Nintendo);
x58_ioWinManager.AddIOWin(splash, 1000, 10000); x58_ioWinManager.AddIOWin(splash, 1000, 10000);
@ -125,6 +131,7 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi
g_GuiSys = &x44_guiSys; g_GuiSys = &x44_guiSys;
g_GameState->GameOptions().EnsureSettings(); g_GameState->GameOptions().EnsureSettings();
*/
} }
void CGameArchitectureSupport::UpdateTicks(float dt) { void CGameArchitectureSupport::UpdateTicks(float dt) {