2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-05-13 21:51:22 +00:00
metaforce/Runtime/World/CWorldTransManager.cpp
Lioncash 221cc5c6b8 RuntimeCommonB: Normalize cpp file includes
Like the prior changes normalizing the inclusions within headers, this
tackles the cpp files of the RuntimeCommonB target, making these source
files consistent with their headers.
2019-12-22 18:12:04 -05:00

495 lines
19 KiB
C++

#include "Runtime/World/CWorldTransManager.hpp"
#include "Runtime/CGameState.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Audio/CSfxManager.hpp"
#include "Runtime/Camera/CCameraManager.hpp"
#include "Runtime/Character/CActorLights.hpp"
#include "Runtime/Character/CAnimPlaybackParms.hpp"
#include "Runtime/Character/CAssetFactory.hpp"
#include "Runtime/Character/CCharacterFactory.hpp"
#include "Runtime/Character/CSkinRules.hpp"
#include "Runtime/Character/IAnimReader.hpp"
#include "Runtime/Graphics/CBooRenderer.hpp"
#include "Runtime/Graphics/CModel.hpp"
#include "Runtime/GuiSys/CGuiTextSupport.hpp"
#include "Runtime/GuiSys/CStringTable.hpp"
#include <hecl/CVarManager.hpp>
namespace urde {
int CWorldTransManager::GetSuitCharIdx() {
CPlayerState& state = *g_GameState->GetPlayerState();
if (state.IsFusionEnabled()) {
switch (state.x20_currentSuit) {
case CPlayerState::EPlayerSuit::Power:
return 4;
case CPlayerState::EPlayerSuit::Gravity:
return 6;
case CPlayerState::EPlayerSuit::Varia:
return 7;
case CPlayerState::EPlayerSuit::Phazon:
return 8;
default:
break;
}
}
return int(state.x20_currentSuit);
}
CWorldTransManager::SModelDatas::SModelDatas(const CAnimRes& samusRes) : x0_samusRes(samusRes) {
x1a0_lights.reserve(8);
}
void CWorldTransManager::UpdateLights(float dt) {
if (!x4_modelData)
return;
x4_modelData->x1a0_lights.clear();
zeus::CVector3f lightPos(0.f, 10.f, 0.f);
CLight spot = CLight::BuildSpot(lightPos, zeus::skBack, zeus::skWhite, 90.f);
spot.SetAttenuation(1.f, 0.f, 0.f);
CLight s1 = spot;
s1.SetPosition(lightPos + zeus::CVector3f{0.f, 0.f, 2.f * x18_bgOffset - x1c_bgHeight});
float z = 1.f;
float delta = x1c_bgHeight - x18_bgOffset;
if (!x44_26_goingUp && delta < 2.f)
z = delta * 0.5f;
else if (x44_26_goingUp && x18_bgOffset < 2.f)
z = x18_bgOffset * 0.5f;
if (z < 1.f) {
CLight s2 = spot;
float pos = x44_26_goingUp ? x1c_bgHeight : -x1c_bgHeight;
s2.SetPosition(lightPos + zeus::CVector3f{0.f, 0.f, pos});
s2.SetColor(zeus::CColor::lerp(zeus::skBlack, zeus::skWhite, 1.f - z));
x4_modelData->x1a0_lights.push_back(std::move(s2));
s1.SetColor(zeus::CColor::lerp(zeus::skBlack, zeus::skWhite, z));
}
x4_modelData->x1a0_lights.push_back(std::move(s1));
}
void CWorldTransManager::UpdateDisabled(float) {
if (x0_curTime <= 2.f)
return;
x44_24_transFinished = true;
}
void CWorldTransManager::UpdateEnabled(float dt) {
if (x4_modelData && !x4_modelData->x1c_samusModelData.IsNull()) {
if (x44_25_stopSoon && !x4_modelData->x1dc_dissolveStarted && x0_curTime > 2.f) {
x4_modelData->x1dc_dissolveStarted = true;
x4_modelData->x1d0_dissolveStartTime = x0_curTime;
x4_modelData->x1d4_dissolveEndTime = 4.f + x0_curTime - 2.f;
x4_modelData->x1d8_transCompleteTime = 5.f + x0_curTime - 2.f;
}
if (x0_curTime > x4_modelData->x1d8_transCompleteTime && x4_modelData->x1dc_dissolveStarted)
x44_24_transFinished = true;
x4_modelData->x1c_samusModelData.AdvanceAnimationIgnoreParticles(dt, x20_random, true);
x4_modelData->x170_gunXf = x4_modelData->x1c_samusModelData.GetScaledLocatorTransform("GUN_LCTR");
x4_modelData->x1c4_randTimeout -= dt;
if (x4_modelData->x1c4_randTimeout <= 0.f) {
x4_modelData->x1c4_randTimeout = x20_random.Range(0.016666668f, 0.1f);
zeus::CVector2f randVec(x20_random.Range(-0.025f, 0.025f), x20_random.Range(-0.075f, 0.075f));
x4_modelData->x1bc_shakeDelta = (randVec - x4_modelData->x1b4_shakeResult) / x4_modelData->x1c4_randTimeout;
x4_modelData->x1cc_blurDelta =
(x20_random.Range(-2.f, 4.f) - x4_modelData->x1c8_blurResult) / x4_modelData->x1c4_randTimeout;
}
x4_modelData->x1b4_shakeResult += x4_modelData->x1bc_shakeDelta * dt;
x4_modelData->x1c8_blurResult += dt * x4_modelData->x1cc_blurDelta;
}
float delta = dt * 50.f;
if (x44_26_goingUp)
delta = -delta;
x18_bgOffset += delta;
if (x18_bgOffset > x1c_bgHeight)
x18_bgOffset -= x1c_bgHeight;
if (x18_bgOffset < 0.f)
x18_bgOffset += x1c_bgHeight;
UpdateLights(dt);
}
void CWorldTransManager::UpdateText(float dt) {
if (x44_28_textDirty) {
if (xc_strTable.IsLoaded()) {
x8_textData->SetText(xc_strTable->GetString(x40_strIdx));
x3c_sfxInterval = 0.f;
x44_28_textDirty = false;
} else if (x0_curTime >= x38_textStartTime) {
x38_textStartTime += dt;
}
}
if (x0_curTime >= x38_textStartTime) {
x8_textData->Update(dt);
float nextSfxInterval = x3c_sfxInterval + g_tweakGui->GetWorldTransManagerCharsPerSfx();
float printed = x8_textData->GetNumCharsPrinted();
if (printed >= nextSfxInterval) {
x3c_sfxInterval = nextSfxInterval;
CSfxManager::SfxStart(SFXsfx059E, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
}
}
if (x44_25_stopSoon) {
if (x8_textData->GetTotalAnimationTime() + 1.f < x8_textData->GetCurTime()) {
/* Done typing + 1 sec */
if (x0_curTime - x34_stopTime > 1.f)
x44_24_transFinished = true;
} else {
x34_stopTime = x0_curTime;
}
}
}
void CWorldTransManager::Update(float dt) {
x0_curTime += dt;
switch (x30_type) {
case ETransType::Disabled:
UpdateDisabled(dt);
break;
case ETransType::Enabled:
UpdateEnabled(dt);
break;
case ETransType::Text:
UpdateText(dt);
break;
}
}
void CWorldTransManager::DrawPlatformModels(CActorLights* lights) {
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::Lighting;
if (!x4_modelData->x100_bgModelData[0].IsNull()) {
zeus::CTransform xf0 = zeus::CTransform::Translate(0.f, 0.f, -(2.f * x1c_bgHeight - x18_bgOffset));
x4_modelData->x100_bgModelData[0].Render(CModelData::EWhichModel::Normal, xf0, lights, flags);
}
if (!x4_modelData->x100_bgModelData[1].IsNull()) {
zeus::CTransform xf1 = zeus::CTransform::Translate(0.f, 0.f, x18_bgOffset - x1c_bgHeight);
x4_modelData->x100_bgModelData[1].Render(CModelData::EWhichModel::Normal, xf1, lights, flags);
}
if (!x4_modelData->x100_bgModelData[2].IsNull()) {
zeus::CTransform xf2 = zeus::CTransform::Translate(0.f, 0.f, x18_bgOffset);
x4_modelData->x100_bgModelData[2].Render(CModelData::EWhichModel::Normal, xf2, lights, flags);
}
if (!x4_modelData->xb4_platformModelData.IsNull()) {
x4_modelData->xb4_platformModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform(), lights,
flags);
}
}
void CWorldTransManager::DrawAllModels(CActorLights* lights) {
DrawPlatformModels(lights);
if (!x4_modelData->x1c_samusModelData.IsNull()) {
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
x4_modelData->x1c_samusModelData.GetAnimationData()->PreRender();
x4_modelData->x1c_samusModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform(), lights,
flags);
if (!x4_modelData->x68_beamModelData.IsNull()) {
x4_modelData->x68_beamModelData.Render(CModelData::EWhichModel::Normal, x4_modelData->x170_gunXf, lights, flags);
}
}
}
void CWorldTransManager::DrawFirstPass(CActorLights* lights) {
CBooModel::SetReflectionCube(m_reflectionCube[0]);
zeus::CTransform translateXf = zeus::CTransform::Translate(
x4_modelData->x1b4_shakeResult.x(), -3.5f * (1.f - zeus::clamp(0.f, x0_curTime / 10.f, 1.f)) - 3.5f,
x4_modelData->x1b4_shakeResult.y() + 2.f);
zeus::CTransform rotateXf =
zeus::CTransform::RotateZ(zeus::degToRad(zeus::clamp(0.f, x0_curTime / 25.f, 100.f) * 360.f + 180.f - 90.f));
CGraphics::SetViewPointMatrix(rotateXf * translateXf);
DrawAllModels(lights);
m_camblur.draw(x4_modelData->x1c8_blurResult);
}
void CWorldTransManager::DrawSecondPass(CActorLights* lights) {
CBooModel::SetReflectionCube(m_reflectionCube[1]);
const zeus::CVector3f& samusScale = x4_modelData->x0_samusRes.GetScale();
zeus::CTransform translateXf =
zeus::CTransform::Translate(-0.1f * samusScale.x(), -0.5f * samusScale.y(), 1.5f * samusScale.z());
zeus::CTransform rotateXf = zeus::CTransform::RotateZ(zeus::degToRad(
48.f * zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime + 2.f) / 5.f, 1.f) + 180.f - 24.f));
CGraphics::SetViewPointMatrix(rotateXf * translateXf);
DrawAllModels(lights);
}
void CWorldTransManager::DrawEnabled() {
SCOPED_GRAPHICS_DEBUG_GROUP("CWorldTransManager::DrawEnabled", zeus::skPurple);
CActorLights lights(0, zeus::skZero3f, 4, 4, 0, 0, 0, 0.1f);
lights.BuildFakeLightList(x4_modelData->x1a0_lights, zeus::CColor{0.1f, 0.1f, 0.1f, 1.0f});
if (m_reflectionCube[0]) {
SViewport backupVp = g_Viewport;
constexpr float width = CUBEMAP_RES;
CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[0], 0);
g_Renderer->SetViewport(0, 0, width, width);
g_Renderer->SetPerspective(90.f, width, width, 0.2f, 750.f);
if (x0_curTime < x4_modelData->x1d4_dissolveEndTime) {
zeus::CTransform mainCamXf =
zeus::CTransform::RotateZ(zeus::degToRad(zeus::clamp(0.f, x0_curTime / 25.f, 100.f) * 360.f + 180.f - 90.f));
for (int face = 0; face < 6; ++face) {
CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[0], face);
CGraphics::g_BooMainCommandQueue->clearTarget();
zeus::CTransform camXf = zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], zeus::CVector3f(0.f, 0.f, 1.5f));
g_Renderer->SetWorldViewpoint(camXf);
DrawPlatformModels(&lights);
}
CGraphics::g_BooMainCommandQueue->generateMipmaps(m_reflectionCube[0]);
}
if (x0_curTime > x4_modelData->x1d0_dissolveStartTime) {
zeus::CTransform mainCamXf = zeus::CTransform::RotateZ(zeus::degToRad(
48.f * zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime + 2.f) / 5.f, 1.f) + 180.f - 24.f));
for (int face = 0; face < 6; ++face) {
CGraphics::g_BooMainCommandQueue->setRenderTarget(m_reflectionCube[1], face);
CGraphics::g_BooMainCommandQueue->clearTarget();
zeus::CTransform camXf = zeus::CTransform(mainCamXf.basis * CGraphics::skCubeBasisMats[face], zeus::CVector3f(0.f, 0.f, 1.5f));
g_Renderer->SetWorldViewpoint(camXf);
DrawPlatformModels(&lights);
}
CGraphics::g_BooMainCommandQueue->generateMipmaps(m_reflectionCube[1]);
}
CBooRenderer::BindMainDrawTarget();
g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height);
}
float wsAspect = CWideScreenFilter::SetViewportToMatch(1.f);
g_Renderer->SetPerspective(CCameraManager::FirstPersonFOV(), wsAspect, CCameraManager::NearPlane(),
CCameraManager::FarPlane());
g_Renderer->x318_26_requestRGBA6 = true;
if (x0_curTime <= x4_modelData->x1d0_dissolveStartTime)
DrawFirstPass(&lights);
else if (x0_curTime >= x4_modelData->x1d4_dissolveEndTime)
DrawSecondPass(&lights);
else {
float t = zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime) / 2.f, 1.f);
DrawFirstPass(&lights);
SClipScreenRect rect(g_Viewport);
CGraphics::ResolveSpareTexture(rect);
CGraphics::g_BooMainCommandQueue->clearTarget(true, true);
DrawSecondPass(&lights);
m_dissolve.drawCropped(zeus::CColor{1.f, 1.f, 1.f, 1.f - t}, 1.f);
}
CWideScreenFilter::SetViewportToFull();
m_widescreen.draw(zeus::skBlack, 1.f);
float ftbT = 0.f;
if (x0_curTime < 0.25f)
ftbT = 1.f - x0_curTime / 0.25f;
else if (x0_curTime > x4_modelData->x1d8_transCompleteTime)
ftbT = 1.f;
else if (x0_curTime > x4_modelData->x1d8_transCompleteTime - 0.25f)
ftbT = 1.f - (x4_modelData->x1d8_transCompleteTime - x0_curTime) / 0.25f;
if (ftbT > 0.f)
m_fadeToBlack.draw(zeus::CColor{0.f, 0.f, 0.f, ftbT});
}
void CWorldTransManager::DrawDisabled() {
SCOPED_GRAPHICS_DEBUG_GROUP("CWorldTransManager::DrawDisabled", zeus::skPurple);
m_fadeToBlack.draw(zeus::CColor{0.f, 0.f, 0.f, 0.01f});
}
void CWorldTransManager::DrawText() {
SCOPED_GRAPHICS_DEBUG_GROUP("CWorldTransManager::DrawText", zeus::skPurple);
float width = 448.f * g_Viewport.aspect;
CGraphics::SetOrtho(0.f, width, 448.f, 0.f, -4096.f, 4096.f);
CGraphics::SetViewPointMatrix(zeus::CTransform());
CGraphics::SetModelMatrix(zeus::CTransform::Translate((width - 640.f) / 2.f, 0.f, 448.f));
x8_textData->Render();
float filterAlpha = 0.f;
if (x0_curTime < 1.f)
filterAlpha = 1.f - x0_curTime;
else if (x44_25_stopSoon)
filterAlpha = std::min(1.f, x0_curTime - x34_stopTime);
if (filterAlpha > 0.f) {
zeus::CColor filterColor = x44_27_fadeWhite ? zeus::skWhite : zeus::skBlack;
filterColor.a() = filterAlpha;
m_fadeToBlack.draw(filterColor);
}
}
void CWorldTransManager::Draw() {
if (x30_type == ETransType::Disabled)
DrawDisabled();
else if (x30_type == ETransType::Enabled)
DrawEnabled();
else if (x30_type == ETransType::Text)
DrawText();
}
void CWorldTransManager::TouchModels() {
if (!x4_modelData)
return;
if (x4_modelData->x68_beamModelData.IsNull() && x4_modelData->x14c_beamModel.IsLoaded() &&
x4_modelData->x14c_beamModel.GetObj()) {
x4_modelData->x68_beamModelData = {
CStaticRes(x4_modelData->x14c_beamModel.GetObjectTag()->id, x4_modelData->x0_samusRes.GetScale()), 2};
}
if (x4_modelData->x1c_samusModelData.IsNull() && x4_modelData->x158_suitModel.IsLoaded() &&
x4_modelData->x158_suitModel.GetObj() && x4_modelData->x164_suitSkin.IsLoaded() &&
x4_modelData->x164_suitSkin.GetObj()) {
CAnimRes animRes(x4_modelData->x0_samusRes.GetId(), GetSuitCharIdx(), x4_modelData->x0_samusRes.GetScale(),
x4_modelData->x0_samusRes.GetDefaultAnim(), true);
x4_modelData->x1c_samusModelData = {animRes, 2};
CAnimPlaybackParms aData(animRes.GetDefaultAnim(), -1, 1.f, true);
x4_modelData->x1c_samusModelData.GetAnimationData()->SetAnimation(aData, false);
}
if (!x4_modelData->x1c_samusModelData.IsNull())
x4_modelData->x1c_samusModelData.Touch(CModelData::EWhichModel::Normal, 0);
if (!x4_modelData->xb4_platformModelData.IsNull())
x4_modelData->xb4_platformModelData.Touch(CModelData::EWhichModel::Normal, 0);
if (!x4_modelData->x100_bgModelData[0].IsNull())
x4_modelData->x100_bgModelData[0].Touch(CModelData::EWhichModel::Normal, 0);
if (!x4_modelData->x100_bgModelData[1].IsNull())
x4_modelData->x100_bgModelData[1].Touch(CModelData::EWhichModel::Normal, 0);
if (!x4_modelData->x100_bgModelData[2].IsNull())
x4_modelData->x100_bgModelData[2].Touch(CModelData::EWhichModel::Normal, 0);
if (!x4_modelData->x68_beamModelData.IsNull())
x4_modelData->x68_beamModelData.Touch(CModelData::EWhichModel::Normal, 0);
}
void CWorldTransManager::EnableTransition(const CAnimRes& samusRes, CAssetId platRes, const zeus::CVector3f& platScale,
CAssetId bgRes, const zeus::CVector3f& bgScale, bool goingUp) {
x44_25_stopSoon = false;
x44_26_goingUp = goingUp;
x30_type = ETransType::Enabled;
x4_modelData = std::make_unique<SModelDatas>(samusRes);
if (!m_reflectionCube[0] && hecl::com_cubemaps->toBoolean())
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) {
m_reflectionCube[0] = ctx.newCubeRenderTexture(CUBEMAP_RES, CUBEMAP_MIPS);
m_reflectionCube[1] = ctx.newCubeRenderTexture(CUBEMAP_RES, CUBEMAP_MIPS);
return true;
} BooTrace);
x8_textData.reset();
x20_random.SetSeed(99);
CAssetId beamModelId = g_tweakPlayerRes->GetBeamCineModel(g_GameState->GetPlayerState()->GetCurrentBeam());
x4_modelData->x14c_beamModel = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), beamModelId});
TToken<CCharacterFactory> fac = g_CharFactoryBuilder->GetFactory(samusRes);
const CCharacterInfo& info = fac.GetObj()->GetCharInfo(GetSuitCharIdx());
x4_modelData->x158_suitModel = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), info.GetModelId()});
x4_modelData->x164_suitSkin = g_SimplePool->GetObj(SObjectTag{FOURCC('CSKR'), info.GetSkinRulesId()});
if (platRes.IsValid()) {
x4_modelData->xb4_platformModelData = {CStaticRes(platRes, platScale), 2};
x4_modelData->xb4_platformModelData.Touch(CModelData::EWhichModel::Normal, 0);
}
if (bgRes.IsValid()) {
CStaticRes bg(bgRes, bgScale);
x4_modelData->x100_bgModelData[0] = bg;
x4_modelData->x100_bgModelData[0].Touch(CModelData::EWhichModel::Normal, 0);
x4_modelData->x100_bgModelData[1] = bg;
x4_modelData->x100_bgModelData[1].Touch(CModelData::EWhichModel::Normal, 0);
x4_modelData->x100_bgModelData[2] = bg;
x4_modelData->x100_bgModelData[2].Touch(CModelData::EWhichModel::Normal, 0);
zeus::CAABox bounds = x4_modelData->x100_bgModelData[0].GetBounds();
x1c_bgHeight = (bounds.max.z() - bounds.min.z()) * bgScale.z();
} else
x1c_bgHeight = 0.f;
StartTransition();
TouchModels();
}
void CWorldTransManager::EnableTransition(CAssetId fontId, CAssetId stringId, u32 strIdx, bool fadeWhite,
float chFadeTime, float chFadeRate, float textStartTime) {
x40_strIdx = strIdx;
x38_textStartTime = textStartTime;
x44_25_stopSoon = false;
x30_type = ETransType::Text;
x4_modelData.reset();
x44_27_fadeWhite = fadeWhite;
const CGuiTextProperties props(false, true, EJustification::Center, EVerticalJustification::Center);
x8_textData = std::make_unique<CGuiTextSupport>(fontId, props, zeus::skWhite, zeus::skBlack, zeus::skWhite, 640, 448,
g_SimplePool, CGuiWidget::EGuiModelDrawFlags::Additive);
x8_textData->SetTypeWriteEffectOptions(true, chFadeTime, chFadeRate);
xc_strTable = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), stringId});
x8_textData->SetText(u"");
StartTransition();
}
void CWorldTransManager::StartTextFadeOut() {
if (!x44_25_stopSoon)
x34_stopTime = x0_curTime;
x44_25_stopSoon = true;
}
void CWorldTransManager::DisableTransition() {
x30_type = ETransType::Disabled;
x4_modelData.reset();
x8_textData.reset();
x44_26_goingUp = false;
}
void CWorldTransManager::StartTransition() {
x0_curTime = 0.f;
x18_bgOffset = 0.f;
x44_24_transFinished = false;
x44_28_textDirty = true;
}
void CWorldTransManager::EndTransition() { DisableTransition(); }
bool CWorldTransManager::WaitForModelsAndTextures() {
std::vector<SObjectTag> tags = g_SimplePool->GetReferencedTags();
for (const SObjectTag& tag : tags) {
if (tag.type == FOURCC('TXTR') || tag.type == FOURCC('CMDL'))
g_SimplePool->GetObj(tag).GetObj();
}
return false;
}
void CWorldTransManager::SfxStop() {
if (x28_sfxHandle) {
CSfxManager::SfxStop(x28_sfxHandle);
x28_sfxHandle.reset();
}
}
void CWorldTransManager::SfxStart() {
if (!x28_sfxHandle && x24_sfx != 0xFFFF)
x28_sfxHandle = CSfxManager::SfxStart(x24_sfx, x2c_volume, x2d_panning, false, 127, true, -1);
}
} // namespace urde