Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animatable template shenanigans + some template improvements #1323

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/Utilities/Savegame.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,25 @@
#include <memory>
#include <type_traits>

namespace Savegame {
namespace Savegame
{
template <typename T>
concept ImplementsUpperCaseSaveLoad = requires (PhobosStreamWriter& stmWriter, PhobosStreamReader& stmReader, T& value, bool registerForChange)
{
value.Save(stmWriter);
value.Load(stmReader, registerForChange);
};

template <typename T>
concept ImplementsLowerCaseSaveLoad = requires (PhobosStreamWriter & stmWriter, PhobosStreamReader & stmReader, T& value, bool registerForChange)
{
value.save(stmWriter);
value.load(stmReader, registerForChange);
};

template <typename T>
concept ImplementsSaveLoad = ImplementsUpperCaseSaveLoad<T> || ImplementsLowerCaseSaveLoad<T>;

template <typename T>
bool ReadPhobosStream(PhobosStreamReader& Stm, T& Value, bool RegisterForChange = true);

Expand Down
14 changes: 0 additions & 14 deletions src/Utilities/SavegameDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,6 @@

namespace Savegame
{
template <typename T>
concept ImplementsUpperCaseSaveLoad = requires (PhobosStreamWriter& stmWriter, PhobosStreamReader& stmReader, T& value, bool registerForChange)
{
value.Save(stmWriter);
value.Load(stmReader, registerForChange);
};

template <typename T>
concept ImplementsLowerCaseSaveLoad = requires (PhobosStreamWriter & stmWriter, PhobosStreamReader & stmReader, T& value, bool registerForChange)
{
value.save(stmWriter);
value.load(stmReader, registerForChange);
};

#pragma warning(push)
#pragma warning(disable: 4702) // MSVC isn't smart enough and yells about unreachable code

Expand Down
91 changes: 91 additions & 0 deletions src/Utilities/Template.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,4 +482,95 @@
size_t ValueCount;
};

// Designates that the type can read it's value from multiple flags.
template<typename T, typename... TExtraArgs>
concept MultiflagReadable = requires(T obj, INI_EX& const parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs)
{
{ obj.Read(parser, pSection, pBaseFlag, extraArgs...) } -> std::same_as<bool>;
};

template<typename T, typename... TExtraArgs>
requires MultiflagReadable<T, TExtraArgs...>
class MultiflagValueableVector : public ValueableVector<T>
{
inline void Read(INI_EX& const parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs);

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

anachronism used: qualifiers on reference are ignored [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

inline void Read(INI_EX& const parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs); [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

^ (compiling source file src\Ext\Techno\Body.Visuals.cpp) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

anachronism used: qualifiers on reference are ignored [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

inline void Read(INI_EX& const parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs); [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

^ (compiling source file src\Ext\Techno\Body.cpp) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

anachronism used: qualifiers on reference are ignored [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

inline void Read(INI_EX& const parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs); [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

^ (compiling source file src\Ext\Techno\Hooks.Cloak.cpp) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check warning on line 496 in src/Utilities/Template.h

View workflow job for this annotation

GitHub Actions / build

anachronism used: qualifiers on reference are ignored [D:\a\Phobos\Phobos\Phobos.vcxproj]
};

template<typename T, typename... TExtraArgs>
requires MultiflagReadable<T, TExtraArgs...>
class MultiflagNullableVector : public NullableVector<T>
{
inline void Read(INI_EX& const parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs);
};

// Need multiple args or multiple return values? Use std::tuple - Kerbiter
// template<typename TArg, typename TValue>
// class Calculatable
// {
// public:

// virtual TValue Get(TArg const arg) const noexcept = 0;

// virtual void Read(INI_EX& const parser, const char* const pSection, const char* const pBaseFlag) = 0;

// virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange) = 0;

// virtual bool Save(PhobosStreamWriter& Stm) const = 0;
// };

// template<typename TArg>
// class ArgBoundable
// {
// public:

// virtual Vector2D<TArg> GetArgBounds() const noexcept = 0;
// };

// template<typename TValue>
// class ValueBoundable
// {
// public:

// virtual Vector2D<TValue> GetValueBounds() const noexcept = 0;
// };


template<typename TValue>
class Animatable // : public Calculatable<double, TValue> //, public ArgBoundable<int>
{
public:
using absolute_length_t = int;

class KeyframeDataEntry
{
public:
Valueable<double> Percentage;
Valueable<TValue> Value;

inline bool Read(INI_EX& const parser, const char* const pSection, const char* const pBaseFlag, absolute_length_t& const absoluteLength = 0);

inline bool Load(PhobosStreamReader& Stm, bool RegisterForChange);

inline bool Save(PhobosStreamWriter& Stm) const;
};

MultiflagValueableVector<KeyframeDataEntry, absolute_length_t> KeyframeData;

// TODO ctors and stuff

inline TValue Get(double const percentage) const noexcept;

// inline TValue Get(int const frame) const noexcept;

// Vector2D<TArg> GetArgBounds() const noexcept override;

inline void Read(INI_EX& const parser, const char* const pSection, const char* const pBaseFlag, absolute_length_t& const absoluteLength = 0);

inline bool Load(PhobosStreamReader& Stm, bool RegisterForChange);

inline bool Save(PhobosStreamWriter& Stm) const;
};

static_assert(Savegame::ImplementsSaveLoad<Animatable<std::monostate>::KeyframeDataEntry>);

static_assert(Savegame::ImplementsSaveLoad<Animatable<std::monostate>>);
120 changes: 120 additions & 0 deletions src/Utilities/TemplateDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,8 @@
Debug::INIParseFailed(pSection, pKey, pCur);
}
}

// TODO detail::interpolate
}


Expand Down Expand Up @@ -1747,3 +1749,121 @@
&& Savegame::WritePhobosStream(Stm, this->ConditionYellow)
&& Savegame::WritePhobosStream(Stm, this->ConditionRed);
}

// MultiflagValueableVector

template<typename T, typename... TExtraArgs>
requires MultiflagReadable<T, TExtraArgs...>
void __declspec(noinline) MultiflagValueableVector<T, TExtraArgs...>::Read(INI_EX& parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs)
{
char flagName[0x40];
for (size_t i = 0; ; ++i)
{
T dataEntry {};

// we expect %d for array number then %s for the subflag name, so we replace %s with itself (but escaped)
_snprintf_s(flagName, sizeof(flagName), pBaseFlag, i, "%%s");

if (!dataEntry.Read(parser, pSection, flagName, extraArgs...))
break;

this->push_back(dataEntry);
}
}

// MultiflagNullableVector

template<typename T, typename... TExtraArgs>
requires MultiflagReadable<T, TExtraArgs...>
void __declspec(noinline) MultiflagValueableVector<T, TExtraArgs...>::Read(INI_EX& parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs)
{
char flagName[0x40];
for (size_t i = 0; ; ++i)
{
T dataEntry {};

// we expect %d for array number then %s for the subflag name, so we replace %s with itself (but escaped)
_snprintf_s(flagName, sizeof(flagName), pBaseFlag, i, "%%s");

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

'void MultiflagValueableVector<T,TExtraArgs...>::Read(INI_EX &,const char *const ,const char *const ,TExtraArgs &...)': function template has already been defined [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

void __declspec(noinline) MultiflagValueableVector<T, TExtraArgs...>::Read(INI_EX& parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

^ (compiling source file src\Ext\Techno\Hooks.Cloak.cpp) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

'void MultiflagValueableVector<T,TExtraArgs...>::Read(INI_EX &,const char *const ,const char *const ,TExtraArgs &...)': function template has already been defined [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

void __declspec(noinline) MultiflagValueableVector<T, TExtraArgs...>::Read(INI_EX& parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

^ (compiling source file src\Ext\Techno\Hooks.Pips.cpp) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

'void MultiflagValueableVector<T,TExtraArgs...>::Read(INI_EX &,const char *const ,const char *const ,TExtraArgs &...)': function template has already been defined [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

void __declspec(noinline) MultiflagValueableVector<T, TExtraArgs...>::Read(INI_EX& parser, const char* const pSection, const char* const pBaseFlag, TExtraArgs& const... extraArgs) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

^ (compiling source file src\Ext\Techno\Body.Visuals.cpp) [D:\a\Phobos\Phobos\Phobos.vcxproj]

Check failure on line 1787 in src/Utilities/TemplateDef.h

View workflow job for this annotation

GitHub Actions / build

'void MultiflagValueableVector<T,TExtraArgs...>::Read(INI_EX &,const char *const ,const char *const ,TExtraArgs &...)': function template has already been defined [D:\a\Phobos\Phobos\Phobos.vcxproj]
if (!dataEntry.Read(parser, pSection, flagName, extraArgs...))
break;

this->push_back(dataEntry);
this->hasValue = true;
}
}

// Animatable

// Animatable::KeyframeDataEntry

template <typename TValue>
bool __declspec(noinline) Animatable<TValue>::KeyframeDataEntry::Read(INI_EX& parser, const char* const pSection, const char* const pBaseFlag, absolute_length_t& const absoluteLength)
{
char flagName[0x40];

Nullable<absolute_length_t> absoluteTemp {};

_snprintf_s(flagName, sizeof(flagName), pBaseFlag, "Percentage");
this->Percentage.Read(parser, pSection, flagName);

_snprintf_s(flagName, sizeof(flagName), pBaseFlag, "Absolute");
absoluteTemp.Read(parser, pSection, flagName);

if (!this->Frame.HasValue && !absoluteTemp.HasValue)
return false;

if (absoluteTemp.HasValue)
this->Percentage.Value = (double)absoluteTemp.Value / absoluteLength;

_snprintf_s(flagName, sizeof(flagName), pBaseFlag, "Value");
this->Value.Read(parser, pSection, flagName);

return true;
};

template <typename TValue>
bool Animatable<TValue>::KeyframeDataEntry::Load(PhobosStreamReader& Stm, bool RegisterForChange)
{
return Savegame::ReadPhobosStream(Stm, this->Percentage, RegisterForChange)
&& Savegame::ReadPhobosStream(Stm, this->Frame, RegisterForChange)
&& Savegame::ReadPhobosStream(Stm, this->Value, RegisterForChange);
}

template <typename TValue>
bool Animatable<TValue>::KeyframeDataEntry::Save(PhobosStreamWriter& Stm) const
{
return Savegame::WritePhobosStream(Stm, this->Percentage)
&& Savegame::WritePhobosStream(Stm, this->Frame)
&& Savegame::WritePhobosStream(Stm, this->Value);
}


template <typename TValue>
TValue Animatable<TValue>::Get(double const percentage) const noexcept
{
return detail::interpolate<TValue>(percentage); // TODO
}

template <typename TValue>
void __declspec(noinline) Animatable<TValue>::Read(INI_EX& parser, const char* const pSection, const char* const pBaseFlag, absolute_length_t& const absoluteLength)
{
char flagName[0x40];

// we expect "BaseFlagName.%s" here
_snprintf_s(flagName, sizeof(flagName), pBaseFlag, "Keyframe%%d.%%s");

this->KeyframeData.Read(parser, pSection, flagName, absoluteLength);
};

template <typename TValue>
bool Animatable<TValue>::Load(PhobosStreamReader& Stm, bool RegisterForChange)
{
return Savegame::ReadPhobosStream(Stm, this->KeyframeData, RegisterForChange);
}

template <typename TValue>
bool Animatable<TValue>::Save(PhobosStreamWriter& Stm) const
{
return Savegame::WritePhobosStream(Stm, this->KeyframeData);
}
Loading