From 34af5fd2516694c3230738073f48b2d8254751cd Mon Sep 17 00:00:00 2001 From: Henrique Gemignani Passos Lima Date: Tue, 8 Nov 2022 16:10:22 +0200 Subject: [PATCH] Add CScriptShadowProjector --- asm/MetroidPrime/CProjectedShadow.s | 4 +- asm/MetroidPrime/Enemies/CMetroidPrimeExo.s | 2 +- asm/MetroidPrime/Enemies/CRidley.s | 2 +- .../ScriptObjects/CScriptProjectedShadow.s | 14 +- configure.py | 2 +- include/MetroidPrime/CProjectedShadow.hpp | 29 ++++ .../ScriptObjects/CScriptProjectedShadow.hpp | 37 +++++ .../ScriptObjects/CScriptProjectedShadow.cpp | 126 ++++++++++++++++++ 8 files changed, 204 insertions(+), 12 deletions(-) create mode 100644 include/MetroidPrime/CProjectedShadow.hpp create mode 100644 include/MetroidPrime/ScriptObjects/CScriptProjectedShadow.hpp create mode 100644 src/MetroidPrime/ScriptObjects/CScriptProjectedShadow.cpp diff --git a/asm/MetroidPrime/CProjectedShadow.s b/asm/MetroidPrime/CProjectedShadow.s index a508ed2b..2e9306c4 100644 --- a/asm/MetroidPrime/CProjectedShadow.s +++ b/asm/MetroidPrime/CProjectedShadow.s @@ -893,8 +893,8 @@ lbl_8029E3C0: /* 8029E3D4 0029B334 38 21 00 10 */ addi r1, r1, 0x10 /* 8029E3D8 0029B338 4E 80 00 20 */ blr -.global __ct__16CProjectedShadowFv -__ct__16CProjectedShadowFv: +.global __ct__16CProjectedShadowFiiUc +__ct__16CProjectedShadowFiiUc: /* 8029E3DC 0029B33C 94 21 FF F0 */ stwu r1, -0x10(r1) /* 8029E3E0 0029B340 7C 08 02 A6 */ mflr r0 /* 8029E3E4 0029B344 38 E0 00 01 */ li r7, 1 diff --git a/asm/MetroidPrime/Enemies/CMetroidPrimeExo.s b/asm/MetroidPrime/Enemies/CMetroidPrimeExo.s index 9d2988b5..e5ccf551 100644 --- a/asm/MetroidPrime/Enemies/CMetroidPrimeExo.s +++ b/asm/MetroidPrime/Enemies/CMetroidPrimeExo.s @@ -12303,7 +12303,7 @@ lbl_8027B730: /* 8027B800 00278760 38 80 00 80 */ li r4, 0x80 /* 8027B804 00278764 38 A0 00 80 */ li r5, 0x80 /* 8027B808 00278768 38 C0 00 01 */ li r6, 1 -/* 8027B80C 0027876C 48 02 2B D1 */ bl __ct__16CProjectedShadowFv +/* 8027B80C 0027876C 48 02 2B D1 */ bl __ct__16CProjectedShadowFiiUc lbl_8027B810: /* 8027B810 00278770 90 70 14 3C */ stw r3, 0x143c(r16) /* 8027B814 00278774 38 00 FF FF */ li r0, -1 diff --git a/asm/MetroidPrime/Enemies/CRidley.s b/asm/MetroidPrime/Enemies/CRidley.s index 044db843..581f0ae2 100644 --- a/asm/MetroidPrime/Enemies/CRidley.s +++ b/asm/MetroidPrime/Enemies/CRidley.s @@ -9358,7 +9358,7 @@ lbl_8025A488: /* 8025A4BC 0025741C 38 80 00 80 */ li r4, 0x80 /* 8025A4C0 00257420 38 A0 00 80 */ li r5, 0x80 /* 8025A4C4 00257424 38 C0 00 01 */ li r6, 1 -/* 8025A4C8 00257428 48 04 3F 15 */ bl __ct__16CProjectedShadowFv +/* 8025A4C8 00257428 48 04 3F 15 */ bl __ct__16CProjectedShadowFiiUc /* 8025A4CC 0025742C 7C 60 1B 78 */ mr r0, r3 lbl_8025A4D0: /* 8025A4D0 00257430 90 1F 0D 10 */ stw r0, 0xd10(r31) diff --git a/asm/MetroidPrime/ScriptObjects/CScriptProjectedShadow.s b/asm/MetroidPrime/ScriptObjects/CScriptProjectedShadow.s index 90c5a0fd..996e74ce 100644 --- a/asm/MetroidPrime/ScriptObjects/CScriptProjectedShadow.s +++ b/asm/MetroidPrime/ScriptObjects/CScriptProjectedShadow.s @@ -3,8 +3,8 @@ .section .data .balign 8 -.global lbl_803EC030 -lbl_803EC030: +.global __vt__22CScriptShadowProjector +__vt__22CScriptShadowProjector: # ROM: 0x3E9030 .4byte 0 .4byte 0 @@ -47,9 +47,9 @@ __dt__22CScriptShadowProjectorFv: /* 8029ECEC 0029BC4C 93 C1 00 08 */ stw r30, 8(r1) /* 8029ECF0 0029BC50 7C 7E 1B 79 */ or. r30, r3, r3 /* 8029ECF4 0029BC54 41 82 00 40 */ beq lbl_8029ED34 -/* 8029ECF8 0029BC58 3C 60 80 3F */ lis r3, lbl_803EC030@ha +/* 8029ECF8 0029BC58 3C 60 80 3F */ lis r3, __vt__22CScriptShadowProjector@ha /* 8029ECFC 0029BC5C 34 1E 01 08 */ addic. r0, r30, 0x108 -/* 8029ED00 0029BC60 38 03 C0 30 */ addi r0, r3, lbl_803EC030@l +/* 8029ED00 0029BC60 38 03 C0 30 */ addi r0, r3, __vt__22CScriptShadowProjector@l /* 8029ED04 0029BC64 90 1E 00 00 */ stw r0, 0(r30) /* 8029ED08 0029BC68 41 82 00 10 */ beq lbl_8029ED18 /* 8029ED0C 0029BC6C 80 7E 01 08 */ lwz r3, 0x108(r30) @@ -340,7 +340,7 @@ lbl_8029F0AC: /* 8029F0F8 0029C058 80 9E 01 0C */ lwz r4, 0x10c(r30) /* 8029F0FC 0029C05C 54 06 CF FE */ rlwinm r6, r0, 0x19, 0x1f, 0x1f /* 8029F100 0029C060 7C 85 23 78 */ mr r5, r4 -/* 8029F104 0029C064 4B FF F2 D9 */ bl __ct__16CProjectedShadowFv +/* 8029F104 0029C064 4B FF F2 D9 */ bl __ct__16CProjectedShadowFiiUc /* 8029F108 0029C068 7C 7F 1B 78 */ mr r31, r3 lbl_8029F10C: /* 8029F10C 0029C06C 80 7E 01 08 */ lwz r3, 0x108(r30) @@ -433,9 +433,9 @@ lbl_8029F164: /* 8029F250 0029C1B0 38 61 00 88 */ addi r3, r1, 0x88 /* 8029F254 0029C1B4 38 80 FF FF */ li r4, -1 /* 8029F258 0029C1B8 4B E7 77 F5 */ bl __dt__10CModelDataFv -/* 8029F25C 0029C1BC 3C 60 80 3F */ lis r3, lbl_803EC030@ha +/* 8029F25C 0029C1BC 3C 60 80 3F */ lis r3, __vt__22CScriptShadowProjector@ha /* 8029F260 0029C1C0 C0 22 C0 E8 */ lfs f1, lbl_805ADE08@sda21(r2) -/* 8029F264 0029C1C4 38 03 C0 30 */ addi r0, r3, lbl_803EC030@l +/* 8029F264 0029C1C4 38 03 C0 30 */ addi r0, r3, __vt__22CScriptShadowProjector@l /* 8029F268 0029C1C8 C8 02 C0 F0 */ lfd f0, lbl_805ADE10@sda21(r2) /* 8029F26C 0029C1CC 90 1F 00 00 */ stw r0, 0(r31) /* 8029F270 0029C1D0 EC 3E 08 28 */ fsubs f1, f30, f1 diff --git a/configure.py b/configure.py index 84a62cb8..7f6cc3e9 100755 --- a/configure.py +++ b/configure.py @@ -387,7 +387,7 @@ LIBS = [ "MetroidPrime/CProjectedShadow", ["MetroidPrime/CPreFrontEnd", True], "MetroidPrime/CGameCubeDoll", - "MetroidPrime/ScriptObjects/CScriptProjectedShadow", + ["MetroidPrime/ScriptObjects/CScriptProjectedShadow", False], "MetroidPrime/ScriptObjects/CEnergyBall", ["MetroidPrime/Enemies/CMetroidPrimeProjectile", False], ["MetroidPrime/Enemies/SPositionHistory", True], diff --git a/include/MetroidPrime/CProjectedShadow.hpp b/include/MetroidPrime/CProjectedShadow.hpp new file mode 100644 index 00000000..e83b998e --- /dev/null +++ b/include/MetroidPrime/CProjectedShadow.hpp @@ -0,0 +1,29 @@ +#ifndef _CPROJECTEDSHADOW +#define _CPROJECTEDSHADOW + +#include "Kyoto/Graphics/CTexture.hpp" +#include "Kyoto/Math/CAABox.hpp" + +class CProjectedShadow { +public: + CProjectedShadow(int, int, uchar); + ~CProjectedShadow(); + + void RenderShadowBuffer(CStateManager&, const CModelData&, const CTransform4f&, int, + const CVector3f&, float, float); + + void SetOpacity(float opacity) { x98_opacity = opacity; } + +private: + CTexture x0_texture; + CAABox x68_; + bool x80_; + bool x81_persistent; + float x84_; + CVector3f x88_; + float x94_zDistanceAdjust; + float x98_opacity; +}; +CHECK_SIZEOF(CProjectedShadow, 0x9c) + +#endif // _CPROJECTEDSHADOW diff --git a/include/MetroidPrime/ScriptObjects/CScriptProjectedShadow.hpp b/include/MetroidPrime/ScriptObjects/CScriptProjectedShadow.hpp new file mode 100644 index 00000000..96d130cd --- /dev/null +++ b/include/MetroidPrime/ScriptObjects/CScriptProjectedShadow.hpp @@ -0,0 +1,37 @@ +#ifndef _CSCRIPTPROJECTEDSHADOW +#define _CSCRIPTPROJECTEDSHADOW + +#include "MetroidPrime/CActor.hpp" + +#include "rstl/single_ptr.hpp" + +class CProjectedShadow; + +class CScriptShadowProjector : public CActor { +public: + CScriptShadowProjector(TUniqueId, const rstl::string&, const CEntityInfo&, const CTransform4f&, + bool, const CVector3f&, bool, float, float, float, float, int); + + void Accept(IVisitor& visitor) override; + void Think(float, CStateManager&) override; + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) override; + void PreRender(CStateManager&, const CFrustumPlanes&) override; + void AddToRenderer(const CFrustumPlanes&, const CStateManager&) const override; + void CreateProjectedShadow(); + + uchar GetPersistent() const { return x110_24_persistent; } + +private: + float xe8_scale; + CVector3f xec_offset; + float xf8_zOffsetAdjust; + float xfc_opacity; + float x100_opacityRecip; + TUniqueId x104_target; + rstl::single_ptr< CProjectedShadow > x108_projectedShadow; + uint x10c_textureSize; + uchar x110_24_persistent : 1; + bool x110_25_shadowInvalidated : 1; +}; + +#endif // _CSCRIPTPROJECTEDSHADOW diff --git a/src/MetroidPrime/ScriptObjects/CScriptProjectedShadow.cpp b/src/MetroidPrime/ScriptObjects/CScriptProjectedShadow.cpp new file mode 100644 index 00000000..b00f6e60 --- /dev/null +++ b/src/MetroidPrime/ScriptObjects/CScriptProjectedShadow.cpp @@ -0,0 +1,126 @@ +#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); + } + } +}