1#pragma once
2
3#include <array>
4#include <type_traits>
5#include <basis/seadRawPrint.h>
6#include <basis/seadTypes.h>
7#include <gfx/seadColor.h>
8#include <hostio/seadHostIOCurve.h>
9#include <hostio/seadHostIOReflexible.h>
10#include <math/seadQuat.h>
11#include <math/seadVector.h>
12#include <prim/seadSafeString.h>
13#include "utility/aglResParameter.h"
14
15namespace sead {
16class Heap;
17class XmlElement;
18} // namespace sead
19
20namespace agl::utl {
21
22class IParameterObj;
23
24class ParameterBase {
25public:
26 enum class ParameterType {
27 Bool = 0,
28 F32 = 1,
29 Int = 2,
30 Vec2 = 3,
31 Vec3 = 4,
32 Vec4 = 5,
33 Color = 6,
34 String32 = 7,
35 String64 = 8,
36 Curve1 = 9,
37 Curve2 = 10,
38 Curve3 = 11,
39 Curve4 = 12,
40 BufferInt = 13,
41 BufferF32 = 14,
42 String256 = 15,
43 Quat = 16,
44 U32 = 17,
45 BufferU32 = 18,
46 BufferBinary = 19,
47 StringRef = 20,
48 Special = 21,
49 };
50
51 ParameterBase();
52 ParameterBase(const sead::SafeString& name, const sead::SafeString& label,
53 IParameterObj* param_obj);
54 ParameterBase(const sead::SafeString& name, const sead::SafeString& label,
55 const sead::SafeString& meta, IParameterObj* param_obj);
56 virtual ~ParameterBase() { ; }
57
58 void initializeListNode(const sead::SafeString& name, const sead::SafeString& label,
59 const sead::SafeString& meta, IParameterObj* param_obj);
60
61 u32 getNameHash() const { return mNameHash; }
62 sead::SafeString getParameterName() const;
63 sead::SafeString getName() const { return getParameterName(); }
64 sead::SafeString getLabel() const;
65 sead::SafeString getMeta() const;
66
67 ParameterBase* getNext() const { return mNext; }
68
69 static const char* getTagName();
70 static const char* getAttributeNameString();
71 static const char* getAttributeTypeString();
72 static const char* getAttributeValueString();
73 static const char* getParameterTypeName(ParameterType type);
74
75 bool isSafeType(ParameterType type) const;
76 bool verifyType(ParameterType type) const;
77
78 virtual bool copy(const ParameterBase& other);
79 virtual void copyUnsafe(const ParameterBase& other);
80 virtual bool copyLerp(const ParameterBase& param1, const ParameterBase& param2, f32 t);
81
82#ifdef SEAD_DEBUG
83 virtual void genMessageParameter(sead::hostio::Context* context);
84 void genMessageParameter(sead::hostio::Context* context, const sead::SafeString&);
85 virtual void listenPropertyEventParameter(sead::hostio::Reflexible* reflexible,
86 const sead::hostio::PropertyEvent* event);
87#endif
88
89 virtual void writeToXML(sead::XmlElement* element, sead::Heap* heap);
90 virtual bool readFromXML(const sead::XmlElement& element, bool x);
91
92 virtual ParameterType getParameterType() const = 0;
93 virtual const void* ptr() const = 0;
94 virtual void* ptr() = 0;
95 virtual const void* typePtr() const = 0;
96 virtual void* typePtr() = 0;
97 virtual u32 size() const = 0;
98 virtual u32 calcBinarizeSize() const { return size(); }
99 virtual ParameterBase* clone(sead::Heap* heap, IParameterObj* obj) const = 0;
100
101 void applyResource(ResParameter res);
102 void applyResource(ResParameter res, f32 t);
103 void applyString(const sead::SafeString& string, bool x);
104 virtual void postApplyResource_(const void*, size_t) {}
105 void createByTypeName(const sead::SafeString& a, const sead::SafeString& b);
106
107 virtual bool isBinary() const { return false; }
108 virtual bool isBinaryInternalBuffer() const { return true; }
109 bool isInterpolatable() const;
110 size_t binarize(void* binary) const;
111 bool makeZero();
112
113 static u32 calcHash(const sead::SafeString& key);
114
115 template <typename T>
116 T* ptrT() {
117 return static_cast<T*>(ptr());
118 }
119
120 template <typename T>
121 const T* ptrT() const {
122 return static_cast<const T*>(ptr());
123 }
124
125protected:
126 friend class IParameterObj;
127
128 template <typename T>
129 void copyLerp_(const ParameterBase& param1, const ParameterBase& param2, f32 t);
130
131 u32 mNameHash;
132 ParameterBase* mNext;
133
134#ifdef SEAD_DEBUG
135 const char* mName;
136 const char* mLabel;
137 const char* mMeta;
138#endif
139};
140
141using ParameterType = ParameterBase::ParameterType;
142
143template <typename T>
144class Parameter : public ParameterBase {
145public:
146 Parameter() = default;
147
148 explicit Parameter(const T& value) : mValue(value) {}
149
150 Parameter(const T& value, const sead::SafeString& name, IParameterObj* obj) {
151 initializeParameter(value, name, name, obj);
152 }
153
154 Parameter(const T& value, const sead::SafeString& name, const sead::SafeString& label,
155 IParameterObj* obj) {
156 initializeParameter(value, name, label, obj);
157 }
158
159 Parameter(const T& value, const sead::SafeString& name, const sead::SafeString& label,
160 const sead::SafeString& meta, IParameterObj* obj) {
161 initializeParameter(value, name, label, meta, obj);
162 }
163
164 ~Parameter() override { ; }
165
166 ParameterType getParameterType() const override {
167 if constexpr (std::is_pointer<T>())
168 return ParameterType::Special;
169 else if constexpr (std::is_same<T, bool>())
170 return ParameterType::Bool;
171 else if constexpr (std::is_same<T, f32>())
172 return ParameterType::F32;
173 else if constexpr (std::is_same<T, s32>())
174 return ParameterType::Int;
175 else if constexpr (std::is_same<T, sead::Vector2f>())
176 return ParameterType::Vec2;
177 else if constexpr (std::is_same<T, sead::Vector3f>())
178 return ParameterType::Vec3;
179 else if constexpr (std::is_same<T, sead::Vector4f>())
180 return ParameterType::Vec4;
181 else if constexpr (std::is_same<T, sead::Color4f>())
182 return ParameterType::Color;
183 else if constexpr (std::is_same<T, sead::FixedSafeString<32>>())
184 return ParameterType::String32;
185 else if constexpr (std::is_same<T, sead::FixedSafeString<64>>())
186 return ParameterType::String64;
187 // TODO: curve1-4
188 else if constexpr (std::is_same<T, sead::FixedSafeString<256>>())
189 return ParameterType::String256;
190 else if constexpr (std::is_same<T, sead::Quatf>())
191 return ParameterType::Quat;
192 else if constexpr (std::is_same<T, u32>())
193 return ParameterType::U32;
194 else if constexpr (std::is_same<T, sead::SafeString>())
195 return ParameterType::StringRef;
196 else
197 static_assert(!std::is_same<T, T>(), "Unknown type");
198 }
199
200 const void* ptr() const override {
201 if constexpr (std::is_base_of<sead::SafeString, T>()) {
202 return mValue.cstr();
203 } else {
204 return &mValue;
205 }
206 }
207
208 void* ptr() override {
209 if constexpr (std::is_same<T, sead::SafeString>()) {
210 SEAD_ASSERT_MSG(false, "Can't access.");
211 return nullptr;
212 } else if constexpr (std::is_base_of<sead::BufferedSafeString, T>()) {
213 return mValue.getBuffer();
214 } else {
215 return &mValue;
216 }
217 }
218
219 const void* typePtr() const override { return &mValue; }
220 void* typePtr() override { return &mValue; }
221
222 u32 size() const override {
223 if constexpr (std::is_same<T, sead::SafeString>())
224 return 8;
225 else if constexpr (std::is_same<T, sead::FixedSafeString<32>>())
226 return 32;
227 else if constexpr (std::is_same<T, sead::FixedSafeString<64>>())
228 return 64;
229 else if constexpr (std::is_same<T, sead::FixedSafeString<256>>())
230 return 256;
231 else
232 return sizeof(T);
233 }
234
235 u32 calcBinarizeSize() const override {
236 if constexpr (std::is_base_of<sead::SafeString, T>()) {
237 return mValue.calcLength() + 1;
238 } else {
239 return size();
240 }
241 }
242
243 ParameterBase* clone(sead::Heap* heap, IParameterObj* obj) const override {
244 return new (heap) Parameter<T>(mValue, getName(), getLabel(), getMeta(), obj);
245 }
246
247 void initializeParameter(const T& value, const sead::SafeString& name,
248 const sead::SafeString& label, IParameterObj* obj) {
249 initializeListNode(name, label, "", obj);
250 mValue = value;
251
252 if constexpr (std::is_same<T, sead::SafeString>()) {
253 SEAD_ASSERT_MSG(!sead::MemUtil::isStack(value.cstr()), "%p is in stack", value.cstr());
254 }
255 }
256
257 void initializeParameter(const T& value, const sead::SafeString& name,
258 const sead::SafeString& label, const sead::SafeString& meta,
259 IParameterObj* obj) {
260 initializeListNode(name, label, meta, obj);
261 mValue = value;
262
263 if constexpr (std::is_same<T, sead::SafeString>()) {
264 SEAD_ASSERT_MSG(!sead::MemUtil::isStack(value.cstr()), "%p is in stack", value.cstr());
265 }
266 }
267
268 /// Alias of initializeParameter.
269 void init(const T& value, const sead::SafeString& name, IParameterObj* obj) {
270 initializeParameter(value, name, name, obj);
271 }
272
273 /// Alias of initializeParameter.
274 void init(const T& value, const sead::SafeString& name, const sead::SafeString& label,
275 IParameterObj* obj) {
276 initializeParameter(value, name, label, obj);
277 }
278
279 /// Alias of initializeParameter.
280 void init(const T& value, const sead::SafeString& name, const sead::SafeString& label,
281 const sead::SafeString& meta, IParameterObj* obj) {
282 initializeParameter(value, name, label, meta, obj);
283 }
284
285 T& ref() { return mValue; }
286 const T& ref() const { return mValue; }
287
288 T& operator*() { return mValue; }
289 const T& operator*() const { return mValue; }
290 T* operator->() { return &mValue; }
291 const T* operator->() const { return &mValue; }
292
293 Parameter& operator=(const T& value) {
294 mValue = value;
295 return *this;
296 }
297
298protected:
299 T mValue;
300};
301
302template <typename T>
303class ParameterBuffer : public Parameter<T*> {
304public:
305 ParameterBuffer(sead::Heap* heap, s32 num) {
306 SEAD_ASSERT(!isBinaryInternalBuffer());
307 this->mValue = new (heap) T[num];
308 mBufferSize = num;
309 mBufferAllocated = true;
310
311 for (s32 i = 0; i < num; ++i)
312 this->mValue[i] = {};
313 }
314
315 ~ParameterBuffer() override { freeBuffer(); }
316
317 void freeBuffer() {
318 if (!mBufferAllocated)
319 return;
320
321 if (this->mValue)
322 delete[] this->mValue;
323 mBufferAllocated = false;
324 }
325
326 ParameterType getParameterType() const override {
327 if constexpr (std::is_same<T, s32>())
328 return ParameterType::BufferInt;
329 else if constexpr (std::is_same<T, f32>())
330 return ParameterType::BufferF32;
331 else if constexpr (std::is_same<T, u32>())
332 return ParameterType::BufferU32;
333 else if constexpr (std::is_same<T, u8>())
334 return ParameterType::BufferBinary;
335 else
336 static_assert(!std::is_same<T, T>(), "Unknown type");
337 }
338
339 const void* ptr() const override { return this->mValue; }
340 void* ptr() override { return this->mValue; }
341 u32 size() const override { return sizeof(T) * mBufferSize; }
342
343 void postApplyResource_(const void* data, size_t size) override {
344 if (isBinaryInternalBuffer())
345 return;
346 this->mValue = data;
347 mBufferSize = size / sizeof(T);
348 }
349
350 bool isBinary() const override { return true; }
351 bool isBinaryInternalBuffer() const override { return mBufferAllocated; }
352
353protected:
354 s32 mBufferSize;
355 bool mBufferAllocated;
356};
357
358class ParameterDirection3f : public Parameter<sead::Vector3f> {
359public:
360 ~ParameterDirection3f() override = default;
361
362#ifdef SEAD_DEBUG
363 void genMessageParameter(sead::hostio::Context* context) override;
364 void listenPropertyEventParameter(sead::hostio::Reflexible* reflexible,
365 const sead::hostio::PropertyEvent* event) override;
366#endif
367};
368
369template <u32 N>
370class ParameterCurve : public ParameterBase {
371public:
372 ParameterCurve(const sead::SafeString& name, const sead::SafeString& label,
373 IParameterObj* param_obj);
374
375 void reset();
376
377 bool copy(const ParameterBase& other) override;
378 void copyUnsafe(const ParameterBase& other) override;
379
380 void writeToXML(sead::XmlElement* element, sead::Heap* heap) override;
381 bool readFromXML(const sead::XmlElement& element, bool x) override;
382
383 ParameterType getParameterType() const override;
384
385 const void* ptr() const override { return mCurveData.data(); }
386 void* ptr() override { return mCurveData.data(); }
387 const void* typePtr() const override { return mCurveData.data(); }
388 void* typePtr() override { return mCurveData.data(); }
389 u32 size() const override { return sizeof(mCurveData); }
390
391 ParameterBase* clone(sead::Heap* heap, IParameterObj* obj) const override;
392
393 void postApplyResource_(const void*, size_t size) override;
394
395#ifdef SEAD_DEBUG
396 void genMessageParameter(sead::hostio::Context* context) override;
397 virtual void genMessageParameterUnit(sead::hostio::Context* context, s32,
398 const sead::SafeString&, const sead::SafeString&);
399#endif
400
401 static constexpr u32 cUnitCurveParamNum = 30;
402
403protected:
404 std::array<sead::hostio::Curve<f32>, N> mCurves;
405 std::array<sead::hostio::CurveData, N> mCurveData;
406};
407
408inline ResParameter getResParameter(const agl::utl::ResParameterObj& obj,
409 const sead::SafeString& name) {
410 const s32 idx = obj.searchIndex(ParameterBase::calcHash(name));
411 if (idx == -1)
412 return {};
413
414 return obj.getResParameter(idx);
415}
416
417inline ResParameterObj getResParameterObj(const agl::utl::ResParameterList& list,
418 const sead::SafeString& name) {
419 const s32 idx = list.searchObjIndex(ParameterBase::calcHash(name));
420 if (idx == -1)
421 return {};
422
423 return list.getResParameterObj(idx);
424}
425
426inline ResParameterList getResParameterList(const agl::utl::ResParameterList& list,
427 const sead::SafeString& name) {
428 const s32 idx = list.searchListIndex(ParameterBase::calcHash(name));
429 if (idx == -1)
430 return {};
431
432 return list.getResParameterList(idx);
433}
434
435} // namespace agl::utl
436
437#define AGL_UTILS_PARAMETER_H_
438#include "utility/aglParameterCurve.hpp"
439#undef AGL_UTILS_PARAMETER_H_
440