nf7/common/generic_type_info.hh

68 lines
1.8 KiB
C++

#pragma once
#include <exception>
#include <memory>
#include <string>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <imgui.h>
#include "nf7.hh"
namespace nf7 {
template <typename T>
concept GenericTypeInfo_UpdateTooltip_ = requires() { T::UpdateTypeTooltip(); };
template <typename T>
concept GenericTypeInfo_Description_ = requires() { T::kTypeDescription; };
template <typename T>
class GenericTypeInfo : public nf7::File::TypeInfo {
public:
GenericTypeInfo(const std::string& name, std::unordered_set<std::string>&& v) noexcept :
TypeInfo(name, AddFlags(std::move(v))) {
}
std::unique_ptr<nf7::File> Deserialize(nf7::Deserializer& ar) const override
try {
return std::make_unique<T>(ar);
} catch (nf7::Exception&) {
throw nf7::DeserializeException {"deserialization failed"};
} catch (std::exception&) {
throw nf7::DeserializeException {"deserialization failed"};
}
std::unique_ptr<File> Create(nf7::Env& env) const override {
if constexpr (std::is_constructible<T, nf7::Env&>::value) {
return std::make_unique<T>(env);
} else {
throw nf7::Exception {name()+" has no factory without parameters"};
}
}
void UpdateTooltip() const noexcept override {
if constexpr (nf7::GenericTypeInfo_UpdateTooltip_<T>) {
T::UpdateTypeTooltip();
} else if constexpr (nf7::GenericTypeInfo_Description_<T>) {
ImGui::TextUnformatted(T::kTypeDescription);
} else {
ImGui::TextUnformatted("(no description)");
}
}
private:
static std::unordered_set<std::string> AddFlags(
std::unordered_set<std::string>&& flags) noexcept {
if (std::is_constructible<T, nf7::Env&>::value) {
flags.insert("nf7::File::TypeInfo::Factory");
}
return flags;
}
};
} // namespace nf7