ksys/gdt: Add Flag

This commit is contained in:
Léo Lam
2020-10-16 13:38:35 +02:00
parent 906dad46ad
commit e3fd543178
6 changed files with 775 additions and 230 deletions
+1
View File
@@ -1,6 +1,7 @@
add_subdirectory(ActorSystem)
add_subdirectory(Ecosystem)
add_subdirectory(Framework)
add_subdirectory(GameData)
add_subdirectory(Map)
add_subdirectory(MessageSystem)
add_subdirectory(Resource)
+4
View File
@@ -0,0 +1,4 @@
target_sources(uking PRIVATE
gdtFlag.cpp
gdtFlag.h
)
+151
View File
@@ -0,0 +1,151 @@
#include "KingSystem/GameData/gdtFlag.h"
namespace ksys::gdt {
SEAD_ENUM_IMPL(FlagType)
FlagProperties::FlagProperties() = default;
FlagProperties::~FlagProperties() = default;
void FlagProperties::setIsProgramReadable(bool on) {
set(PropertyFlag::IsProgramReadable, on);
}
bool FlagProperties::isProgramReadable() const {
return get(PropertyFlag::IsProgramReadable);
}
void FlagProperties::setIsProgramWritable(bool on) {
set(PropertyFlag::IsProgramWritable, on);
}
bool FlagProperties::isProgramWritable() const {
return get(PropertyFlag::IsProgramWritable);
}
void FlagProperties::setIsSave(bool on) {
set(PropertyFlag::IsSave, on);
}
bool FlagProperties::isSave() const {
return get(PropertyFlag::IsSave);
}
void FlagProperties::setIsOneTrigger(bool on) {
set(PropertyFlag::IsOneTrigger, on);
}
bool FlagProperties::isOneTrigger() const {
return get(PropertyFlag::IsOneTrigger);
}
void FlagProperties::setIsEventAssociated(bool on) {
set(PropertyFlag::IsEventAssociated, on);
}
bool FlagProperties::isEventAssociated() const {
return get(PropertyFlag::IsEventAssociated);
}
void FlagProperties::setResetType(ResetType type) {
mFlags = (mFlags & 0x1F) | 0x20 * u32(type);
}
ResetType FlagProperties::getResetType() const {
return ResetType(mFlags >> 5);
}
FlagProperties& FlagProperties::operator=(const FlagProperties& other) {
setIsProgramReadable(other.isProgramReadable());
setIsProgramWritable(other.isProgramWritable());
setIsSave(other.isSave());
setIsOneTrigger(other.isOneTrigger());
setIsEventAssociated(other.isEventAssociated());
setResetType(other.getResetType());
return *this;
}
s32 FlagBase::clampValue_(const s32& min_value, s32* value, const s32& max_value) {
if (*value < min_value) {
*value = min_value;
return -1;
}
if (*value > max_value) {
*value = max_value;
return 1;
}
return 0;
}
s32 FlagBase::clampValue_(const f32& min_value, f32* value, const f32& max_value) {
if (*value < min_value) {
*value = min_value;
return -1;
}
if (*value > max_value) {
*value = max_value;
return 1;
}
return 0;
}
s32 FlagBase::clampValue_(const sead::SafeString&, sead::SafeString*, const sead::SafeString&) {
return 0;
}
namespace {
template <typename T>
constexpr s32 clampVectorComponentWise(const T& min_value, T* value, const T& max_value) {
s32 ret = 0;
for (size_t i = 0; i < min_value.e.size(); ++i) {
if (value->e[i] < min_value.e[i]) {
value->e[i] = min_value.e[i];
ret = -1;
}
}
for (size_t i = 0; i < max_value.e.size(); ++i) {
if (value->e[i] > max_value.e[i]) {
value->e[i] = max_value.e[i];
ret = 1;
}
}
return ret;
}
} // namespace
s32 FlagBase::clampValue_(const sead::Vector2f& min_value, sead::Vector2f* value,
const sead::Vector2f& max_value) {
return clampVectorComponentWise(min_value, value, max_value);
}
s32 FlagBase::clampValue_(const sead::Vector3f& min_value, sead::Vector3f* value,
const sead::Vector3f& max_value) {
return clampVectorComponentWise(min_value, value, max_value);
}
s32 FlagBase::clampValue_(const sead::Vector4f& min_value, sead::Vector4f* value,
const sead::Vector4f& max_value) {
return clampVectorComponentWise(min_value, value, max_value);
}
bool FlagBase::isBoolean_() const {
const auto type = getType();
return s32(type) == FlagType::Bool || s32(type) == FlagType::BoolArray;
}
u32 FlagBase::getCategoryForBool_(const void* data) const {
if (!isBoolean_())
return 0;
return *static_cast<const u8*>(data) >> 1;
}
void FlagBase::setCategoryForBool_(void* data, u32 category) const {
if (!isBoolean_())
return;
auto* ptr = static_cast<u8*>(data);
*ptr = (*ptr & 1) | 2 * category;
}
} // namespace ksys::gdt
+384
View File
@@ -0,0 +1,384 @@
#pragma once
#include <basis/seadTypes.h>
#include <container/seadBuffer.h>
#include <math/seadVector.h>
#include <prim/seadEnum.h>
#include <prim/seadSafeString.h>
#include <prim/seadSizedEnum.h>
#include <type_traits>
#include "KingSystem/Utils/Types.h"
namespace al {
class ByamlIter;
}
namespace ksys::gdt {
enum class ResetType {
/// The flag will not be reset.
NoReset = 0,
/// The flag is reset every time a blood moon occurs.
ResetOnBloodMoon = 1,
/// The flag is reset every time a stage is generated.
ResetOnStageGeneration = 2,
/// The flag is reset every day at midnight.
ResetAtMidnight = 3,
/// The flag is reset every time the Lord of the Mountain makes an appearance.
ResetOnAnimalMasterAppearance = 4,
};
struct FlagDebugData {
sead::SafeString name;
s32 delete_rev = 0;
u32 _14 = 0;
};
KSYS_CHECK_SIZE_NX150(FlagDebugData, 0x18);
class FlagProperties {
public:
FlagProperties();
FlagProperties(const FlagProperties& other) { *this = other; }
~FlagProperties();
FlagProperties& operator=(const FlagProperties& other);
void setIsProgramReadable(bool on);
bool isProgramReadable() const;
void setIsProgramWritable(bool on);
bool isProgramWritable() const;
void setIsSave(bool on);
bool isSave() const;
void setIsOneTrigger(bool on);
bool isOneTrigger() const;
void setIsEventAssociated(bool on);
bool isEventAssociated() const;
void setResetType(ResetType type);
ResetType getResetType() const;
private:
enum class PropertyFlag {
IsProgramReadable = 0x1,
IsProgramWritable = 0x2,
IsSave = 0x4,
IsOneTrigger = 0x8,
IsEventAssociated = 0x10,
};
void set(PropertyFlag flag, bool on) {
if (on)
mFlags |= u8(flag);
else
mFlags &= ~u8(flag);
}
bool get(PropertyFlag flag) const { return (mFlags & u8(flag)) != 0; }
u8 mFlags{};
};
KSYS_CHECK_SIZE_NX150(FlagProperties, 0x1);
SEAD_ENUM(FlagType, Bool = 0, S32 = 1, F32 = 2, String = 3, String64 = 4, String256 = 5,
Vector2f = 6, Vector3f = 7, Vector4f = 8, BoolArray = 9, S32Array = 10, F32Array = 11,
StringArray = 12, String64Array = 13, String256Array = 14, Vector2fArray = 15,
Vector3fArray = 16, Vector4fArray = 17, Invalid = 18)
class FlagBase {
public:
virtual ~FlagBase() = 0;
virtual u32 getHash() const = 0;
virtual void setHash(u32 hash) = 0;
virtual FlagType getType() const = 0;
virtual void setType(FlagType type) = 0;
virtual const FlagProperties& getProperties() const = 0;
virtual void setProperties(const FlagProperties& properties) = 0;
virtual void resetToInitialValue() = 0;
virtual bool isInitialValue() const = 0;
virtual u32 getCategory() const = 0;
virtual void setCategory(u32 category) = 0;
virtual const sead::SafeString& getName() const = 0;
virtual s32 getDeleteRev() const = 0;
protected:
s32 clampValue_(const s32& min_value, s32* value, const s32& max_value);
s32 clampValue_(const f32& min_value, f32* value, const f32& max_value);
s32 clampValue_(const sead::SafeString& min_value, sead::SafeString* value,
const sead::SafeString& max_value);
s32 clampValue_(const sead::Vector2f& min_value, sead::Vector2f* value,
const sead::Vector2f& max_value);
s32 clampValue_(const sead::Vector3f& min_value, sead::Vector3f* value,
const sead::Vector3f& max_value);
s32 clampValue_(const sead::Vector4f& min_value, sead::Vector4f* value,
const sead::Vector4f& max_value);
bool isBoolean_() const;
u32 getCategoryForBool_(const void* data) const;
void setCategoryForBool_(void* data, u32 category) const;
};
template <typename T>
struct FlagConfig {
FlagConfig& operator=(const FlagConfig& other) {
initial_value = other.initial_value;
min_value = other.min_value;
max_value = other.max_value;
return *this;
}
T initial_value;
T min_value;
T max_value;
};
template <>
struct FlagConfig<bool> {
u8 initial_value;
};
template <typename T>
class Flag : public FlagBase {
public:
using ConfigType = FlagConfig<T>;
using RawValueType = std::conditional_t<std::is_same_v<T, bool>, u8, T>;
Flag() = default;
~Flag() override = default;
u32 getHash() const override;
void setHash(u32 hash) override;
FlagType getType() const override;
void setType(FlagType type) override;
const FlagProperties& getProperties() const override;
void setProperties(const FlagProperties& properties) override;
void resetToInitialValue() override;
bool isInitialValue() const override;
u32 getCategory() const override;
void setCategory(u32 category) override;
const sead::SafeString& getName() const override;
s32 getDeleteRev() const override;
virtual u32 getRandomResetData() const;
virtual const ConfigType& getConfig() const;
virtual void setConfig(const ConfigType& config);
virtual T getValue() const;
virtual RawValueType& getValueRef();
virtual const RawValueType& getValueRef() const;
virtual bool hasValue(const T& value) const;
virtual bool setValue(T value);
virtual FlagDebugData* getDebugData() const;
private:
sead::SizedEnum<typename FlagType::ValueType, u8> mType = FlagType::Invalid;
FlagProperties mProperties;
ConfigType mConfig{};
RawValueType mValue{};
u32 mHash = 0;
FlagDebugData* mDebugData = nullptr;
};
using FlagBool = Flag<bool>;
using FlagS32 = Flag<s32>;
using FlagF32 = Flag<f32>;
using FlagString = Flag<sead::FixedSafeString<32>>;
using FlagString64 = Flag<sead::FixedSafeString<64>>;
using FlagString256 = Flag<sead::FixedSafeString<256>>;
using FlagVector2f = Flag<sead::Vector2f>;
using FlagVector3f = Flag<sead::Vector3f>;
using FlagVector4f = Flag<sead::Vector4f>;
using FlagBoolArray = sead::Buffer<FlagBool>;
using FlagS32Array = sead::Buffer<FlagS32>;
using FlagF32Array = sead::Buffer<FlagF32>;
using FlagStringArray = sead::Buffer<FlagString>;
using FlagString64Array = sead::Buffer<FlagString64>;
using FlagString256Array = sead::Buffer<FlagString256>;
using FlagVector2fArray = sead::Buffer<FlagVector2f>;
using FlagVector3fArray = sead::Buffer<FlagVector3f>;
using FlagVector4fArray = sead::Buffer<FlagVector4f>;
KSYS_CHECK_SIZE_NX150(FlagBool, 0x18);
KSYS_CHECK_SIZE_NX150(FlagS32, 0x28);
KSYS_CHECK_SIZE_NX150(FlagF32, 0x28);
KSYS_CHECK_SIZE_NX150(FlagString, 0x100);
KSYS_CHECK_SIZE_NX150(FlagString64, 0x180);
KSYS_CHECK_SIZE_NX150(FlagString256, 0x480);
KSYS_CHECK_SIZE_NX150(FlagVector2f, 0x38);
KSYS_CHECK_SIZE_NX150(FlagVector3f, 0x48);
KSYS_CHECK_SIZE_NX150(FlagVector4f, 0x58);
inline FlagBase::~FlagBase() = default;
template <typename T>
inline u32 Flag<T>::getHash() const {
return mHash;
}
template <typename T>
inline void Flag<T>::setHash(u32 hash) {
mHash = hash;
}
template <typename T>
inline FlagType Flag<T>::getType() const {
return mType.mValue;
}
template <typename T>
inline void Flag<T>::setType(FlagType type) {
mType.mValue = u8(type);
}
template <typename T>
inline const FlagProperties& Flag<T>::getProperties() const {
return mProperties;
}
template <typename T>
inline void Flag<T>::setProperties(const FlagProperties& properties) {
mProperties = properties;
}
template <typename T>
inline void Flag<T>::resetToInitialValue() {
if constexpr (std::is_same<T, bool>()) {
const auto category = getCategory();
mValue = getConfig().initial_value & 1;
setCategory(category);
} else {
mValue = getConfig().initial_value;
}
}
template <typename T>
inline bool Flag<T>::isInitialValue() const {
if constexpr (std::is_same<T, bool>()) {
const bool initial_value = getConfig().initial_value & 1;
return getValue() == initial_value;
} else {
T initial_value;
initial_value = getConfig().initial_value;
return getValue() == initial_value;
}
}
template <typename T>
inline u32 Flag<T>::getCategory() const {
if (!isBoolean_())
return 0;
return getCategoryForBool_(&mValue);
}
template <typename T>
inline void Flag<T>::setCategory(u32 category) {
if (!isBoolean_())
return;
setCategoryForBool_(&mValue, category);
}
template <typename T>
inline const sead::SafeString& Flag<T>::getName() const {
return mDebugData ? mDebugData->name : sead::SafeString::cEmptyString;
}
template <typename T>
inline s32 Flag<T>::getDeleteRev() const {
return mDebugData ? mDebugData->delete_rev : -1;
}
template <typename T>
inline u32 Flag<T>::getRandomResetData() const {
const auto& initial_value = getConfig().initial_value;
if constexpr (std::is_same<T, bool>())
return initial_value >> 1;
else
return 0;
}
template <typename T>
inline const typename Flag<T>::ConfigType& Flag<T>::getConfig() const {
return mConfig;
}
template <typename T>
inline void Flag<T>::setConfig(const ConfigType& config) {
mConfig = config;
}
template <typename T>
inline T Flag<T>::getValue() const {
if constexpr (std::is_same<T, bool>())
return mValue & 1;
else
return mValue;
}
template <typename T>
inline typename Flag<T>::RawValueType& Flag<T>::getValueRef() {
return mValue;
}
template <typename T>
inline const typename Flag<T>::RawValueType& Flag<T>::getValueRef() const {
return mValue;
}
template <typename T>
inline bool Flag<T>::hasValue(const T& value) const {
return value == getValue();
}
template <typename T>
inline bool Flag<T>::setValue(T value) {
if constexpr (std::is_same<T, bool>()) {
if (value == getValue())
return false;
if (value)
mValue |= 1;
else
mValue &= ~1;
return true;
} else {
[[maybe_unused]] const T new_value = value;
T min_value;
T max_value;
min_value = getConfig().min_value;
max_value = getConfig().max_value;
clampValue_(min_value, &value, max_value);
if (mValue != value) {
mValue = value;
return true;
}
return false;
}
}
template <typename T>
inline FlagDebugData* Flag<T>::getDebugData() const {
return mDebugData;
}
} // namespace ksys::gdt