1#include "utility/aglParameterObj.h"
2#include <basis/seadRawPrint.h>
3#include <prim/seadFormatPrint.h>
4#include "utility/aglParameter.h"
5
6namespace agl::utl {
7
8IParameterObj::IParameterObj() = default;
9
10void IParameterObj::pushBackListNode(ParameterBase* p_node) {
11 SEAD_ASSERT(p_node != nullptr);
12
13 ParameterBase** ptr;
14 if (mParamListTail) {
15 ptr = &mParamListTail->mNext;
16 } else {
17 ptr = &mParamListHead;
18 mParamListTail = p_node;
19 }
20
21 *ptr = p_node;
22 mParamListTail = p_node;
23 ++mParamListSize;
24}
25
26const char* IParameterObj::getTagName() {
27 return "param_array";
28}
29
30sead::SafeString IParameterObj::getName() const {
31#ifdef SEAD_DEBUG
32 return mName;
33#else
34 return sead::SafeString::cEmptyString;
35#endif
36}
37
38void IParameterObj::applyResParameterObj(ResParameterObj obj1, ResParameterObj obj2, f32 t,
39 IParameterList* list) {
40 if (obj1.ptr() && t <= 0.0f) {
41 applyResParameterObj_(interpolate: false, obj1, obj2: {}, t: 0.0f, list);
42 return;
43 }
44
45 if (obj2.ptr() && t >= 1.0f) {
46 applyResParameterObj_(interpolate: false, obj1: obj2, obj2: {}, t: 0.0f, list);
47 return;
48 }
49
50 applyResParameterObj_(interpolate: true, obj1, obj2, t, list);
51}
52
53bool IParameterObj::isComplete(ResParameterObj obj, bool check_values) const {
54 if (!obj.ptr() || obj.getNum() != mParamListSize)
55 return false;
56
57 ParameterBase* param = mParamListHead;
58
59 while (param) {
60 const auto idx = obj.searchIndex(param_hash: param->getNameHash());
61 if (idx == -1)
62 return false;
63
64 if (check_values) {
65 const auto res = obj.getResParameter(index: idx);
66
67 // As usual, booleans are a special case.
68 if (ParameterType(res.ptr()->getType()) == ParameterType::Bool) {
69 const bool value = *res.getData<u32>() != 0;
70 if (value != *param->ptrT<bool>())
71 return false;
72 } else {
73 if (sead::MemUtil::compare(ptr1: param->ptr(), ptr2: res.getData<void>(), size: res.getDataSize()))
74 return false;
75 }
76 }
77
78 param = param->mNext;
79 }
80 return true;
81}
82
83bool IParameterObj::verify() const {
84 bool ret = true;
85 for (auto* param = mParamListHead; param; param = param->mNext)
86 ret &= verify(p_check: param, other: param->mNext);
87 return ret;
88}
89
90bool IParameterObj::verify(ParameterBase* p_check, ParameterBase* other) const {
91 SEAD_ASSERT(p_check != nullptr);
92 auto* param = other;
93 bool ok = true;
94 while (param) {
95 if (p_check->getNameHash() == param->getNameHash()) {
96 sead::BufferingPrintFormatter ss;
97 ss << "Same hash code at [%s] and [%s]. Please change.\n"
98 << p_check->getName().cstr() << param->getName().cstr() << sead::flush;
99 ok = false;
100 }
101 param = param->mNext;
102 }
103 return ok;
104}
105
106ParameterBase* IParameterObj::searchParameter_(u32 hash) {
107 for (auto* param = mParamListHead; param; param = param->mNext) {
108 if (param->getNameHash() == hash)
109 return param;
110 }
111 return nullptr;
112}
113
114ParameterBase* IParameterObj::searchParameter_(u32 hash) const {
115 for (auto* param = mParamListHead; param; param = param->mNext) {
116 if (param->getNameHash() == hash)
117 return param;
118 }
119 return nullptr;
120}
121
122void IParameterObj::copy(ParameterBase* first, ParameterBase* last, const ParameterBase* src_first,
123 const ParameterBase* src_last) {
124 if (!preCopy_())
125 return;
126
127 copy_(first, last, src_first, src_last);
128
129 postCopy_();
130}
131
132void IParameterObj::copy_(ParameterBase* first, ParameterBase* last, const ParameterBase* src_first,
133 const ParameterBase* src_last) {
134 auto target = first;
135 auto source = src_first;
136 while (target != last && source != src_last) {
137 const bool result = target->copy(other: *source);
138 SEAD_ASSERT(result);
139 target = target->mNext;
140 source = source->mNext;
141 }
142}
143
144void IParameterObj::copy(const IParameterObj& obj) {
145 if (!preCopy_())
146 return;
147
148 auto* mpHead = mParamListHead;
149 SEAD_ASSERT(mpHead != nullptr);
150
151 auto* src = obj.mParamListHead;
152 while (src && src->getNameHash() != mpHead->getNameHash())
153 src = src->mNext;
154
155 while (src && mpHead) {
156 const bool result = mpHead->copy(other: *src);
157 SEAD_ASSERT(result);
158 mpHead = mpHead->mNext;
159 if (!mpHead)
160 break;
161 src = src->mNext;
162 }
163
164 postCopy_();
165}
166
167void IParameterObj::copyLerp(ParameterBase* first, ParameterBase* last,
168 const ParameterBase* src1_first, const ParameterBase* src1_last,
169 const ParameterBase* src2_first, const ParameterBase* src2_last,
170 f32 t) {
171 if (!preCopy_())
172 return;
173
174 if (t <= 0.0)
175 copy_(first, last, src_first: src1_first, src_last: src1_last);
176 else if (t >= 1.0)
177 copy_(first, last, src_first: src2_first, src_last: src2_last);
178 else
179 copyLerp_(first, last, src1_first, src1_last, src2_first, src2_last, t);
180
181 postCopy_();
182}
183
184void IParameterObj::copyLerp(const IParameterObj& obj1, const IParameterObj& obj2, f32 t) {
185 if (!preCopy_())
186 return;
187
188 auto mpHead = mParamListHead;
189 SEAD_ASSERT(mpHead);
190
191 const u32 hash = mpHead->getNameHash();
192
193 auto* it1 = obj1.mParamListHead;
194 while (it1 && it1->getNameHash() != hash)
195 it1 = it1->mNext;
196
197 auto* it2 = obj2.mParamListHead;
198 while (it2 && it2->getNameHash() != hash)
199 it2 = it2->mNext;
200
201 while (it1 && it2 && mpHead) {
202 const bool result = mpHead->copyLerp(param1: *it1, param2: *it2, t);
203 SEAD_ASSERT(result);
204 it2 = it2->mNext;
205 if (!it2)
206 break;
207 mpHead = mpHead->mNext;
208 if (!mpHead)
209 break;
210 it1 = it1->mNext;
211 }
212
213 postCopy_();
214}
215
216void IParameterObj::copyLerp_(ParameterBase* first, ParameterBase* last,
217 const ParameterBase* src1_first, const ParameterBase* src1_last,
218 const ParameterBase* src2_first, const ParameterBase* src2_last,
219 f32 t) {
220 auto* it = first;
221 auto* src1 = src1_first;
222 auto* src2 = src2_first;
223 while (it != last && src1 != src1_last && src2 != src2_last) {
224 const bool result = it->copyLerp(param1: *src1, param2: *src2, t);
225 SEAD_ASSERT(result);
226 it = it->mNext;
227 src1 = src1->mNext;
228 src2 = src2->mNext;
229 }
230}
231
232} // namespace agl::utl
233