Library/Camera: Implement CameraTargetHolder (#784)

This commit is contained in:
Narr the Reg 2025-11-23 03:54:41 -06:00 committed by GitHub
parent 5539b5a52c
commit 64aa34a491
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 184 additions and 20 deletions

View file

@ -229235,55 +229235,55 @@ Library/Camera/CameraTargetHolder.o:
label:
- _ZN2al18CameraTargetHolderC1Ei
- _ZN2al18CameraTargetHolderC2Ei
status: NotDecompiled
status: Matching
- offset: 0x83ae18
size: 292
label: _ZN2al18CameraTargetHolder18initAfterPlacementEPKNS_12PlayerHolderE
status: NotDecompiled
status: Matching
- offset: 0x83af3c
size: 52
label: _ZNK2al18CameraTargetHolder16tryGetViewTargetEi
status: NotDecompiled
status: Matching
- offset: 0x83af70
size: 244
label: _ZN2al18CameraTargetHolder6updateEv
status: NotDecompiled
status: Matching
- offset: 0x83b064
size: 116
label: _ZN2al18CameraTargetHolder9addTargetEPNS_16CameraTargetBaseE
status: NotDecompiled
status: Matching
- offset: 0x83b0d8
size: 156
label: _ZN2al18CameraTargetHolder12removeTargetEPNS_16CameraTargetBaseE
status: NotDecompiled
status: Matching
- offset: 0x83b174
size: 52
label: _ZNK2al18CameraTargetHolder13getViewTargetEi
status: NotDecompiled
status: Matching
- offset: 0x83b1a8
size: 24
label: _ZNK2al18CameraTargetHolder18isChangeViewTargetEi
status: NotDecompiled
status: Matching
- offset: 0x83b1c0
size: 8
label: _ZNK2al18CameraTargetHolder15getTopSubTargetEv
status: NotDecompiled
status: Matching
- offset: 0x83b1c8
size: 116
label: _ZN2al18CameraTargetHolder12addSubTargetEPNS_19CameraSubTargetBaseE
status: NotDecompiled
status: NonMatchingMinor
- offset: 0x83b23c
size: 92
label: _ZN2al18CameraTargetHolder15removeSubTargetEPNS_19CameraSubTargetBaseE
status: NotDecompiled
status: NonMatchingMinor
- offset: 0x83b298
size: 116
label: _ZN2al18CameraTargetHolder21addPlacementSubTargetEPNS_19CameraSubTargetBaseE
status: NotDecompiled
status: NonMatchingMinor
- offset: 0x83b30c
size: 92
label: _ZN2al18CameraTargetHolder24removePlacementSubTargetEPNS_19CameraSubTargetBaseE
status: NotDecompiled
status: NonMatchingMinor
Library/Camera/CameraTicket.o:
'.text':
- offset: 0x83b368

View file

@ -43,6 +43,12 @@ public:
virtual f32 getRequestDistance() const { return -1.0f; }
bool isActiveTarget() const { return mIsActiveTarget; }
void enableTarget() { mIsActiveTarget = true; }
void disableTarget() { mIsActiveTarget = false; }
private:
bool mIsActiveTarget = false;
};

View file

@ -0,0 +1,138 @@
#include "Library/Camera/CameraTargetHolder.h"
#include "Library/Camera/ActorCameraTarget.h"
#include "Library/Camera/CameraSubTargetBase.h"
#include "Library/Camera/CameraTargetBase.h"
#include "Library/Player/PlayerUtil.h"
namespace al {
CameraTargetHolder::CameraTargetHolder(s32 maxTargets) : mViewTargetSize(maxTargets) {
mViewTargetArray = new CameraTargetBase*[maxTargets];
mViewTargetInfo = new ViewTargetInfo[maxTargets];
for (s32 i = 0; i < mViewTargetSize; i++)
mViewTargetArray[i] = nullptr;
mTargetArray.allocBuffer(32, nullptr);
mSubTargetArray.allocBuffer(32, nullptr);
mPlacementSubTargetArray.allocBuffer(32, nullptr);
}
void CameraTargetHolder::initAfterPlacement(const PlayerHolder* holder) {
if (mTargetArray.isEmpty()) {
for (s32 i = 0; i < getPlayerNumMax(holder); i++) {
if (mTargetArray.isFull())
break;
mTargetArray.pushBack(new ActorCameraTarget(getPlayerActor(holder, i), 0.0f, nullptr));
}
}
for (s32 i = 0; i < mViewTargetSize; i++) {
ViewTargetInfo* info = &mViewTargetInfo[i];
info->target = getViewTarget(i);
}
}
CameraTargetBase* CameraTargetHolder::tryGetViewTarget(s32 index) const {
CameraTargetBase* target = mViewTargetArray[index];
if (target)
return target;
if (mTargetArray.size() > 0)
return mTargetArray.front();
return nullptr;
}
void CameraTargetHolder::update() {
for (s32 i = 0; i < mViewTargetSize; i++) {
ViewTargetInfo* info = &mViewTargetInfo[i];
CameraTargetBase* target = getViewTarget(i);
info->hasTargetChanged = info->target != target;
info->target = target;
if (target)
target->update();
}
CameraSubTargetBase* topSubTarget = nullptr;
if (!mSubTargetArray.isEmpty())
topSubTarget = mSubTargetArray.front();
else if (!mPlacementSubTargetArray.isEmpty())
topSubTarget = mPlacementSubTargetArray.front();
mHasTopSubTargetChanged = mTopSubTarget != topSubTarget;
mTopSubTarget = topSubTarget;
if (topSubTarget)
topSubTarget->update();
}
void CameraTargetHolder::addTarget(CameraTargetBase* target) {
s32 index = mTargetArray.indexOf(target);
if (index > -1)
mTargetArray.erase(index);
target->enableTarget();
mTargetArray.pushFront(target);
}
void CameraTargetHolder::removeTarget(CameraTargetBase* target) {
s32 index = mTargetArray.indexOf(target);
if (index > -1) {
target->disableTarget();
mTargetArray.erase(index);
}
for (s32 i = 0; i < mViewTargetSize; i++) {
if (mViewTargetArray[i] == target) {
target->disableTarget();
mViewTargetArray[i] = nullptr;
}
}
}
CameraTargetBase* CameraTargetHolder::getViewTarget(s32 index) const {
return tryGetViewTarget(index);
}
bool CameraTargetHolder::isChangeViewTarget(s32 index) const {
return mViewTargetInfo[index].hasTargetChanged;
}
CameraSubTargetBase* CameraTargetHolder::getTopSubTarget() const {
return mTopSubTarget;
}
// NON_MATCHING: Depends on removeSubTarget
void CameraTargetHolder::addSubTarget(CameraSubTargetBase* subTarget) {
removeSubTarget(subTarget);
subTarget->enableTarget();
mSubTargetArray.pushFront(subTarget);
}
// NON_MATCHING: https://decomp.me/scratch/qrlL5
void CameraTargetHolder::removeSubTarget(CameraSubTargetBase* subTarget) {
s32 index = mSubTargetArray.indexOf(subTarget);
if (index > -1)
mSubTargetArray.erase(index);
subTarget->disableTarget();
}
// NON_MATCHING: Depends on removePlacementSubTarget
void CameraTargetHolder::addPlacementSubTarget(CameraSubTargetBase* subTarget) {
removePlacementSubTarget(subTarget);
subTarget->enableTarget();
mPlacementSubTargetArray.pushFront(subTarget);
}
// NON_MATCHING: https://decomp.me/scratch/Sv3mo
void CameraTargetHolder::removePlacementSubTarget(CameraSubTargetBase* subTarget) {
s32 index = mPlacementSubTargetArray.indexOf(subTarget);
if (index > -1)
mPlacementSubTargetArray.erase(index);
subTarget->disableTarget();
}
} // namespace al

View file

@ -1,6 +1,7 @@
#pragma once
#include <basis/seadTypes.h>
#include <container/seadPtrArray.h>
namespace al {
@ -8,22 +9,41 @@ class PlayerHolder;
class CameraTargetBase;
class CameraSubTargetBase;
struct ViewTargetInfo {
CameraTargetBase* target = nullptr;
// Note: s8 is used instead of bool to match isChangeViewTarget
s8 hasTargetChanged = false;
};
static_assert(sizeof(ViewTargetInfo) == 0x10);
class CameraTargetHolder {
public:
CameraTargetHolder(u32 maxTargets);
CameraTargetBase* tryGetViewTarget(u32 index) const;
CameraTargetBase* getViewTarget(u32 index) const;
CameraSubTargetBase* getTopSubTarget() const;
CameraTargetHolder(s32 maxTargets);
void initAfterPlacement(const PlayerHolder*);
CameraTargetBase* tryGetViewTarget(s32 index) const;
void update();
void addTarget(CameraTargetBase* target);
void removeTarget(const CameraTargetBase* target);
void removeTarget(CameraTargetBase* target);
CameraTargetBase* getViewTarget(s32 index) const;
bool isChangeViewTarget(s32 index) const;
CameraSubTargetBase* getTopSubTarget() const;
void addSubTarget(CameraSubTargetBase* subTarget);
void removeSubTarget(CameraSubTargetBase* subTarget);
void addPlacementSubTarget(CameraSubTargetBase* subTarget);
void removePlacementSubTarget(CameraSubTargetBase* subTarget);
bool isChangeViewTarget(u32 index) const;
private:
s32 mViewTargetSize = 0;
CameraTargetBase** mViewTargetArray = nullptr;
ViewTargetInfo* mViewTargetInfo = nullptr;
sead::PtrArray<CameraTargetBase> mTargetArray;
CameraSubTargetBase* mTopSubTarget = nullptr;
bool mHasTopSubTargetChanged = false;
sead::PtrArray<CameraSubTargetBase> mSubTargetArray;
sead::PtrArray<CameraSubTargetBase> mPlacementSubTargetArray;
};
static_assert(sizeof(CameraTargetHolder) == 0x58);
} // namespace al