mirror of https://github.com/AxioDL/metaforce.git
Implement CCredits, minor text parser fixes
This commit is contained in:
parent
0f92b8d8c5
commit
0c6813d952
|
@ -125,6 +125,11 @@ struct ITweakGui : ITweak {
|
|||
virtual float GetHudLightAttMulConstant() const = 0;
|
||||
virtual float GetHudLightAttMulLinear() 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 FaceReflectionHeightDebugValueToActualValue(float v) { return 0.005f * v - 0.05f; }
|
||||
|
|
|
@ -160,9 +160,9 @@ struct CTweakGui final : ITweakGui {
|
|||
Value<float> x2c0_hudLightAttMulQuadratic;
|
||||
Value<atUint32> m_scanSpeedsCount;
|
||||
Vector<float, AT_DNA_COUNT(m_scanSpeedsCount)> x2c4_scanSpeeds;
|
||||
String<-1> x2d0_;
|
||||
String<-1> x2e0_;
|
||||
String<-1> x2f0_;
|
||||
String<-1> x2d0_creditsTable;
|
||||
String<-1> x2e0_creditsFont;
|
||||
String<-1> x2f0_japaneseCreditsFont;
|
||||
DNAColor x300_;
|
||||
DNAColor x304_;
|
||||
Value<float> x308_;
|
||||
|
@ -301,6 +301,11 @@ struct CTweakGui final : ITweakGui {
|
|||
float GetHudLightAttMulConstant() const override { return x2b8_hudLightAttMulConstant; }
|
||||
float GetHudLightAttMulLinear() const override { return x2bc_hudLightAttMulLinear; }
|
||||
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 {
|
||||
if (idx < 0 || size_t(idx) >= x2c4_scanSpeeds.size())
|
||||
|
|
|
@ -129,6 +129,17 @@ public:
|
|||
void SetVerticalJustification(EVerticalJustification j);
|
||||
void SetImageBaseline(bool b);
|
||||
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; }
|
||||
void SetCurTime(float t) { x3c_curTime = t; }
|
||||
std::u16string_view GetString() const { return x0_string; }
|
||||
|
|
|
@ -162,7 +162,13 @@ void CLineSpacingInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer*
|
|||
|
||||
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); }
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ protected:
|
|||
|
||||
public:
|
||||
CSaveableState() : x54_colors(3, zeus::skBlack), x64_colorOverrides(16) {}
|
||||
const TLockedToken<CRasterFont>& GetFont() const { return x48_font; }
|
||||
|
||||
bool IsFinishedLoading() const;
|
||||
};
|
||||
|
|
|
@ -229,7 +229,7 @@ void CTextExecuteBuffer::MoveWordLTR() {
|
|||
->get());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ void CTextExecuteBuffer::TerminateLine() {
|
|||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -280,7 +280,7 @@ void CTextExecuteBuffer::AddPopState() {
|
|||
x18_textState = xc4_stateStack.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->x2c_vjust = x18_textState.x84_vjust;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,252 @@
|
|||
#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 {
|
||||
|
||||
CCredits::CCredits() : CIOWin("Credits") {}
|
||||
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));
|
||||
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
|
||||
|
|
|
@ -1,15 +1,53 @@
|
|||
#pragma once
|
||||
|
||||
#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 {
|
||||
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:
|
||||
CCredits();
|
||||
EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&) override;
|
||||
bool GetIsContinueDraw() const override { return false; }
|
||||
void Draw() override;
|
||||
};
|
||||
|
||||
} // namespace metaforce::MP1
|
||||
EMessageReturn Update(float, CArchitectureQueue& queue);
|
||||
EMessageReturn ProcessUserInput(const CFinalInput& input);
|
||||
};
|
||||
} // namespace MP1
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -70,6 +70,9 @@
|
|||
#include <DataSpec/DNAMP1/SFX/Weapons.h>
|
||||
#include <DataSpec/DNAMP1/SFX/ZZZ.h>
|
||||
|
||||
|
||||
#include "Runtime/MP1/CCredits.hpp"
|
||||
|
||||
#include <discord_rpc.h>
|
||||
|
||||
namespace metaforce::MP1 {
|
||||
|
@ -106,6 +109,9 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi
|
|||
CStreamAudioManager::SetMusicVolume(0x7f);
|
||||
m->ResetGameState();
|
||||
|
||||
std::shared_ptr<CIOWin> credits = std::make_shared<CCredits>();
|
||||
x58_ioWinManager.AddIOWin(credits, 1000, 10000);
|
||||
/*
|
||||
if (!g_tweakGame->GetSplashScreensDisabled()) {
|
||||
std::shared_ptr<CIOWin> splash = std::make_shared<CSplashScreen>(CSplashScreen::ESplashScreen::Nintendo);
|
||||
x58_ioWinManager.AddIOWin(splash, 1000, 10000);
|
||||
|
@ -125,6 +131,7 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi
|
|||
|
||||
g_GuiSys = &x44_guiSys;
|
||||
g_GameState->GameOptions().EnsureSettings();
|
||||
*/
|
||||
}
|
||||
|
||||
void CGameArchitectureSupport::UpdateTicks(float dt) {
|
||||
|
|
Loading…
Reference in New Issue