nf7/file/gl_obj.cc
2022-10-06 10:52:19 +09:00

240 lines
5.9 KiB
C++

#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <typeinfo>
#include <vector>
#include <imgui.h>
#include <imgui_stdlib.h>
#include <implot.h>
#include <magic_enum.hh>
#include <yaml-cpp/yaml.h>
#include <yas/serialize.hpp>
#include <yas/types/utility/usertype.hpp>
#include "nf7.hh"
#include "common/dir_item.hh"
#include "common/generic_context.hh"
#include "common/generic_memento.hh"
#include "common/generic_type_info.hh"
#include "common/gl_obj.hh"
#include "common/life.hh"
#include "common/node.hh"
#include "common/ptr_selector.hh"
#include "common/yas_enum.hh"
namespace nf7 {
namespace {
template <typename T>
class ObjBase final : public nf7::File,
public nf7::DirItem, public nf7::Node, public T {
public:
ObjBase(nf7::File::TypeInfo& t, nf7::Env& env,
std::span<const std::string> inputs,
std::span<const std::string> outputs) noexcept :
nf7::File(t, env),
nf7::DirItem(nf7::DirItem::kTooltip),
nf7::Node(nf7::Node::kNone),
inputs_(inputs), outputs_(outputs) {
}
std::span<const std::string> GetInputs() const noexcept override {
return inputs_;
}
std::span<const std::string> GetOutputs() const noexcept override {
return outputs_;
}
Product Create() noexcept final {
if (!prod_) {
prod_ = Create_();
}
return *prod_;
}
nf7::File::Interface* interface(const std::type_info& t) noexcept override {
return nf7::InterfaceSelector<nf7::DirItem, T>(t).Select(this);
}
protected:
virtual Product Create_() noexcept = 0;
void DropCache() noexcept {
prod_ = std::nullopt;
}
const Product& prod() const noexcept {
// Product is always wrapped nf7::Future
return prod_ && prod_->done()? prod_->value(): nullptr;
}
private:
std::span<const std::string> inputs_;
std::span<const std::string> outputs_;
std::optional<Product> prod_;
};
class Buffer final : public ObjBase<nf7::gl::BufferFactory> {
public:
static inline const nf7::GenericTypeInfo<Buffer> kType = {
"GL/Buffer", {"nf7::DirItem",}};
static void UpdateTypeTooltip() noexcept {
ImGui::TextUnformatted("OpenGL buffer");
}
static inline const std::vector<std::string> kInputs = {
"resize", "upload", "download",
};
static inline const std::vector<std::string> kOutputs = {
"result",
};
class Lambda;
enum Type {
kArray,
kElement,
};
enum Usage {
kStaticDraw,
kDynamicDraw,
kStreamDraw,
kStaticRead,
kDynamicRead,
kStreamRead,
kStaticCopy,
kDynamicCopy,
kStreamCopy,
};
struct Data {
Type type;
Usage usage;
void serialize(auto& ar) {
ar(type, usage);
}
std::string Stringify() noexcept;
void Parse(const std::string& v);
};
Buffer(nf7::Env& env) noexcept :
ObjBase(kType, env, kInputs, kOutputs) {
}
Buffer(nf7::Deserializer& ar) noexcept : Buffer(ar.env()) {
ar(mem_.data());
}
void Serialize(nf7::Serializer&) const noexcept override {
ar(mem_.data());
}
std::unique_ptr<nf7::File> Clone(nf7::Env& env) const noexcept override {
return std::make_unique<Buffer>(env);
}
std::shared_ptr<nf7::Node::Lambda> CreateLambda(
const std::shared_ptr<nf7::Node::Lambda>& parent) noexcept override;
Product Create_() noexcept override {
// TODO
std::abort();
}
void UpdateTooltip() noexcept override {
if (auto prod = product()) {
ImGui::Text("size: %zu bytes", );
}
}
private:
nf7::Life<Buffer> life_;
nf7::GenericMemento<Data> data_;
};
std::string Buffer::Data::Stringify() noexcept {
YAML::Emitter st;
st << YAML::BeginMap;
st << YAML::Key << "type";
st << YAML::Value << std::string {magic_enum::enum_name(type)};
st << YAML::Key << "usage";
st << YAML::Value << std::string {magic_enum::enum_name(usage)};
st << YAML::EndMap;
return std::string {st.c_str(), st.size()};
}
void Buffer::Data::Parse(const std::string&)
try {
const auto yaml = YAML::Load(v);
const auto new_type = magic_enum::
enum_cast<Type>(yaml["type"].as<std::string>()).value();
const auto new_usage = magic_enum::
enum_cast<Usage>(yaml["usage"].as<std::string>()).value();
type = new_type;
usage = new_usage;
} catch (std::bad_optional_access&) {
throw nf7::Exception {"unknown enum"};
} catch (YAML::Exception& e) {
throw nf7::Exception {std::string {"YAML error: "}+e.what()};
}
}
} // namespace nf7
namespace magic_enum::customize {
template <>
constexpr customize_t magic_enum::customize::enum_name<nf7::Buffer::Type>(nf7::Buffer::Type v) noexcept {
switch (v) {
case nf7::Buffer::Type::kArray: return "array";
case nf7::Buffer::Type::kElement: return "element";
}
return invalid_tag;
}
template <>
constexpr customize_t magic_enum::customize::enum_name<nf7::BUffer::Usage>(nf7::Plot::SeriesFormat v) noexcept {
switch (v) {
case nf7::Buffer::Usage::kStaticDraw: return "StaticDraw";
case nf7::Buffer::Usage::kDynamicDraw: return "DynamicDraw";
case nf7::Buffer::Usage::kStreamDraw: return "StreamDraw";
case nf7::Buffer::Usage::kStaticRead: return "StaticRead";
case nf7::Buffer::Usage::kDynamicRead: return "DynamicRead";
case nf7::Buffer::Usage::kStreamRead: return "StreamRead";
case nf7::Buffer::Usage::kStaticCopy: return "StaticCopy";
case nf7::Buffer::Usage::kDynamicCopy: return "DynamicCopy";
case nf7::Buffer::Usage::kStreamCopy: return "StreamCopy";
}
return invalid_tag;
}
} // namespace magic_enum::customize
namespace yas::detail {
template <size_t F>
struct serializer<
yas::detail::type_prop::is_enum,
yas::detail::ser_case::use_internal_serializer,
F, nf7::Plot::SeriesType> :
nf7::EnumSerializer<nf7::Plot::SeriesType> {
};
template <size_t F>
struct serializer<
yas::detail::type_prop::is_enum,
yas::detail::ser_case::use_internal_serializer,
F, nf7::Plot::SeriesFormat> :
nf7::EnumSerializer<nf7::Plot::SeriesFormat> {
};
} // namespace yas::detail