1#include "Library/Obj/PartsModel.h"
2
3#include "Library/Base/StringUtil.h"
4#include "Library/LiveActor/ActorClippingFunction.h"
5#include "Library/LiveActor/ActorFlagFunction.h"
6#include "Library/LiveActor/ActorInitFunction.h"
7#include "Library/LiveActor/ActorInitUtil.h"
8#include "Library/LiveActor/ActorModelFunction.h"
9#include "Library/LiveActor/ActorPoseUtil.h"
10#include "Library/LiveActor/ActorResourceFunction.h"
11#include "Library/LiveActor/LiveActorFunction.h"
12#include "Library/Math/MathUtil.h"
13#include "Library/Matrix/MatrixUtil.h"
14#include "Library/Yaml/ByamlUtil.h"
15
16namespace al {
17PartsModel::PartsModel(const char* name) : LiveActor(name) {}
18
19void PartsModel::endClipped() {
20 LiveActor::endClipped();
21 updatePose();
22}
23
24void PartsModel::calcAnim() {
25 updatePose();
26 LiveActor::calcAnim();
27}
28
29void PartsModel::attackSensor(HitSensor* self, HitSensor* other) {
30 mParentModel->attackSensor(self, other);
31}
32
33bool PartsModel::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) {
34 return mParentModel->receiveMsg(message, other, self);
35}
36
37void PartsModel::initPartsDirect(LiveActor* parent, const ActorInitInfo& initInfo,
38 const char* arcName, const sead::Matrix34f* jointMtx,
39 const sead::Vector3f& localTrans,
40 const sead::Vector3f& localRotate,
41 const sead::Vector3f& localScale, bool useFollowMtxScale) {
42 mParentModel = parent;
43 mJointMtx = jointMtx;
44 mIsUseFollowMtxScale = useFollowMtxScale;
45 initChildActorWithArchiveNameNoPlacementInfo(actor: this, initInfo, archiveName: arcName, suffix: nullptr);
46 invalidateClipping(actor: this);
47 registerSubActor(parent, this);
48 makeActorAlive();
49 mIsUseLocalPos = true;
50 mLocalTrans = localTrans;
51 mLocalRotate = localRotate;
52 mLocalScale = localScale;
53}
54
55void PartsModel::initPartsSuffix(LiveActor* parent, const ActorInitInfo& initInfo,
56 const char* arcName, const char* suffix,
57 const sead::Matrix34f* jointMtx, bool useFollowMtxScale) {
58 mParentModel = parent;
59 mJointMtx = jointMtx;
60 mIsUseFollowMtxScale = useFollowMtxScale;
61 initChildActorWithArchiveNameNoPlacementInfo(actor: this, initInfo, archiveName: arcName, suffix);
62 invalidateClipping(actor: this);
63 registerSubActor(parent, this);
64 makeActorAlive();
65}
66
67void PartsModel::initPartsMtx(LiveActor* parent, const ActorInitInfo& initInfo, const char* arcName,
68 const sead::Matrix34f* jointMtx, bool useFollowMtxScale) {
69 mParentModel = parent;
70 mJointMtx = jointMtx;
71 mIsUseFollowMtxScale = useFollowMtxScale;
72 initChildActorWithArchiveNameNoPlacementInfo(actor: this, initInfo, archiveName: arcName, suffix: nullptr);
73 invalidateClipping(actor: this);
74 registerSubActor(parent, this);
75 makeActorAlive();
76}
77
78void PartsModel::initPartsFixFile(LiveActor* parent, const ActorInitInfo& initInfo,
79 const char* arcName, const char* arcSuffix, const char* suffix) {
80 initPartsFixFileNoRegister(parent, initInfo, arcName, arcSuffix, suffix);
81 registerSubActor(parent, this);
82}
83
84void PartsModel::initPartsFixFileNoRegister(LiveActor* parent, const ActorInitInfo& initInfo,
85 const char* arcName, const char* arcSuffix,
86 const char* suffix) {
87 mParentModel = parent;
88 mJointMtx = parent->getBaseMtx();
89
90 initChildActorWithArchiveNameNoPlacementInfo(actor: this, initInfo, archiveName: arcName, suffix: arcSuffix);
91 invalidateClipping(actor: this);
92
93 sead::FixedSafeString<0x80> initArcName;
94 createFileNameBySuffix(out: &initArcName, name: "InitPartsFixInfo", suffix);
95
96 if (!isExistModelResourceYaml(mParentModel, initArcName.cstr(), nullptr))
97 return makeActorAlive();
98 u8* modelResByml = getModelResourceYaml(mParentModel, initArcName.cstr(), nullptr);
99 ByamlIter modelResIter(modelResByml);
100
101 const char* jointName = nullptr;
102 modelResIter.tryGetStringByKey(string: &jointName, key: "JointName");
103
104 if (jointName)
105 mJointMtx = getJointMtxPtr(actor: mParentModel, jointName);
106
107 tryGetByamlV3f(&mLocalTrans, modelResIter, "LocalTrans");
108 tryGetByamlV3f(&mLocalRotate, modelResIter, "LocalRotate");
109 tryGetByamlV3f(&mLocalScale, modelResIter, "LocalScale");
110
111 mIsUseLocalScale = tryGetByamlKeyBoolOrFalse(modelResIter, "UseLocalScale");
112
113 if (!isNearZero(vec: mLocalTrans) || !isNearZero(vec: mLocalRotate) || mIsUseLocalScale)
114 mIsUseLocalPos = true;
115
116 mIsUseFollowMtxScale = tryGetByamlKeyBoolOrFalse(modelResIter, "UseFollowMtxScale");
117
118 makeActorAlive();
119}
120
121void PartsModel::updatePose() {
122 if (!mIsUpdate)
123 return;
124
125 if (!mIsUseLocalPos) {
126 sead::Matrix34f baseMtx = *mJointMtx;
127 if (mIsUseFollowMtxScale) {
128 sead::Vector3f mtxScale;
129 calcMtxScale(outMtx: &mtxScale, mtx: baseMtx);
130 const sead::Vector3f& scale = sead::Vector3f::ones;
131 mtxScale.x *= scale.x;
132 mtxScale.y *= scale.y;
133 mtxScale.z *= scale.z;
134 setScale(actor: this, scale: mtxScale);
135 }
136 normalize(mtx: &baseMtx);
137 updatePoseMtx(actor: this, mtx: &baseMtx);
138 return;
139 }
140
141 sead::Matrix34f rotationMatrix;
142 sead::Vector3f rotate(sead::Mathf::deg2rad(deg: mLocalRotate.x),
143 sead::Mathf::deg2rad(deg: mLocalRotate.y),
144 sead::Mathf::deg2rad(deg: mLocalRotate.z));
145 rotationMatrix.makeR(r: rotate);
146
147 sead::Matrix34f translationMatrix;
148 translationMatrix.makeRT(r: {0.0f, 0.0f, 0.0f}, t: mLocalTrans);
149
150 sead::Matrix34f poseMatrix = rotationMatrix * translationMatrix;
151
152 sead::Matrix34f baseMtx = *mJointMtx;
153
154 if (mIsUseFollowMtxScale) {
155 sead::Matrix34f rotBaseMtx = baseMtx * rotationMatrix;
156
157 sead::Vector3f mtxScale = {0.0f, 0.0f, 0.0f};
158 calcMtxScale(outMtx: &mtxScale, mtx: rotBaseMtx);
159
160 poseMatrix.m[0][3] *= mtxScale.x;
161 poseMatrix.m[1][3] *= mtxScale.y;
162 poseMatrix.m[2][3] *= mtxScale.z;
163
164 if (mIsUseLocalScale) {
165 mtxScale.x *= mLocalScale.x;
166 mtxScale.y *= mLocalScale.y;
167 mtxScale.z *= mLocalScale.z;
168 }
169
170 setScale(actor: this, scale: mtxScale);
171 } else if (mIsUseLocalScale) {
172 setScale(actor: this, scale: mLocalScale);
173 }
174
175 normalize(mtx: &baseMtx);
176 baseMtx = baseMtx * poseMatrix;
177 updatePoseMtx(actor: this, mtx: &baseMtx);
178}
179
180void PartsModel::offSyncAppearAndHide() {
181 offSyncAppearSubActor(actor: mParentModel, subActor: this);
182 offSyncHideSubActor(actor: mParentModel, subActor: this);
183}
184
185void PartsModel::onSyncAppearAndHide() {
186 onSyncHideSubActor(actor: mParentModel, subActor: this);
187
188 if (isHideModel(actor: mParentModel))
189 hideModelIfShow(actor: this);
190 else
191 showModelIfHide(actor: this);
192
193 onSyncAppearSubActor(actor: mParentModel, subActor: this);
194
195 if (isDead(actor: mParentModel) && isAlive(actor: this))
196 makeActorDead();
197 else if (isAlive(actor: mParentModel) && isDead(actor: this))
198 makeActorAlive();
199}
200} // namespace al
201