Scene: Implement SceneEventFunctorListener, SceneEventListenerHolder, SceneEventNotifier and SceneEventNotifyFunction (#917)

This commit is contained in:
Fuzzy2319 2026-02-24 00:07:35 +01:00 committed by GitHub
parent bf1e9d457a
commit b65ba0f9c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 276 additions and 39 deletions

View file

@ -137364,11 +137364,11 @@ Scene/SceneEventFunctorListener.o:
label:
- _ZN25SceneEventFunctorListenerC1ERKN2al11FunctorBaseE
- _ZN25SceneEventFunctorListenerC2ERKN2al11FunctorBaseE
status: NotDecompiled
status: Matching
- offset: 0x4c3d94
size: 24
label: _ZN25SceneEventFunctorListener6notifyEv
status: NotDecompiled
status: Matching
Scene/SceneEventListenerHolder.o:
'.text':
- offset: 0x4c3dac
@ -137376,15 +137376,15 @@ Scene/SceneEventListenerHolder.o:
label:
- _ZN24SceneEventListenerHolderC1EPKci
- _ZN24SceneEventListenerHolderC2EPKci
status: NotDecompiled
status: Matching
- offset: 0x4c3df0
size: 28
label: _ZN24SceneEventListenerHolder3addEP18SceneEventListener
status: NotDecompiled
status: Matching
- offset: 0x4c3e0c
size: 80
label: _ZN24SceneEventListenerHolder6notifyEv
status: NotDecompiled
status: Matching
Scene/SceneEventNotifier.o:
'.text':
- offset: 0x4c3e5c
@ -137392,54 +137392,54 @@ Scene/SceneEventNotifier.o:
label:
- _ZN18SceneEventNotifierC1Ev
- _ZN18SceneEventNotifierC2Ev
status: NotDecompiled
status: NonMatchingMajor
- offset: 0x4c3ee4
size: 144
label: _ZN18SceneEventNotifier22initListenerHolderListEP27SceneEventNotifierInitTablei
status: NotDecompiled
status: Matching
- offset: 0x4c3f74
size: 120
label: _ZN18SceneEventNotifier11addListenerEPKcP18SceneEventListener
status: NotDecompiled
status: Matching
- offset: 0x4c3fec
size: 112
label: _ZN18SceneEventNotifier28findSceneEventListenerHolderEPKc
status: NotDecompiled
status: Matching
- offset: 0x4c405c
size: 112
label: _ZN18SceneEventNotifier6notifyEPKc
status: NotDecompiled
status: Matching
- offset: 0x4c40cc
size: 112
label: _ZN18SceneEventNotifier31tryFindSceneEventListenerHolderEPKc
status: NotDecompiled
status: Matching
- offset: 0x4c413c
size: 120
label: _ZN2rs16notifySceneEventEPKN2al18IUseSceneObjHolderEPKc
status: NotDecompiled
status: Matching
- offset: 0x4c41b4
size: 128
label: _ZN2rs16listenSceneEventEPKN2al18IUseSceneObjHolderEPKcP18SceneEventListener
status: NotDecompiled
status: Matching
- offset: 0x4c4234
size: 4
label: _ZN18SceneEventNotifierD0Ev
status: NotDecompiled
status: Matching
lazy: true
Scene/SceneEventNotifyFunction.o:
'.text':
- offset: 0x4c4238
size: 120
label: _ZN2rs23listenSnapShotModeOnOffEPKN2al18IUseSceneObjHolderERKNS0_11FunctorBaseES6_
status: NotDecompiled
Scene/SceneEventNotifyFunction.o:
'.text':
status: Matching
- offset: 0x4c42b0
size: 12
label: _ZN24SceneEventNotifyFunction20notifySnapShotModeOnEPKN2al18IUseSceneObjHolderE
status: NotDecompiled
status: Matching
- offset: 0x4c42bc
size: 12
label: _ZN24SceneEventNotifyFunction21notifySnapShotModeOffEPKN2al18IUseSceneObjHolderE
status: NotDecompiled
status: Matching
Scene/SceneObjFactory.o:
'.text':
- offset: 0x4c42c8

View file

@ -1,9 +1,6 @@
#pragma once
#include <basis/seadTypes.h>
namespace al {
class ISceneObj;
class SceneObjHolder;
class IUseSceneObjHolder {
@ -13,7 +10,4 @@ public:
private:
static const char* sSceneObjName;
};
ISceneObj* createSceneObj(const IUseSceneObjHolder* user, s32 sceneObjId);
} // namespace al

View file

@ -14,6 +14,16 @@ bool isExistSceneObj(const IUseSceneObjHolder* user, s32 sceneObjId);
void deleteSceneObj(const IUseSceneObjHolder* user, s32 sceneObjId);
bool tryDeleteSceneObj(const IUseSceneObjHolder* user, s32 sceneObjId);
template <typename T>
inline T* createSceneObj(const IUseSceneObjHolder* user) {
return static_cast<T*>(createSceneObj(user, T::sSceneObjId));
}
template <typename T>
inline void setSceneObj(const IUseSceneObjHolder* user, T* obj) {
setSceneObj(user, obj, T::sSceneObjId);
}
template <typename T>
inline T* getSceneObj(const IUseSceneObjHolder* user) {
return static_cast<T*>(getSceneObj(user, T::sSceneObjId));
@ -24,4 +34,19 @@ inline T* tryGetSceneObj(const IUseSceneObjHolder* user) {
return static_cast<T*>(tryGetSceneObj(user, T::sSceneObjId));
}
template <typename T>
inline bool isExistSceneObj(const IUseSceneObjHolder* user) {
return isExistSceneObj(user, T::sSceneObjId);
}
template <typename T>
inline void deleteSceneObj(const IUseSceneObjHolder* user) {
deleteSceneObj(user, T::sSceneObjId);
}
template <typename T>
inline bool tryDeleteSceneObj(const IUseSceneObjHolder* user) {
return tryDeleteSceneObj(user, T::sSceneObjId);
}
} // namespace al

View file

@ -4,11 +4,11 @@
#include "Library/Base/StringUtil.h"
#include "Library/LiveActor/ActorFlagFunction.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/Scene/SceneObjUtil.h"
#include "Item/CoinCollect.h"
#include "Item/CoinCollect2D.h"
#include "MapObj/CoinCollectHintObj.h"
#include "Scene/SceneObjFactory.h"
#include "Util/PlayerUtil.h"
CoinCollectHolder::CoinCollectHolder() {
@ -206,6 +206,6 @@ const char* CoinCollectHolder::getSceneObjName() const {
namespace rs {
CoinCollectHolder* createCoinCollectHolder(const al::IUseSceneObjHolder* objHolder) {
return (CoinCollectHolder*)al::createSceneObj(objHolder, SceneObjID_CoinCollectHolder);
return al::createSceneObj<CoinCollectHolder>(objHolder);
}
} // namespace rs

View file

@ -3,10 +3,10 @@
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/Player/PlayerUtil.h"
#include "Library/Scene/IUseSceneObjHolder.h"
#include "Library/Scene/SceneObjUtil.h"
#include "Library/Se/SeFunction.h"
#include "Layout/CoinCollectLayout.h"
#include "Scene/SceneObjFactory.h"
#include "System/GameDataFunction.h"
CoinCollectWatcher::CoinCollectWatcher() : al::ISceneObj() {}
@ -36,6 +36,6 @@ void CoinCollectWatcher::countup(const al::LiveActor* actor) {
namespace rs {
CoinCollectWatcher* createCoinCollectWatcher(const al::IUseSceneObjHolder* objHolder) {
return (CoinCollectWatcher*)al::createSceneObj(objHolder, SceneObjID_CoinCollectWatcher);
return al::createSceneObj<CoinCollectWatcher>(objHolder);
}
} // namespace rs

View file

@ -273,27 +273,27 @@ void BirdPlayerGlideCtrl::exeWaitFlyAway() {
namespace rs {
void validateGlideBirdOnPlayerNose(const al::LiveActor* player) {
if (al::isExistSceneObj(player, BirdPlayerGlideCtrl::sSceneObjId))
if (al::isExistSceneObj<BirdPlayerGlideCtrl>(player))
al::getSceneObj<BirdPlayerGlideCtrl>(player)->validateGlideOnNose();
}
void invalidateGlideBirdOnPlayerNose(const al::LiveActor* player) {
if (al::isExistSceneObj(player, BirdPlayerGlideCtrl::sSceneObjId))
if (al::isExistSceneObj<BirdPlayerGlideCtrl>(player))
al::getSceneObj<BirdPlayerGlideCtrl>(player)->invalidateGlideOnNose();
}
void validateGlideBirdOnSitDownPlayerHead(const al::LiveActor* player) {
if (al::isExistSceneObj(player, BirdPlayerGlideCtrl::sSceneObjId))
if (al::isExistSceneObj<BirdPlayerGlideCtrl>(player))
al::getSceneObj<BirdPlayerGlideCtrl>(player)->validateGlideOnSitDownHead();
}
void invalidateGlideBirdOnSitDownPlayerHead(const al::LiveActor* player) {
if (al::isExistSceneObj(player, BirdPlayerGlideCtrl::sSceneObjId))
if (al::isExistSceneObj<BirdPlayerGlideCtrl>(player))
al::getSceneObj<BirdPlayerGlideCtrl>(player)->invalidateGlideOnSitDownHead();
}
bool isPlayerSitDownChair(const Bird* bird) {
return al::isExistSceneObj(bird, BirdPlayerGlideCtrl::sSceneObjId) &&
return al::isExistSceneObj<BirdPlayerGlideCtrl>(bird) &&
al::getSceneObj<BirdPlayerGlideCtrl>(bird)->isValidOnSitDownHead();
}

View file

@ -45,8 +45,7 @@ void FirstSequenceScene::init(const al::SceneInitInfo& info) {
initDrawSystemInfo(info);
initSceneObjHolder(SceneObjFactory::createSceneObjHolder());
al::setSceneObj(this, GameDataFunction::getGameDataHolder(info.gameDataHolder),
SceneObjID_GameDataHolder);
al::setSceneObj(this, GameDataFunction::getGameDataHolder(info.gameDataHolder));
initSceneStopCtrl();

View file

@ -0,0 +1,14 @@
#include "Scene/SceneEventFunctorListener.h"
#include "Library/Thread/FunctorV0M.h"
SceneEventFunctorListener::SceneEventFunctorListener(const al::FunctorBase& functor) {
mFunctor = functor.clone();
}
void SceneEventFunctorListener::notify() {
if (!mFunctor)
return;
(*mFunctor)();
}

View file

@ -0,0 +1,17 @@
#pragma once
#include "Scene/SceneEventListener.h"
namespace al {
class FunctorBase;
} // namespace al
class SceneEventFunctorListener : public SceneEventListener {
public:
SceneEventFunctorListener(const al::FunctorBase& functor);
void notify() override;
private:
al::FunctorBase* mFunctor = nullptr;
};

View file

@ -0,0 +1,6 @@
#pragma once
struct SceneEventListener {
public:
virtual void notify() = 0;
};

View file

@ -0,0 +1,18 @@
#include "Scene/SceneEventListenerHolder.h"
#include "Scene/SceneEventListener.h"
SceneEventListenerHolder::SceneEventListenerHolder(const char* name, s32 maxListenerCount)
: mName(name), mMaxListenerCount(maxListenerCount) {
mListeners = new SceneEventListener*[maxListenerCount];
}
void SceneEventListenerHolder::add(SceneEventListener* listener) {
mListeners[mListenerCount] = listener;
mListenerCount++;
}
void SceneEventListenerHolder::notify() {
for (s32 i = 0; i < mListenerCount; i++)
mListeners[i]->notify();
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <basis/seadTypes.h>
struct SceneEventListener;
class SceneEventListenerHolder {
public:
SceneEventListenerHolder(const char* name, s32 maxListenerCount);
/**
* @warning This function doesn't check maxListenerCount, possible buffer overflow.
*/
void add(SceneEventListener* listener);
void notify();
const char* getName() const { return mName; }
private:
const char* mName;
SceneEventListener** mListeners;
s32 mListenerCount = 0;
s32 mMaxListenerCount;
};

View file

@ -0,0 +1,55 @@
#include "Scene/SceneEventNotifier.h"
#include "Library/Base/StringUtil.h"
#include "Library/Scene/SceneObjUtil.h"
#include "Scene/SceneEventListenerHolder.h"
SceneEventNotifierInitTable sSceneEventNotifierInitTables[] = {{"SnapShotModeOn", 256},
{"SnapShotModeOff", 256}};
// NON_MATCHING but equivalent https://decomp.me/scratch/bNYHm
SceneEventNotifier::SceneEventNotifier() {
initListenerHolderList(sSceneEventNotifierInitTables);
}
void SceneEventNotifier::initListenerHolderList(SceneEventNotifierInitTable* initTables,
s32 initTableCount) {
mListenerHolderCount = initTableCount;
mListenerHolders = new SceneEventListenerHolder*[mListenerHolderCount];
for (s32 i = 0; i < mListenerHolderCount; i++)
mListenerHolders[i] = new SceneEventListenerHolder(initTables[i].name, initTables[i].count);
}
void SceneEventNotifier::addListener(const char* holderName, SceneEventListener* listener) {
findSceneEventListenerHolder(holderName)->add(listener);
}
SceneEventListenerHolder* SceneEventNotifier::findSceneEventListenerHolder(const char* holderName) {
for (s32 i = 0; i < mListenerHolderCount; i++)
if (al::isEqualString(mListenerHolders[i]->getName(), holderName))
return mListenerHolders[i];
return nullptr;
}
void SceneEventNotifier::notify(const char* holderName) {
findSceneEventListenerHolder(holderName)->notify();
}
SceneEventListenerHolder*
SceneEventNotifier::tryFindSceneEventListenerHolder(const char* holderName) {
return findSceneEventListenerHolder(holderName);
}
namespace rs {
void notifySceneEvent(const al::IUseSceneObjHolder* user, const char* holderName) {
al::createSceneObj<SceneEventNotifier>(user)->notify(holderName);
}
void listenSceneEvent(const al::IUseSceneObjHolder* user, const char* holderName,
SceneEventListener* listener) {
al::createSceneObj<SceneEventNotifier>(user)->addListener(holderName, listener);
}
} // namespace rs

View file

@ -0,0 +1,49 @@
#pragma once
#include <basis/seadTypes.h>
#include "Library/HostIO/HioNode.h"
#include "Library/Scene/ISceneObj.h"
#include "Scene/SceneObjFactory.h"
namespace al {
class IUseSceneObjHolder;
} // namespace al
struct SceneEventListener;
class SceneEventListenerHolder;
struct SceneEventNotifierInitTable {
const char* name;
s32 count;
};
class SceneEventNotifier : public al::ISceneObj, public al::HioNode {
public:
static constexpr s32 sSceneObjId = SceneObjID_SceneEventNotifier;
SceneEventNotifier();
template <s32 N>
inline void initListenerHolderList(SceneEventNotifierInitTable (&initTables)[N]) {
initListenerHolderList(initTables, N);
}
void addListener(const char* holderName, SceneEventListener* listener);
SceneEventListenerHolder* findSceneEventListenerHolder(const char* holderName);
void notify(const char* holderName);
SceneEventListenerHolder* tryFindSceneEventListenerHolder(const char* holderName);
private:
void initListenerHolderList(SceneEventNotifierInitTable* initTables, s32 initTableCount);
SceneEventListenerHolder** mListenerHolders;
s32 mListenerHolderCount;
};
namespace rs {
void notifySceneEvent(const al::IUseSceneObjHolder* user, const char* holderName);
void listenSceneEvent(const al::IUseSceneObjHolder* user, const char* holderName,
SceneEventListener* listener);
} // namespace rs

View file

@ -0,0 +1,22 @@
#include "Scene/SceneEventNotifyFunction.h"
#include "Scene/SceneEventFunctorListener.h"
#include "Scene/SceneEventNotifier.h"
namespace rs {
void listenSnapShotModeOnOff(const al::IUseSceneObjHolder* user, const al::FunctorBase& actionOnOn,
const al::FunctorBase& actionOnOff) {
listenSceneEvent(user, "SnapShotModeOn", new SceneEventFunctorListener(actionOnOn));
listenSceneEvent(user, "SnapShotModeOff", new SceneEventFunctorListener(actionOnOff));
}
} // namespace rs
namespace SceneEventNotifyFunction {
void notifySnapShotModeOn(const al::IUseSceneObjHolder* user) {
rs::notifySceneEvent(user, "SnapShotModeOn");
}
void notifySnapShotModeOff(const al::IUseSceneObjHolder* user) {
rs::notifySceneEvent(user, "SnapShotModeOff");
}
} // namespace SceneEventNotifyFunction

View file

@ -0,0 +1,16 @@
#pragma once
namespace al {
class FunctorBase;
class IUseSceneObjHolder;
} // namespace al
namespace rs {
void listenSnapShotModeOnOff(const al::IUseSceneObjHolder* user, const al::FunctorBase& actionOnOn,
const al::FunctorBase& actionOnOff);
} // namespace rs
namespace SceneEventNotifyFunction {
void notifySnapShotModeOn(const al::IUseSceneObjHolder* user);
void notifySnapShotModeOff(const al::IUseSceneObjHolder* user);
} // namespace SceneEventNotifyFunction

View file

@ -32,7 +32,6 @@
#include "Library/Play/Layout/WindowConfirm.h"
#include "Library/Play/Layout/WipeSimple.h"
#include "Library/Player/PlayerUtil.h"
#include "Library/Projection/Projection.h"
#include "Library/Scene/Scene.h"
#include "Library/Scene/SceneObjUtil.h"
#include "Library/Scene/SceneUtil.h"
@ -79,8 +78,7 @@ void TitleMenuScene::init(const al::SceneInitInfo& info) {
al::SceneObjHolder* sceneObjHolder = SceneObjFactory::createSceneObjHolder();
initSceneObjHolder(sceneObjHolder);
al::setSceneObj(this, GameDataFunction::getGameDataHolder(info.gameDataHolder),
SceneObjID_GameDataHolder);
al::setSceneObj(this, GameDataFunction::getGameDataHolder(info.gameDataHolder));
initSceneStopCtrl();