mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-04-23 09:04:21 +00:00
1041 lines
39 KiB
C++
1041 lines
39 KiB
C++
#include "Library/LiveActor/ActorInitUtil.h"
|
|
|
|
#include <math/seadBoundBox.h>
|
|
#include <nn/g3d/ModelObj.h>
|
|
|
|
#include "Library/Action/ActorActionKeeper.h"
|
|
#include "Library/Base/HashCodeUtil.h"
|
|
#include "Library/Base/Macros.h"
|
|
#include "Library/Base/StringUtil.h"
|
|
#include "Library/Camera/CameraDirector.h"
|
|
#include "Library/Draw/GraphicsQualityController.h"
|
|
#include "Library/Draw/GraphicsSystemInfo.h"
|
|
#include "Library/Effect/EffectSystemInfo.h"
|
|
#include "Library/Effect/PartsEffectGroup.h"
|
|
#include "Library/Factory/Factory.h"
|
|
#include "Library/HitSensor/HitSensorKeeper.h"
|
|
#include "Library/HitSensor/SensorFunction.h"
|
|
#include "Library/Light/ModelMaterialCategory.h"
|
|
#include "Library/LiveActor/ActorActionFunction.h"
|
|
#include "Library/LiveActor/ActorAnimFunction.h"
|
|
#include "Library/LiveActor/ActorClippingFunction.h"
|
|
#include "Library/LiveActor/ActorCollisionFunction.h"
|
|
#include "Library/LiveActor/ActorFactory.h"
|
|
#include "Library/LiveActor/ActorFlagFunction.h"
|
|
#include "Library/LiveActor/ActorInitFunction.h"
|
|
#include "Library/LiveActor/ActorInitInfo.h"
|
|
#include "Library/LiveActor/ActorModelFunction.h"
|
|
#include "Library/LiveActor/ActorPoseKeeper.h"
|
|
#include "Library/LiveActor/ActorPoseUtil.h"
|
|
#include "Library/LiveActor/ActorResourceFunction.h"
|
|
#include "Library/LiveActor/ActorSensorFunction.h"
|
|
#include "Library/LiveActor/ActorSensorUtil.h"
|
|
#include "Library/LiveActor/LiveActor.h"
|
|
#include "Library/LiveActor/LiveActorGroup.h"
|
|
#include "Library/Model/ModelKeeper.h"
|
|
#include "Library/Model/ModelLodCtrl.h"
|
|
#include "Library/Model/ModelOcclusionQuery.h"
|
|
#include "Library/Nerve/NerveAction.h"
|
|
#include "Library/Nerve/NerveActionCtrl.h"
|
|
#include "Library/Nerve/NerveKeeper.h"
|
|
#include "Library/Obj/ActorDitherAnimator.h"
|
|
#include "Library/Obj/FarDistanceDitherAnimator.h"
|
|
#include "Library/Placement/PlacementFunction.h"
|
|
#include "Library/Placement/PlacementInfo.h"
|
|
#include "Library/Resource/ActorResource.h"
|
|
#include "Library/Resource/Resource.h"
|
|
#include "Library/Resource/ResourceFunction.h"
|
|
#include "Library/Se/SeFunction.h"
|
|
#include "Library/Shadow/ActorShadowUtil.h"
|
|
#include "Library/Stage/StageSwitchUtil.h"
|
|
#include "Library/Thread/FunctorV0M.h"
|
|
#include "Library/Yaml/ByamlIter.h"
|
|
#include "Library/Yaml/ByamlUtil.h"
|
|
#include "Project/HitSensor/HitSensor.h"
|
|
#include "Project/Item/ActorScoreKeeper.h"
|
|
|
|
namespace al {
|
|
|
|
using PoseKeeperCreatorFunction = void (*)(LiveActor*);
|
|
|
|
const NameToCreator<PoseKeeperCreatorFunction> gActorPoseTable[] = {
|
|
{"TRSV", initActorPoseTRSV}, {"TRMSV", initActorPoseTRMSV}, {"TRGMSV", initActorPoseTRGMSV},
|
|
{"TFSV", initActorPoseTFSV}, {"TFUSV", initActorPoseTFUSV}, {"TFGSV", initActorPoseTFGSV},
|
|
{"TQSV", initActorPoseTQSV}, {"TQGSV", initActorPoseTQGSV}, {"TQGMSV", initActorPoseTQGMSV},
|
|
};
|
|
|
|
void initActor(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
initActorSuffix(actor, initInfo, nullptr);
|
|
}
|
|
|
|
ALWAYS_INLINE bool initActorPoseKeeper(const char* pose, LiveActor* actor) {
|
|
if (!pose)
|
|
return false;
|
|
s32 poseId = -1;
|
|
for (s32 i = 0; i < 9; i++) {
|
|
if (isEqualString(gActorPoseTable[i].name, pose)) {
|
|
poseId = i;
|
|
break;
|
|
}
|
|
}
|
|
if (poseId != -1) {
|
|
gActorPoseTable[poseId].creationFunction(actor);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorPose(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initPose;
|
|
if (!tryGetActorInitFileIter(&initPose, modelRes, "InitPose", suffix))
|
|
return;
|
|
|
|
const char* pose = nullptr;
|
|
if (!initPose.tryGetStringByKey(&pose, "Pose"))
|
|
return;
|
|
|
|
if (!initActorPoseKeeper(pose, actor))
|
|
return;
|
|
|
|
if (isEqualString(pose, "TFUSV") && tryGetByamlKeyBoolOrFalse(initPose, "IsFrontUp"))
|
|
((ActorPoseKeeperTFUSV*)actor->getPoseKeeper())->setFrontUp(true);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorScale(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initScale;
|
|
if (!tryGetActorInitFileIter(&initScale, modelRes, "InitScale", suffix))
|
|
return;
|
|
|
|
sead::Vector3f scale = {1.0f, 1.0f, 1.0f};
|
|
if (!tryGetByamlScale(&scale, initScale, "Scale"))
|
|
return;
|
|
|
|
const sead::Vector3f& prevScale = getScale(actor);
|
|
scale.x = scale.x * prevScale.x;
|
|
scale.y = scale.y * prevScale.y;
|
|
scale.z = scale.z * prevScale.z;
|
|
setScale(actor, scale);
|
|
}
|
|
|
|
ALWAYS_INLINE ModelLodCtrl* initActorModelLodCtrl(LiveActor* actor, Resource* modelRes,
|
|
const char* suffix) {
|
|
ByamlIter initLod;
|
|
if (!tryGetActorInitFileIter(&initLod, modelRes, "InitLod", suffix))
|
|
return nullptr;
|
|
|
|
sead::BoundBox3f modelBoundingBox;
|
|
s32 lodModelCount = 5;
|
|
if (isExistModel(actor)) {
|
|
lodModelCount = getLodModelCount(actor);
|
|
calcModelBoundingBox(&modelBoundingBox, actor);
|
|
}
|
|
|
|
ModelLodCtrl* modelLodCtrl = new ModelLodCtrl{
|
|
actor,
|
|
getTransPtr(actor),
|
|
actor->getBaseMtx(),
|
|
getScalePtr(actor),
|
|
modelBoundingBox,
|
|
lodModelCount,
|
|
};
|
|
modelLodCtrl->init(initLod);
|
|
|
|
return modelLodCtrl;
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorModel(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, ActorResource* actorResource,
|
|
const char* suffix) {
|
|
ByamlIter initModel;
|
|
if (!tryGetActorInitFileIter(&initModel, modelRes, "InitModel", suffix))
|
|
return;
|
|
|
|
s32 blendAnimMax = 1;
|
|
initModel.tryGetIntByKey(&blendAnimMax, "BlendAnimMax");
|
|
const char* displayRootJointName = nullptr;
|
|
initModel.tryGetStringByKey(&displayRootJointName, "DisplayRootJointName");
|
|
|
|
initActorModelKeeper(actor, initInfo, actorResource, blendAnimMax);
|
|
if (displayRootJointName)
|
|
actor->getModelKeeper()->setDisplayRootJointMtxPtr(
|
|
getJointMtxPtr(actor, displayRootJointName));
|
|
|
|
bool isCreateUniqShader = false;
|
|
initModel.tryGetBoolByKey(&isCreateUniqShader, "IsCreateUniqShader");
|
|
if (isCreateUniqShader)
|
|
createUniqueShader(actor);
|
|
|
|
s32 partialAnimSlotNum = 0;
|
|
initModel.tryGetIntByKey(&partialAnimSlotNum, "PartialAnimSlotNum");
|
|
s32 partialAnimGroupNum = partialAnimSlotNum;
|
|
initModel.tryGetIntByKey(&partialAnimGroupNum, "PartialAnimGroupNum");
|
|
s32 partialAnimPartsListBufferSize = 16;
|
|
initModel.tryGetIntByKey(&partialAnimPartsListBufferSize, "PartialAnimPartsListBufferSize");
|
|
if (partialAnimGroupNum >= 1)
|
|
initPartialSklAnim(actor, partialAnimSlotNum, partialAnimGroupNum,
|
|
partialAnimPartsListBufferSize);
|
|
|
|
bool isFixedModel = false;
|
|
initModel.tryGetBoolByKey(&isFixedModel, "IsFixedModel");
|
|
if (isFixedModel)
|
|
setFixedModelFlag(actor);
|
|
|
|
bool isIgnoreUpdateOnDrawClipping = false;
|
|
initModel.tryGetBoolByKey(&isIgnoreUpdateOnDrawClipping, "IsIgnoreUpdateOnDrawClipping");
|
|
if (isIgnoreUpdateOnDrawClipping)
|
|
setIgnoreUpdateDrawClipping(actor, true);
|
|
|
|
ModelKeeper* modelKeeper = actor->getModelKeeper();
|
|
|
|
ModelLodCtrl* modelLodCtrl = initActorModelLodCtrl(actor, modelRes, suffix);
|
|
modelKeeper->setModelLodCtrl(modelLodCtrl);
|
|
if (modelLodCtrl)
|
|
initInfo.actorSceneInfo.graphicsSystemInfo->getModelLodAllCtrl()->registerLodCtrl(
|
|
modelLodCtrl);
|
|
|
|
MaterialCategoryKeeper* materialCategoryKeeper =
|
|
initInfo.actorSceneInfo.graphicsSystemInfo->getMaterialCategoryKeeper();
|
|
ModelMaterialCategory::tryCreate(modelKeeper->getModelCtrl(), modelRes, suffix,
|
|
materialCategoryKeeper);
|
|
|
|
GraphicsQualityInfo* graphicsQualityInfo =
|
|
initInfo.actorSceneInfo.graphicsSystemInfo->getGraphicsQualityController()
|
|
->getGraphicsQualityInfo();
|
|
modelKeeper->getModelCtrl()->setGraphicsQualityInfo(graphicsQualityInfo);
|
|
|
|
ModelOcclusionQuery* modelOcclusionQuery =
|
|
ModelOcclusionQuery::tryCreate(actor, modelRes, suffix);
|
|
modelKeeper->getModelCtrl()->setModelOcclusionQuery(modelOcclusionQuery);
|
|
|
|
bool isCalcViewCore1 = false;
|
|
initModel.tryGetBoolByKey(&isCalcViewCore1, "IsCalcViewCore1");
|
|
if (isCalcViewCore1)
|
|
modelKeeper->getModelCtrl()->setCalcViewCore(1);
|
|
|
|
bool isCalcViewCore2 = false;
|
|
initModel.tryGetBoolByKey(&isCalcViewCore2, "IsCalcViewCore2");
|
|
if (isCalcViewCore2)
|
|
modelKeeper->getModelCtrl()->setCalcViewCore(2);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorExecutor(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initExecutor;
|
|
if (!tryGetActorInitFileIter(&initExecutor, modelRes, "InitExecutor", suffix)) {
|
|
ModelKeeper* modelKeeper = actor->getModelKeeper();
|
|
if (modelKeeper && modelKeeper->getModelCtrl()->getModelObj()->GetNumShapes())
|
|
initExecutorModelUpdate(actor, initInfo);
|
|
return;
|
|
}
|
|
|
|
const char* updaterCategoryName = nullptr;
|
|
const char* drawerCategoryName = nullptr;
|
|
|
|
ByamlIter iter;
|
|
if (initExecutor.tryGetIterByKey(&iter, "Updater") && iter.isTypeArray()) {
|
|
ByamlIter entry;
|
|
s32 index = 0;
|
|
while (iter.tryGetIterByIndex(&entry, index)) {
|
|
entry.tryGetStringByKey(&updaterCategoryName, "CategoryName");
|
|
initExecutorUpdate(actor, initInfo, updaterCategoryName);
|
|
index++;
|
|
}
|
|
}
|
|
|
|
if (initExecutor.tryGetIterByKey(&iter, "Drawer")) {
|
|
ModelKeeper* modelKeeper = actor->getModelKeeper();
|
|
if (modelKeeper && modelKeeper->getModelCtrl()->getModelObj()->GetNumShapes())
|
|
initExecutorModelUpdate(actor, initInfo);
|
|
|
|
if (iter.isTypeArray()) {
|
|
ByamlIter entry;
|
|
s32 index = 0;
|
|
while (iter.tryGetIterByIndex(&entry, index)) {
|
|
entry.tryGetStringByKey(&drawerCategoryName, "CategoryName");
|
|
initExecutorDraw(actor, initInfo, drawerCategoryName);
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorSensor(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initSensor;
|
|
if (!tryGetActorInitFileIter(&initSensor, modelRes, "InitSensor", suffix))
|
|
return;
|
|
|
|
s32 numSensors = initSensor.getSize();
|
|
if (numSensors <= 0)
|
|
return;
|
|
|
|
actor->initHitSensor(numSensors);
|
|
for (s32 i = 0; i < numSensors; i++) {
|
|
ByamlIter sensor;
|
|
if (!initSensor.tryGetIterByIndex(&sensor, i))
|
|
continue;
|
|
|
|
const char* sensorName = nullptr;
|
|
if (!sensor.tryGetStringByKey(&sensorName, "Name"))
|
|
continue;
|
|
|
|
const char* sensorType = nullptr;
|
|
if (!sensor.tryGetStringByKey(&sensorType, "Type"))
|
|
continue;
|
|
|
|
f32 radius = 0.0f;
|
|
sensor.tryGetFloatByKey(&radius, "Radius");
|
|
|
|
s32 maxCount = 8;
|
|
sensor.tryGetIntByKey(&maxCount, "MaxCount");
|
|
|
|
sead::Vector3f offset = sead::Vector3f::zero;
|
|
tryGetByamlV3f(&offset, sensor);
|
|
|
|
HitSensorType type = alSensorFunction::findSensorTypeByName(sensorType);
|
|
if (type == HitSensorType::CollisionParts)
|
|
maxCount = 0;
|
|
|
|
addHitSensor(actor, initInfo, sensorName, (u32)type, radius, maxCount, offset);
|
|
|
|
const char* joint = nullptr;
|
|
sensor.tryGetStringByKey(&joint, "Joint");
|
|
if (joint)
|
|
setHitSensorJointMtx(actor, sensorName, joint);
|
|
}
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorCollision(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initCollision;
|
|
if (!tryGetActorInitFileIter(&initCollision, modelRes, "InitCollision", suffix))
|
|
return;
|
|
|
|
const char* name = nullptr;
|
|
initCollision.tryGetStringByKey(&name, "Name");
|
|
StringTmp<256> unused;
|
|
|
|
if (!name)
|
|
name = getBaseName(modelRes->getArchiveName());
|
|
|
|
const char* sensorName = nullptr;
|
|
HitSensor* sensor = nullptr;
|
|
if (initCollision.tryGetStringByKey(&sensorName, "Sensor"))
|
|
sensor = getHitSensor(actor, sensorName);
|
|
|
|
const char* joint = nullptr;
|
|
initCollision.tryGetStringByKey(&joint, "Joint");
|
|
sead::Matrix34f* jointMtx = nullptr;
|
|
if (joint)
|
|
jointMtx = getJointMtxPtr(actor, joint);
|
|
|
|
initActorCollisionWithResource(actor, modelRes, name, sensor, jointMtx, suffix);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorCollider(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initCollider;
|
|
if (!tryGetActorInitFileIter(&initCollider, modelRes, "InitCollider", suffix))
|
|
return;
|
|
|
|
f32 radius = 0.0f;
|
|
initCollider.tryGetFloatByKey(&radius, "Radius");
|
|
|
|
u32 planeNum = 0;
|
|
initCollider.tryGetUIntByKey(&planeNum, "PlaneNum");
|
|
|
|
sead::Vector3f offset = sead::Vector3f::zero;
|
|
tryGetByamlV3f(&offset, initCollider);
|
|
|
|
actor->initCollider(radius, offset.y, planeNum);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorEffect(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initEffect;
|
|
if (!tryGetActorInitFileIter(&initEffect, modelRes, "InitEffect", suffix))
|
|
return;
|
|
|
|
const char* name = nullptr;
|
|
if (!initEffect.tryGetStringByKey(&name, "Name"))
|
|
return;
|
|
|
|
initActorEffectKeeper(actor, initInfo, name);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorSound(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initSound;
|
|
const char* seName = nullptr;
|
|
const char* bgmName = nullptr;
|
|
if (tryGetActorInitFileIter(&initSound, modelRes, "InitSound", suffix)) {
|
|
initSound.tryGetStringByKey(&seName, "Name");
|
|
} else if (tryGetActorInitFileIter(&initSound, modelRes, "InitAudio", suffix)) {
|
|
initSound.tryGetStringByKey(&seName, "SeUserName");
|
|
initSound.tryGetStringByKey(&bgmName, "BgmUserName");
|
|
} else
|
|
return;
|
|
|
|
if (seName)
|
|
initActorSeKeeper(actor, initInfo, seName);
|
|
if (initSound.isExistKey("BgmUserName"))
|
|
initActorBgmKeeper(actor, initInfo, bgmName);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorRail(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
if (isExistRail(initInfo, "Rail"))
|
|
actor->initRailKeeper(initInfo, "Rail");
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorGroupClipping(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
const ByamlIter& initClipping) {
|
|
if (initClipping.isExistKey("NoGroupClipping"))
|
|
return;
|
|
|
|
ByamlIter groupClipping;
|
|
if (!initClipping.tryGetIterByKey(&groupClipping, "GroupClipping"))
|
|
return;
|
|
|
|
initGroupClipping(actor, initInfo);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorClipping(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initClipping;
|
|
if (!tryGetActorInitFileIter(&initClipping, modelRes, "InitClipping", suffix))
|
|
return;
|
|
initActorClipping(actor, initInfo);
|
|
|
|
bool invalidate = false;
|
|
initClipping.tryGetBoolByKey(&invalidate, "Invalidate");
|
|
if (invalidate)
|
|
invalidateClipping(actor);
|
|
|
|
f32 radius = 0.0f;
|
|
if (initClipping.tryGetFloatByKey(&radius, "Radius")) {
|
|
setClippingInfo(actor, radius, nullptr);
|
|
} else if (actor->getModelKeeper()) {
|
|
const sead::Vector3f& scale = getScale(actor);
|
|
f32 maxXY = sead::Mathf::max(sead::Mathf::abs(scale.x), sead::Mathf::abs(scale.y));
|
|
f32 maxXYZ = sead::Mathf::max(maxXY, sead::Mathf::abs(scale.z));
|
|
|
|
setClippingInfo(actor, calcModelBoundingSphereRadius(actor) * maxXYZ, nullptr);
|
|
}
|
|
|
|
sead::BoundBox3f obb;
|
|
if (tryGetByamlBox3f(&obb, initClipping, "Obb"))
|
|
setClippingObb(actor, obb);
|
|
|
|
f32 nearClipDistance = 0.0f;
|
|
if (initClipping.tryGetFloatByKey(&nearClipDistance, "NearClipDistance"))
|
|
setClippingNearDistance(actor, nearClipDistance);
|
|
|
|
initActorGroupClipping(actor, initInfo, initClipping);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorShadowMask(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
bool usingDepthShadow = false;
|
|
tryGetArg(&usingDepthShadow, initInfo, "UsingDepthShadow");
|
|
initDepthShadowMapCtrl(actor, modelRes, initInfo, suffix);
|
|
|
|
ByamlIter initShadowMask;
|
|
if (!tryGetActorInitFileIter(&initShadowMask, modelRes, "InitShadowMask", suffix))
|
|
return;
|
|
|
|
initShadowMaskCtrl(actor, initInfo, initShadowMask, "InitShadowMask");
|
|
if (usingDepthShadow)
|
|
invalidateShadowMaskIntensityAll(actor);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorFlag(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initFlag;
|
|
if (!tryGetActorInitFileIter(&initFlag, modelRes, "InitFlag", suffix))
|
|
return;
|
|
|
|
ByamlIter tmp;
|
|
if (initFlag.tryGetIterByKey(&tmp, "MaterialCode"))
|
|
validateMaterialCode(actor);
|
|
if (initFlag.tryGetIterByKey(&tmp, "UpdatePuddleMaterial"))
|
|
validatePuddleMaterial(actor);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorItem(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initItem;
|
|
if (!tryGetActorInitFileIter(&initItem, modelRes, "InitItem", suffix))
|
|
return;
|
|
|
|
initActorItemKeeper(actor, initInfo, initItem);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorScore(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, const char* suffix) {
|
|
ByamlIter initScore;
|
|
if (!tryGetActorInitFileIter(&initScore, modelRes, "InitScore", suffix))
|
|
return;
|
|
|
|
actor->initScoreKeeper();
|
|
actor->getActorScoreKeeper()->init(initScore);
|
|
}
|
|
|
|
ALWAYS_INLINE void initActorAction(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
Resource* modelRes, ActorResource* actorResource,
|
|
const char* suffix) {
|
|
const char* archiveName = actorResource->getModelRes()->getArchiveName();
|
|
initActorActionKeeper(actor, actorResource, archiveName, suffix);
|
|
|
|
if (!actor->getModelKeeper())
|
|
return;
|
|
|
|
if (!tryStartAction(actor, archiveName)) {
|
|
ActorActionKeeper* actionKeeper = actor->getActorActionKeeper();
|
|
if (actionKeeper)
|
|
actionKeeper->startAction(archiveName);
|
|
}
|
|
|
|
ModelKeeper* modelKeeper = actor->getModelKeeper();
|
|
if (!modelKeeper)
|
|
return;
|
|
|
|
DitherAnimator* ditherAnimator = ActorDitherAnimator::tryCreate(actor, modelRes, suffix);
|
|
if (ditherAnimator) {
|
|
modelKeeper->setDitherAnimator(ditherAnimator);
|
|
return;
|
|
}
|
|
|
|
ditherAnimator = FarDistanceDitherAnimator::tryCreate(actor, modelRes, suffix);
|
|
if (ditherAnimator)
|
|
modelKeeper->setDitherAnimator(ditherAnimator);
|
|
}
|
|
|
|
void initActorImpl(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
const sead::SafeString& folderName, const sead::SafeString& fileName,
|
|
const char* suffix) {
|
|
StringTmp<256> path = {"%s/%s", folderName.cstr(), fileName.cstr()};
|
|
ActorResource* actorResource =
|
|
findOrCreateActorResource(initInfo.actorResourceHolder, path.cstr(), suffix);
|
|
Resource* modelRes = actorResource->getModelRes();
|
|
if (!actor->getSceneInfo())
|
|
initActorSceneInfo(actor, initInfo);
|
|
|
|
initActorPose(actor, initInfo, modelRes, suffix);
|
|
initActorSRT(actor, initInfo);
|
|
initActorScale(actor, initInfo, modelRes, suffix);
|
|
initActorModel(actor, initInfo, actorResource->getModelRes(), actorResource, suffix);
|
|
initActorPrePassLightKeeper(actor, modelRes, initInfo, suffix);
|
|
initActorExecutor(actor, initInfo, modelRes, suffix);
|
|
initActorSensor(actor, initInfo, modelRes, suffix);
|
|
initActorCollision(actor, initInfo, modelRes, suffix);
|
|
initActorCollider(actor, initInfo, modelRes, suffix);
|
|
initActorEffect(actor, initInfo, modelRes, suffix);
|
|
initActorSound(actor, initInfo, modelRes, suffix);
|
|
initActorRail(actor, initInfo);
|
|
initStageSwitch(actor, initInfo);
|
|
initActorClipping(actor, initInfo, modelRes, suffix);
|
|
initActorOcclusionKeeper(actor, modelRes, initInfo, suffix);
|
|
initActorShadowMask(actor, initInfo, modelRes, suffix);
|
|
initActorFlag(actor, initInfo, modelRes, suffix);
|
|
initActorItem(actor, initInfo, modelRes, suffix);
|
|
initActorScore(actor, initInfo, modelRes, suffix);
|
|
initScreenPointKeeper(actor, modelRes, initInfo, suffix);
|
|
initHitReactionKeeper(actor, modelRes, suffix);
|
|
initActorParamHolder(actor, modelRes, suffix);
|
|
initActorAction(actor, initInfo, modelRes, actorResource, suffix);
|
|
|
|
if (actor->getNerveKeeper() && actor->getNerveKeeper()->getActionCtrl())
|
|
resetNerveActionForInit(actor);
|
|
|
|
if (!actor->getSubActorKeeper())
|
|
initSubActorKeeper(actor, initInfo, suffix, 0);
|
|
}
|
|
|
|
void initActorSuffix(LiveActor* actor, const ActorInitInfo& initInfo, const char* suffix) {
|
|
const char* objName = nullptr;
|
|
tryGetObjectName(&objName, initInfo);
|
|
initActorImpl(actor, initInfo, "ObjectData", objName, suffix);
|
|
}
|
|
|
|
void initActorChangeModel(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
initActorChangeModelSuffix(actor, initInfo, nullptr);
|
|
}
|
|
|
|
inline const char* getModelName(const ActorInitInfo& initInfo) {
|
|
const char* name = nullptr;
|
|
if (alPlacementFunction::tryGetModelName(&name, initInfo))
|
|
return name;
|
|
else if (tryGetObjectName(&name, initInfo))
|
|
return name;
|
|
return nullptr;
|
|
}
|
|
|
|
void initActorChangeModelSuffix(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
const char* suffix) {
|
|
const char* file = getModelName(initInfo);
|
|
initActorImpl(actor, initInfo, "ObjectData", file, suffix);
|
|
}
|
|
|
|
void initActorWithArchiveName(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
const sead::SafeString& archiveName, const char* suffix) {
|
|
initChildActorWithArchiveNameWithPlacementInfo(actor, initInfo, archiveName, suffix);
|
|
}
|
|
|
|
void initChildActorWithArchiveNameWithPlacementInfo(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
const sead::SafeString& archiveName,
|
|
const char* suffix) {
|
|
initActorImpl(actor, initInfo, "ObjectData", archiveName.cstr(), suffix);
|
|
}
|
|
|
|
void initChildActorWithArchiveNameNoPlacementInfo(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
const sead::SafeString& archiveName,
|
|
const char* suffix) {
|
|
PlacementInfo placementInfo;
|
|
ActorInitInfo childInitInfo;
|
|
childInitInfo.initViewIdHost(&placementInfo, initInfo);
|
|
initActorImpl(actor, childInitInfo, "ObjectData", archiveName.cstr(), suffix);
|
|
}
|
|
|
|
LiveActor* createChildLinkSimpleActor(const char* actorName, const char* linkName,
|
|
const ActorInitInfo& initInfo, bool alive) {
|
|
ActorInitInfo childInitInfo;
|
|
PlacementInfo placementInfo;
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, linkName, 0);
|
|
childInitInfo.initViewIdSelf(&placementInfo, initInfo);
|
|
|
|
LiveActor* actor = new LiveActor(actorName);
|
|
initActor(actor, childInitInfo);
|
|
|
|
if (alive)
|
|
actor->makeActorAlive();
|
|
else
|
|
actor->makeActorDead();
|
|
return actor;
|
|
}
|
|
|
|
LiveActor* createChildLinkMapPartsActor(const char* actorName, const char* linkName,
|
|
const ActorInitInfo& initInfo, s32 linkIndex, bool alive) {
|
|
ActorInitInfo childInitInfo;
|
|
PlacementInfo placementInfo;
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, linkName, linkIndex);
|
|
childInitInfo.initViewIdSelf(&placementInfo, initInfo);
|
|
|
|
LiveActor* actor = new LiveActor(actorName);
|
|
initMapPartsActor(actor, childInitInfo, nullptr);
|
|
|
|
if (alive)
|
|
actor->makeActorAlive();
|
|
else
|
|
actor->makeActorDead();
|
|
return actor;
|
|
}
|
|
|
|
void initMapPartsActor(LiveActor* actor, const ActorInitInfo& initInfo, const char* suffix) {
|
|
const char* modelName;
|
|
StringTmp<256> fileName;
|
|
StringTmp<256> folderName;
|
|
|
|
const PlacementInfo& placementInfo = *initInfo.placementInfo;
|
|
modelName = nullptr;
|
|
if (alPlacementFunction::tryGetModelName(&modelName, placementInfo) &&
|
|
!isEqualString(modelName, "")) {
|
|
fileName.copy(modelName);
|
|
folderName.copy("ObjectData");
|
|
} else {
|
|
tryGetStringArg(&modelName, placementInfo, "UnitConfigName");
|
|
fileName.copy(modelName);
|
|
folderName.copy("ObjectData");
|
|
}
|
|
|
|
initActorImpl(actor, initInfo, folderName, fileName, suffix);
|
|
}
|
|
|
|
void initLinksActor(LiveActor* actor, const ActorInitInfo& initInfo, const char* suffix,
|
|
s32 linkIndex) {
|
|
ActorInitInfo childInitInfo;
|
|
PlacementInfo placementInfo;
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, suffix, linkIndex);
|
|
childInitInfo.initViewIdSelf(&placementInfo, initInfo);
|
|
actor->init(childInitInfo);
|
|
}
|
|
|
|
ActorInitInfo* createLinksPlayerActorInfo(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
s32 startPosNum = calcLinkChildNum(initInfo, "PlayerRestartPos");
|
|
ActorInitInfo* result = new ActorInitInfo();
|
|
if (startPosNum == 1) {
|
|
PlacementInfo* placementInfo = new PlacementInfo();
|
|
getLinksInfoByIndex(placementInfo, *initInfo.placementInfo, "PlayerRestartPos", 0);
|
|
result->initViewIdSelf(placementInfo, initInfo);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
const char* getLinksActorClassName(const ActorInitInfo& initInfo, const char* linkName,
|
|
s32 linkIndex) {
|
|
ActorInitInfo childInitInfo;
|
|
PlacementInfo placementInfo;
|
|
|
|
const char* className = nullptr;
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, linkName, linkIndex);
|
|
childInitInfo.initViewIdSelf(&placementInfo, initInfo);
|
|
getClassName(&className, childInitInfo);
|
|
return className;
|
|
}
|
|
|
|
const char* getLinksActorDisplayName(const ActorInitInfo& initInfo, const char* linkName,
|
|
s32 linkIndex) {
|
|
PlacementInfo placementInfo;
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, linkName, linkIndex);
|
|
const char* displayName = nullptr;
|
|
getDisplayName(&displayName, placementInfo);
|
|
return displayName;
|
|
}
|
|
|
|
const char* getLinksActorObjectName(const ActorInitInfo& initInfo, const char* linkName,
|
|
s32 linkIndex) {
|
|
PlacementInfo placementInfo;
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, linkName, linkIndex);
|
|
const char* objectName = nullptr;
|
|
getObjectName(&objectName, placementInfo);
|
|
return objectName;
|
|
}
|
|
|
|
void initCreateActorWithPlacementInfo(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
actor->init(initInfo);
|
|
}
|
|
|
|
void initCreateActorWithPlacementInfo(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
const PlacementInfo& placementInfo) {
|
|
ActorInitInfo childInitInfo;
|
|
childInitInfo.initViewIdSelf(&placementInfo, initInfo);
|
|
actor->init(childInitInfo);
|
|
}
|
|
|
|
void initCreateActorNoPlacementInfo(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
PlacementInfo placementInfo;
|
|
ActorInitInfo childInitInfo;
|
|
childInitInfo.initViewIdHost(&placementInfo, initInfo);
|
|
actor->init(childInitInfo);
|
|
}
|
|
|
|
void initCreateActorNoPlacementInfoNoViewId(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
PlacementInfo placementInfo;
|
|
ActorInitInfo childInitInfo;
|
|
childInitInfo.initNoViewId(&placementInfo, initInfo);
|
|
actor->init(childInitInfo);
|
|
}
|
|
|
|
ALWAYS_INLINE LiveActor* createActorFromFactory(const ActorInitInfo& childInitInfo,
|
|
const PlacementInfo* placementInfo) {
|
|
const ActorFactory* factory = childInitInfo.actorFactory;
|
|
|
|
const char* objectName = nullptr;
|
|
getObjectName(&objectName, childInitInfo);
|
|
const char* className = nullptr;
|
|
getClassName(&className, childInitInfo);
|
|
|
|
ActorCreatorFunction creationFunction = nullptr;
|
|
factory->getEntryIndex(&creationFunction, className);
|
|
if (!creationFunction)
|
|
return nullptr;
|
|
|
|
const char* displayName;
|
|
getDisplayName(&displayName, childInitInfo);
|
|
LiveActor* actor = (*creationFunction)(displayName);
|
|
actor->init(childInitInfo);
|
|
return actor;
|
|
}
|
|
|
|
LiveActor* createPlacementActorFromFactory(const ActorInitInfo& initInfo,
|
|
const PlacementInfo* placementInfo) {
|
|
ActorInitInfo childInitInfo;
|
|
childInitInfo.initViewIdSelf(placementInfo, initInfo);
|
|
return createActorFromFactory(childInitInfo, placementInfo);
|
|
}
|
|
|
|
LiveActor* createLinksActorFromFactory(const ActorInitInfo& initInfo, const char* linkName,
|
|
s32 linkNum) {
|
|
ActorInitInfo childInitInfo;
|
|
PlacementInfo placementInfo;
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, linkName, linkNum);
|
|
childInitInfo.initViewIdSelf(&placementInfo, initInfo);
|
|
return createActorFromFactory(childInitInfo, &placementInfo);
|
|
}
|
|
|
|
LiveActorGroup* createLinksActorGroupFromFactory(const ActorInitInfo& initInfo,
|
|
const char* linkName, const char* groupName) {
|
|
return tryCreateLinksActorGroupFromFactory(initInfo, linkName, groupName);
|
|
}
|
|
|
|
LiveActorGroup* tryCreateLinksActorGroupFromFactory(const ActorInitInfo& initInfo,
|
|
const char* linkName, const char* groupName) {
|
|
ActorInitInfo childInitInfo;
|
|
PlacementInfo placementInfo;
|
|
s32 linkChildNum = calcLinkChildNum(initInfo, linkName);
|
|
if (linkChildNum < 1)
|
|
return nullptr;
|
|
|
|
LiveActorGroup* group = new LiveActorGroup(groupName, linkChildNum);
|
|
for (s32 i = 0; i < linkChildNum; i++) {
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, linkName, i);
|
|
childInitInfo.initViewIdSelf(&placementInfo, initInfo);
|
|
group->registerActor(createActorFromFactory(childInitInfo, &placementInfo));
|
|
}
|
|
return group;
|
|
}
|
|
|
|
LiveActor* tryCreateLinksActorFromFactorySingle(const ActorInitInfo& initInfo,
|
|
const char* linkName) {
|
|
if (calcLinkChildNum(initInfo, linkName) < 1)
|
|
return nullptr;
|
|
return createLinksActorFromFactory(initInfo, linkName, 0);
|
|
}
|
|
|
|
void createAndRegisterLinksActorFromFactory(LiveActorGroup* group, const ActorInitInfo& initInfo,
|
|
const char* linkName) {
|
|
ActorInitInfo childInitInfo;
|
|
PlacementInfo placementInfo;
|
|
s32 linkChildNum = calcLinkChildNum(initInfo, linkName);
|
|
if (linkChildNum < 1)
|
|
return;
|
|
|
|
for (s32 i = 0; i < linkChildNum; i++) {
|
|
getLinksInfoByIndex(&placementInfo, *initInfo.placementInfo, linkName, i);
|
|
childInitInfo.initViewIdSelf(&placementInfo, initInfo);
|
|
group->registerActor(createActorFromFactory(childInitInfo, &placementInfo));
|
|
}
|
|
}
|
|
|
|
void makeMapPartsModelName(sead::BufferedSafeString* modelName, sead::BufferedSafeString* path,
|
|
const PlacementInfo& placementInfo) {
|
|
const char* archiveName = nullptr;
|
|
if (alPlacementFunction::tryGetModelName(&archiveName, placementInfo) &&
|
|
!isEqualString(archiveName, "")) {
|
|
modelName->copy(archiveName);
|
|
path->format("ObjectData/%s", archiveName);
|
|
} else {
|
|
tryGetStringArg(&archiveName, placementInfo, "UnitConfigName");
|
|
modelName->copy(archiveName);
|
|
path->format("ObjectData/%s", archiveName);
|
|
}
|
|
}
|
|
|
|
void makeMapPartsModelName(sead::BufferedSafeString* modelName, sead::BufferedSafeString* path,
|
|
const ActorInitInfo& initInfo) {
|
|
makeMapPartsModelName(modelName, path, *initInfo.placementInfo);
|
|
}
|
|
|
|
const char* tryGetMapPartsSuffix(const ActorInitInfo& initInfo, const char* suffix) {
|
|
StringTmp<64> name = {"InitActor%s", suffix};
|
|
if (!tryGetMapPartsResourceYaml(initInfo, name.cstr()))
|
|
return nullptr;
|
|
return suffix;
|
|
}
|
|
|
|
void initMapPartsActorWithArchiveName(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
const char* fileName, const char* suffix) {
|
|
return initActorImpl(actor, initInfo, "MapPartsData", fileName, suffix);
|
|
}
|
|
|
|
void initNerve(LiveActor* actor, const Nerve* nerve, s32 maxStates) {
|
|
actor->initNerveKeeper(new NerveKeeper(actor, nerve, maxStates));
|
|
}
|
|
|
|
void initNerveAction(LiveActor* actor, const char* actionName,
|
|
alNerveFunction::NerveActionCollector* collector, s32 maxStates) {
|
|
auto* nerveActionCtrl = new NerveActionCtrl(collector);
|
|
initNerve(actor, nerveActionCtrl->findNerve(actionName), maxStates);
|
|
actor->getNerveKeeper()->initNerveAction(nerveActionCtrl);
|
|
startNerveAction(actor, actionName);
|
|
}
|
|
|
|
bool trySyncStageSwitchAppear(LiveActor* actor) {
|
|
using LiveActorFunctor = FunctorV0M<LiveActor*, void (LiveActor::*)()>;
|
|
|
|
if (listenStageSwitchOnOffAppear(actor, LiveActorFunctor{actor, &LiveActor::appear},
|
|
LiveActorFunctor{actor, &LiveActor::kill})) {
|
|
actor->makeActorDead();
|
|
return true;
|
|
} else {
|
|
actor->makeActorAlive();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool trySyncStageSwitchKill(LiveActor* actor) {
|
|
using LiveActorFunctor = FunctorV0M<LiveActor*, void (LiveActor::*)()>;
|
|
|
|
bool result = listenStageSwitchOnOffKill(actor, LiveActorFunctor(actor, &LiveActor::kill),
|
|
LiveActorFunctor(actor, &LiveActor::appear));
|
|
actor->makeActorAlive();
|
|
|
|
return result;
|
|
}
|
|
|
|
bool trySyncStageSwitchAppearAndKill(LiveActor* actor) {
|
|
if (trySyncStageSwitchAppear(actor))
|
|
return true;
|
|
return trySyncStageSwitchKill(actor);
|
|
}
|
|
|
|
bool tryListenStageSwitchAppear(LiveActor* actor) {
|
|
using LiveActorFunctor = FunctorV0M<LiveActor*, void (LiveActor::*)()>;
|
|
|
|
if (listenStageSwitchOnAppear(actor, LiveActorFunctor{actor, &LiveActor::appear})) {
|
|
actor->makeActorDead();
|
|
return true;
|
|
} else {
|
|
actor->makeActorAlive();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool tryListenStageSwitchKill(LiveActor* actor) {
|
|
using LiveActorFunctor = FunctorV0M<LiveActor*, void (LiveActor::*)()>;
|
|
|
|
return listenStageSwitchOnKill(actor, LiveActorFunctor(actor, &LiveActor::kill));
|
|
}
|
|
|
|
void syncSensorScaleY(LiveActor* actor) {
|
|
f32 scaleY = getScale(actor).y;
|
|
for (s32 i = 0; i < actor->getHitSensorKeeper()->getSensorNum(); i++)
|
|
actor->getHitSensorKeeper()->getSensor(i)->scaleY(scaleY);
|
|
}
|
|
|
|
void syncSensorAndColliderScaleY(LiveActor* actor) {
|
|
syncSensorScaleY(actor);
|
|
f32 scaleY = getScale(actor).y;
|
|
setColliderRadius(actor, scaleY * getColliderRadius(actor));
|
|
setColliderOffsetY(actor, scaleY * getColliderOffsetY(actor));
|
|
}
|
|
|
|
void setMaterialCode(LiveActor* actor, const char* materialCode) {
|
|
if (actor->getEffectKeeper())
|
|
tryUpdateEffectMaterialCode(actor, materialCode);
|
|
if (isExistSeKeeper(actor))
|
|
tryUpdateSeMaterialCode(actor, materialCode);
|
|
}
|
|
|
|
void initMaterialCode(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
const char* materialCode = "";
|
|
if (tryGetStringArg(&materialCode, initInfo, "MaterialCode"))
|
|
setMaterialCode(actor, materialCode);
|
|
}
|
|
|
|
bool tryAddDisplayRotate(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
sead::Vector3f rotate = {0.0f, 0.0f, 0.0f};
|
|
if (!tryGetDisplayRotate(&rotate, initInfo))
|
|
return false;
|
|
|
|
sead::Matrix34f rotateMtx;
|
|
rotateMtx.makeR({sead::Mathf::deg2rad(rotate.x), sead::Mathf::deg2rad(rotate.y),
|
|
sead::Mathf::deg2rad(rotate.z)});
|
|
|
|
sead::Matrix34f origMtx = sead::Matrix34f::ident;
|
|
makeMtxRT(&origMtx, actor);
|
|
|
|
origMtx = origMtx * rotateMtx;
|
|
updatePoseMtx(actor, &origMtx);
|
|
return true;
|
|
}
|
|
|
|
bool tryAddDisplayOffset(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
sead::Vector3f offset = {0.0f, 0.0f, 0.0f};
|
|
if (!tryGetDisplayOffset(&offset, initInfo))
|
|
return false;
|
|
|
|
*getTransPtr(actor) += offset;
|
|
return true;
|
|
}
|
|
|
|
bool tryAddDisplayScale(LiveActor* actor, const ActorInitInfo& initInfo) {
|
|
sead::Vector3f scale = {0.0f, 0.0f, 0.0f};
|
|
if (!tryGetDisplayScale(&scale, initInfo))
|
|
return false;
|
|
|
|
setScaleX(actor, getScale(actor).x * scale.x);
|
|
setScaleY(actor, getScale(actor).y * scale.y);
|
|
setScaleZ(actor, getScale(actor).z * scale.z);
|
|
return true;
|
|
}
|
|
|
|
const PlacementInfo& getPlacementInfo(const ActorInitInfo& initInfo) {
|
|
return *initInfo.placementInfo;
|
|
}
|
|
|
|
const LayoutInitInfo& getLayoutInitInfo(const ActorInitInfo& initInfo) {
|
|
return *initInfo.layoutInitInfo;
|
|
}
|
|
|
|
AudioDirector* getAudioDirector(const ActorInitInfo& initInfo) {
|
|
return initInfo.audioDirector;
|
|
}
|
|
|
|
CollisionDirector* getCollisionDirectorFromInfo(const ActorInitInfo& initInfo) {
|
|
return initInfo.actorSceneInfo.collisionDirector;
|
|
}
|
|
|
|
const SceneCameraInfo* getSceneCameraInfoFromInfo(const ActorInitInfo& initInfo) {
|
|
return initInfo.actorSceneInfo.cameraDirector->getSceneCameraInfo();
|
|
}
|
|
|
|
GraphicsSystemInfo* getGraphicsSystemInfo(const ActorInitInfo& initInfo) {
|
|
return initInfo.actorSceneInfo.graphicsSystemInfo;
|
|
}
|
|
|
|
agl::DrawContext* getDrawContext(const ActorInitInfo& initInfo) {
|
|
return initInfo.actorSceneInfo.graphicsSystemInfo->getDrawContext();
|
|
}
|
|
|
|
void getActorRecourseDataF32(f32* val, LiveActor* actor, const char* fileName,
|
|
const char* entryName) {
|
|
isExistModelResourceYaml(actor, fileName, nullptr);
|
|
ByamlIter iter = {getModelResourceYaml(actor, fileName, nullptr)};
|
|
tryGetByamlF32(val, iter, entryName);
|
|
}
|
|
|
|
void getActorRecourseDataString(const char** val, LiveActor* actor, const char* fileName,
|
|
const char* entryName) {
|
|
isExistModelResourceYaml(actor, fileName, nullptr);
|
|
ByamlIter iter = {getModelResourceYaml(actor, fileName, nullptr)};
|
|
*val = getByamlKeyString(iter, entryName);
|
|
}
|
|
|
|
void getActorRecourseDataV3f(sead::Vector3f* val, LiveActor* actor, const char* fileName,
|
|
const char* entryName) {
|
|
isExistModelResourceYaml(actor, fileName, nullptr);
|
|
ByamlIter iter = {getModelResourceYaml(actor, fileName, nullptr)};
|
|
if (entryName)
|
|
tryGetByamlV3f(val, iter, entryName);
|
|
else
|
|
tryGetByamlV3f(val, iter);
|
|
}
|
|
|
|
void getActorRecourseDataBox3f(sead::BoundBox3f* box, LiveActor* actor, const char* fileName,
|
|
const char* entryName) {
|
|
isExistModelResourceYaml(actor, fileName, nullptr);
|
|
ByamlIter iter = {getModelResourceYaml(actor, fileName, nullptr)};
|
|
if (entryName)
|
|
tryGetByamlBox3f(box, iter, entryName);
|
|
else
|
|
tryGetByamlBox3f(box, iter);
|
|
}
|
|
|
|
PartsEffectGroup* createPartsEffectGroup(LiveActor* actor, const ActorInitInfo& initInfo,
|
|
s32 maxEffects) {
|
|
const char* name;
|
|
if (isExistModelResourceYaml(actor, "InitPartsEffect", nullptr))
|
|
getActorRecourseDataString(&name, actor, "InitPartsEffect", "Name");
|
|
else
|
|
getActorRecourseDataString(&name, actor, "InitEffect", "Name");
|
|
|
|
PartsEffectGroup* group = new PartsEffectGroup();
|
|
group->init(maxEffects, initInfo.effectSystemInfo, name, getTransPtr(actor),
|
|
tryGetScalePtr(actor), actor->getBaseMtx(), actor);
|
|
return group;
|
|
}
|
|
|
|
} // namespace al
|