prime/src/MetroidPrime/ScriptObjects/CHUDBillboardEffect.cpp
2022-11-11 02:26:17 +02:00

116 lines
4.1 KiB
C++

#include "MetroidPrime/ScriptObjects/CHUDBillboardEffect.hpp"
#include "MetroidPrime/CStateManager.hpp"
#include "MetroidPrime/CWorld.hpp"
#include "MetroidPrime/Cameras/CCameraManager.hpp"
#include "MetroidPrime/Cameras/CGameCamera.hpp"
#include "MetroidPrime/Player/CPlayer.hpp"
#include "MetaRender/CCubeRenderer.hpp"
#include "Kyoto/Particles/CElementGen.hpp"
#include "Kyoto/Particles/CParticleElectric.hpp"
#include "rstl/math.hpp"
int CHUDBillboardEffect::g_BillboardCount = 0;
int CHUDBillboardEffect::g_IndirectTexturedBillboardCount = 0;
float CHUDBillboardEffect::CalcGenRate() {
float f1 = (g_BillboardCount + g_IndirectTexturedBillboardCount <= 4)
? 0.f
: g_BillboardCount * 0.2f + g_IndirectTexturedBillboardCount * 0.1f;
return 1.f - rstl::min_val(0.8f, f1);
}
const CVector3f& CHUDBillboardEffect::GetScaleForPOV(const CStateManager& mgr) {
static CVector3f result(0.155f, 1.f, 0.155f);
return result;
}
float CHUDBillboardEffect::GetNearClipDistance(const CStateManager& mgr) {
return mgr.GetCameraManager()->GetCurrentCamera(mgr).GetNearClipDistance() + 0.01f;
}
CHUDBillboardEffect::CHUDBillboardEffect(
const rstl::optional_object< TToken< CGenDescription > >& particle,
const rstl::optional_object< TToken< CElectricDescription > >& electric, TUniqueId uid,
bool active, const rstl::string& name, float dist, const CVector3f& scale0, const CColor& color,
const CVector3f& scale1, const CVector3f& translation)
: CEffect(uid, CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList), active, name,
CTransform4f::Identity())
, xec_translation(translation.GetX(), translation.GetY() + dist, translation.GetZ())
, xf8_localScale(CVector3f::ByElementMultiply(scale1, scale0))
, x104_24_renderAsParticleGen(true)
, x104_25_enableRender(false)
, x104_26_isElementGen(false)
, x104_27_runIndefinitely(false)
, x108_timeoutTimer(0.f) {
if (particle) {
x104_26_isElementGen = true;
xe8_generator = new CElementGen(*particle);
if (static_cast< CElementGen& >(*xe8_generator).IsIndirectTextured())
++g_IndirectTexturedBillboardCount;
} else {
xe8_generator = new CParticleElectric(TToken< CElectricDescription >(*electric));
}
++g_BillboardCount;
xe8_generator->SetModulationColor(color);
xe8_generator->SetLocalScale(xf8_localScale);
}
CHUDBillboardEffect::~CHUDBillboardEffect() {
--g_BillboardCount;
if (xe8_generator->Get4CharId() == 'PART')
if (static_cast< CElementGen& >(*xe8_generator).IsIndirectTextured())
--g_IndirectTexturedBillboardCount;
}
void CHUDBillboardEffect::AddToRenderer(const CFrustumPlanes& frustum,
const CStateManager& mgr) const {
if (x104_25_enableRender && x104_24_renderAsParticleGen) {
gpRender->AddParticleGen(*xe8_generator);
}
}
void CHUDBillboardEffect::PreRender(CStateManager& mgr, const CFrustumPlanes& frustum) {
if (mgr.GetPlayer()->GetCameraState() == CPlayer::kCS_FirstPerson) {
CTransform4f camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr);
xe8_generator->SetGlobalTranslation(camXf * xec_translation);
xe8_generator->SetGlobalOrientation(camXf);
x104_25_enableRender = true;
} else {
x104_25_enableRender = false;
}
x104_24_renderAsParticleGen = !mgr.RenderLast(GetUniqueId());
}
void CHUDBillboardEffect::Render(const CStateManager& mgr) const {
if (x104_25_enableRender && !x104_24_renderAsParticleGen) {
xe8_generator->Render();
}
}
void CHUDBillboardEffect::Think(float dt, CStateManager& mgr) {
if (GetActive()) {
mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId());
float oldGenRate = xe8_generator->GetGeneratorRate();
xe8_generator->SetGeneratorRate(oldGenRate * CalcGenRate());
xe8_generator->Update(dt);
xe8_generator->SetGeneratorRate(oldGenRate);
if (!x104_27_runIndefinitely) {
x108_timeoutTimer += dt;
if (x108_timeoutTimer > 30.f) {
mgr.FreeScriptObject(GetUniqueId());
return;
}
}
if (xe8_generator->IsSystemDeletable())
mgr.FreeScriptObject(GetUniqueId());
}
}
void CHUDBillboardEffect::Accept(IVisitor& visitor) { visitor.Visit(*this); }