mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-05-10 09:18:01 +00:00
201 lines
7.2 KiB
C++
201 lines
7.2 KiB
C++
#include "Project/Action/ActionFlagCtrl.h"
|
|
|
|
#include "Library/Base/StringUtil.h"
|
|
#include "Library/HitSensor/HitSensorKeeper.h"
|
|
#include "Library/LiveActor/ActorClippingFunction.h"
|
|
#include "Library/LiveActor/ActorCollisionFunction.h"
|
|
#include "Library/LiveActor/ActorFlagFunction.h"
|
|
#include "Library/LiveActor/ActorModelFunction.h"
|
|
#include "Library/LiveActor/ActorResourceFunction.h"
|
|
#include "Library/LiveActor/ActorSensorUtil.h"
|
|
#include "Library/LiveActor/LiveActor.h"
|
|
#include "Library/Yaml/ByamlIter.h"
|
|
#include "Library/Yaml/ByamlUtil.h"
|
|
#include "Project/Action/InitResourceDataActionAnim.h"
|
|
#include "Project/HitSensor/HitSensor.h"
|
|
|
|
namespace al {
|
|
ActionSensorCtrlInfo::ActionSensorCtrlInfo() = default;
|
|
ActionFlagCtrlInfo::ActionFlagCtrlInfo() = default;
|
|
|
|
ActionFlagCtrl::ActionFlagCtrl(LiveActor* actor, const char* name)
|
|
: mParentActor(actor), mArchiveName(createStringIfInStack(name)) {}
|
|
|
|
ActionFlagCtrl* ActionFlagCtrl::tryCreate(LiveActor* actor, const char* name) {
|
|
if (!isExistModelResource(actor))
|
|
return nullptr;
|
|
|
|
sead::FixedSafeString<128> initFileName;
|
|
if (!tryGetActorInitFileName(&initFileName, actor, "ActionFlagCtrl", name))
|
|
createFileNameBySuffix(&initFileName, "ActionFlagCtrl", name);
|
|
|
|
if (!isExistModelResourceYaml(actor, initFileName.cstr(), nullptr))
|
|
return nullptr;
|
|
|
|
return new ActionFlagCtrl(actor, name);
|
|
}
|
|
|
|
inline CtrlFlag getCtrlFlagByKey(ByamlIter iter, const char* name) {
|
|
bool isValid = false;
|
|
if (!iter.tryGetBoolByKey(&isValid, name))
|
|
return CtrlFlag::NotFound;
|
|
|
|
return isValid ? CtrlFlag::ValidOn : CtrlFlag::ValidOff;
|
|
}
|
|
|
|
void ActionFlagCtrl::initPost() {
|
|
mHitSensorKeeper = mParentActor->getHitSensorKeeper();
|
|
|
|
sead::FixedSafeString<128> initFileName;
|
|
tryGetActorInitFileName(&initFileName, mParentActor, "ActionFlagCtrl", mArchiveName);
|
|
|
|
ByamlIter fileIter;
|
|
tryGetActorInitFileIter(&fileIter, mParentActor, initFileName.cstr(), mArchiveName);
|
|
|
|
mInfoCount = fileIter.getSize();
|
|
mCtrlInfoArray = new ActionFlagCtrlInfo*[mInfoCount];
|
|
for (s32 i = 0; i < mInfoCount; i++) {
|
|
ByamlIter iter;
|
|
fileIter.tryGetIterByIndex(&iter, i);
|
|
ActionFlagCtrlInfo* flagCtrlInfo = new ActionFlagCtrlInfo();
|
|
mCtrlInfoArray[i] = flagCtrlInfo;
|
|
|
|
iter.tryGetStringByKey(&flagCtrlInfo->actionName, "ActionName");
|
|
|
|
flagCtrlInfo->ctrlFlags = new CtrlFlag[5];
|
|
flagCtrlInfo->ctrlFlags[0] = getCtrlFlagByKey(iter, "ShowModel");
|
|
flagCtrlInfo->ctrlFlags[1] = getCtrlFlagByKey(iter, "CollisionParts");
|
|
flagCtrlInfo->ctrlFlags[2] = getCtrlFlagByKey(iter, "Collider");
|
|
flagCtrlInfo->ctrlFlags[3] = getCtrlFlagByKey(iter, "ClippingOff");
|
|
flagCtrlInfo->ctrlFlags[4] = getCtrlFlagByKey(iter, "FaceCtrl");
|
|
|
|
ByamlIter sensorListIter;
|
|
if (iter.tryGetIterByKey(&sensorListIter, "SensorList") && mHitSensorKeeper) {
|
|
flagCtrlInfo->sensorCtrlInfoArray =
|
|
new ActionSensorCtrlInfo[mHitSensorKeeper->getSensorNum()];
|
|
|
|
for (s32 j = 0; j < mHitSensorKeeper->getSensorNum(); j++) {
|
|
ActionSensorCtrlInfo* sensorInfoArray = flagCtrlInfo->sensorCtrlInfoArray;
|
|
sensorInfoArray[j].name = mHitSensorKeeper->getSensor(j)->getName();
|
|
|
|
ByamlIter sensorIter;
|
|
if (sensorListIter.tryGetIterByKey(&sensorIter, sensorInfoArray[j].name)) {
|
|
sensorInfoArray[j].state = getCtrlFlagByKey(sensorIter, "State");
|
|
tryGetByamlS16(&sensorInfoArray[j].startFrame, sensorIter, "StartFrame");
|
|
tryGetByamlS16(&sensorInfoArray[j].endFrame, sensorIter, "EndFrame");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ActionFlagCtrl::start(const char* name) {
|
|
mCurrentCtrlInfo = findFlagInfo(name);
|
|
mIsUpdateNeeded = false;
|
|
if (!mCurrentCtrlInfo)
|
|
return;
|
|
|
|
startCtrlFlag();
|
|
startCtrlSensor();
|
|
}
|
|
|
|
ActionFlagCtrlInfo* ActionFlagCtrl::findFlagInfo(const char* name) const {
|
|
for (s32 i = 0; i < mInfoCount; i++) {
|
|
ActionFlagCtrlInfo* flagInfo = mCtrlInfoArray[i];
|
|
if (isEqualStringCase(flagInfo->actionName, name))
|
|
return flagInfo;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// NON_MATCHING: Wrong compiler optimization https://decomp.me/scratch/3VkWo
|
|
void ActionFlagCtrl::startCtrlFlag() {
|
|
if (isFlagValidOn(0, !isHideModel(mParentActor)))
|
|
showModel(mParentActor);
|
|
else if (isFlagValidOff(0, !isHideModel(mParentActor)))
|
|
hideModel(mParentActor);
|
|
|
|
if (mParentActor->getCollisionParts()) {
|
|
if (isFlagValidOn(1, isValidCollisionParts(mParentActor)))
|
|
validateCollisionParts(mParentActor);
|
|
else if (isFlagValidOff(1, isValidCollisionParts(mParentActor)))
|
|
invalidateCollisionParts(mParentActor);
|
|
}
|
|
|
|
if (mParentActor->getCollider()) {
|
|
if (isFlagValidOn(2, !isNoCollide(mParentActor)))
|
|
onCollide(mParentActor);
|
|
else if (isFlagValidOff(2, !isNoCollide(mParentActor)))
|
|
offCollide(mParentActor);
|
|
}
|
|
|
|
if (isFlagValidOn(3, isInvalidClipping(mParentActor)))
|
|
invalidateClipping(mParentActor);
|
|
else if (isFlagValidOff(3, isInvalidClipping(mParentActor)))
|
|
validateClipping(mParentActor);
|
|
}
|
|
|
|
void ActionFlagCtrl::startCtrlSensor() {
|
|
if (!mHitSensorKeeper)
|
|
return;
|
|
|
|
for (s32 i = 0; i < mHitSensorKeeper->getSensorNum(); i++) {
|
|
ActionSensorCtrlInfo* sensor = mCurrentCtrlInfo->sensorCtrlInfoArray;
|
|
if (sensor[i].startFrame > 0) {
|
|
mIsUpdateNeeded = true;
|
|
continue;
|
|
}
|
|
|
|
if (sensor[i].endFrame > 0)
|
|
mIsUpdateNeeded = true;
|
|
|
|
switch (sensor[i].state) {
|
|
case CtrlFlag::ValidOn:
|
|
validateHitSensor(mParentActor, sensor[i].name);
|
|
break;
|
|
case CtrlFlag::ValidOff:
|
|
invalidateHitSensor(mParentActor, sensor[i].name);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ActionFlagCtrl::update(f32 frame, f32 frameRateMax, f32 frameRate, bool isStop) {
|
|
if (!mCurrentCtrlInfo || !mIsUpdateNeeded)
|
|
return;
|
|
if (!mHitSensorKeeper)
|
|
return;
|
|
|
|
updateCtrlSensor(frame, frameRateMax, frameRate, isStop);
|
|
}
|
|
|
|
void ActionFlagCtrl::updateCtrlSensor(f32 frame, f32 frameRateMax, f32 frameRate, bool isStop) {
|
|
for (s32 i = 0; i < mHitSensorKeeper->getSensorNum(); i++) {
|
|
ActionSensorCtrlInfo* ctrlInfo = mCurrentCtrlInfo->sensorCtrlInfoArray;
|
|
|
|
f32 startFrame = ctrlInfo[i].startFrame;
|
|
if (startFrame > 0 &&
|
|
alAnimFunction::checkPass(frame, frameRateMax, frameRate, isStop, startFrame))
|
|
validateHitSensor(mParentActor, ctrlInfo[i].name);
|
|
|
|
f32 endFrame = ctrlInfo[i].endFrame;
|
|
if (endFrame > 0 &&
|
|
alAnimFunction::checkPass(frame, frameRateMax, frameRate, isStop, endFrame))
|
|
invalidateHitSensor(mParentActor, ctrlInfo[i].name);
|
|
}
|
|
}
|
|
|
|
bool ActionFlagCtrl::isFlagValidOn(s32 index, bool isEnabled) const {
|
|
return mCurrentCtrlInfo && mCurrentCtrlInfo->ctrlFlags[index] == CtrlFlag::ValidOn &&
|
|
!isEnabled;
|
|
}
|
|
|
|
bool ActionFlagCtrl::isFlagValidOff(s32 index, bool isEnabled) const {
|
|
return mCurrentCtrlInfo && mCurrentCtrlInfo->ctrlFlags[index] == CtrlFlag::ValidOff &&
|
|
isEnabled;
|
|
}
|
|
|
|
} // namespace al
|