#include "MetroidPrime/ScriptObjects/CScriptProjectedShadow.hpp" #include "MetroidPrime/CActorParameters.hpp" #include "MetroidPrime/CAnimData.hpp" #include "MetroidPrime/CModelData.hpp" #include "MetroidPrime/CProjectedShadow.hpp" #include "Kyoto/Math/CloseEnough.hpp" CScriptShadowProjector::CScriptShadowProjector(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, const CTransform4f& xf, bool active, const CVector3f& offset, bool persistent, float scale, float f2, float opacity, float opacityQ, int textureSize) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(), CActorParameters::None(), kInvalidUniqueId) , xe8_scale(scale) , xec_offset(offset) , xf8_zOffsetAdjust(f2) , xfc_opacity(opacity) , x100_opacityRecip(close_enough(opacity, 0.f) ? 1.f : opacityQ / opacity) , x104_target(kInvalidUniqueId) , x108_projectedShadow(nullptr) , x10c_textureSize(textureSize) , x110_24_persistent(persistent) , x110_25_shadowInvalidated(false) {} void CScriptShadowProjector::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { CActor::AcceptScriptMsg(msg, uid, mgr); switch (msg) { case kSM_InitializedInArea: for (rstl::vector< SConnection >::const_iterator conn = GetConnectionList().begin(); conn != GetConnectionList().end(); ++conn) { if (conn->x0_state != kSS_Play) { continue; } if (CActor* act = TCastToPtr< CActor >(mgr.ObjectById(mgr.GetIdForScript(conn->x8_objId)))) { if (act->HasModelData()) { x104_target = act->GetUniqueId(); break; } } } if (x104_target == kInvalidUniqueId) { mgr.FreeScriptObject(GetUniqueId()); break; } case kSM_Deactivate: case kSM_Activate: if (GetActive() && x104_target != kInvalidUniqueId && xfc_opacity > 0.f) { x108_projectedShadow = new CProjectedShadow(x10c_textureSize, x10c_textureSize, GetPersistent()); } else { x108_projectedShadow = nullptr; } break; case kSM_Decrement: if (!GetActive()) { return; } if (xfc_opacity > 0.f) { x110_25_shadowInvalidated = true; } break; default: break; } } void CScriptShadowProjector::AddToRenderer(const CFrustumPlanes&, const CStateManager&) const {} void CScriptShadowProjector::PreRender(CStateManager& mgr, const CFrustumPlanes&) { SetPreRenderClipped(true); if (!x108_projectedShadow.null()) { CActor* act = TCastToPtr< CActor >(mgr.ObjectById(x104_target)); bool hasModelData; if (act != nullptr) { hasModelData = false; if (act->HasModelData()) { hasModelData = true; } } else { x104_target = kInvalidUniqueId; return; } if (hasModelData) { if (!act->GetActive()) { return; } if (act->HasAnimation()) { act->AnimationData()->PreRender(); } x108_projectedShadow->SetOpacity(xfc_opacity); x108_projectedShadow->RenderShadowBuffer(mgr, *act->GetModelData(), act->GetTransform(), 0, xec_offset, xe8_scale, xf8_zOffsetAdjust); } } } void CScriptShadowProjector::Accept(IVisitor& visitor) { visitor.Visit(*this); } void CScriptShadowProjector::Think(float dt, CStateManager& mgr) { if (GetActive() && x110_25_shadowInvalidated) { xfc_opacity = -(x100_opacityRecip * dt - xfc_opacity); if (xfc_opacity <= 0.0f) { xfc_opacity = 0.0f; x108_projectedShadow = nullptr; x110_25_shadowInvalidated = false; SendScriptMsgs(kSS_Zero, mgr, kSM_None); } } }