#pragma once #include #include #include "buffer.hpp" #include "types.hpp" template class VertexArray { public: template using Fmt = std::tuple_element_t>; private: GLuint id = 0; template inline void formatall( std::integer_sequence ) { (AutoFormat::Fmt::apply(id, idx), ...); } template inline void bindall( const Binder &...buf, std::integer_sequence ) { (buf.bind(id, idx), ...); } public: explicit VertexArray() { glCreateVertexArrays(1, &id); formatall(std::make_index_sequence()); } explicit VertexArray(const Binder &...buf) : VertexArray() { bind(buf...); } VertexArray(VertexArray &&o) noexcept { id = std::exchange(o.id, 0); } VertexArray(const VertexArray &) = delete; // this is doable, but would be slow. ~VertexArray() { glDeleteVertexArrays(1, &id); } operator GLuint() const { // NOLINT(google-explicit-constructor) return id; } void bind(const Binder &...buf) { bindall(buf..., std::make_index_sequence()); } template void bind(const Binder> &buf) { buf.bind(id, idx); } };