#pragma once #include #include struct xcb_connection_t; class QByteArray; struct alignas(16) Vec4 { float x, y, z, w; }; namespace ffi { struct Core; struct ByteArray { std::byte* data; std::size_t length; }; enum class Mode : std::uint32_t { Solid, Shell, Mesh, }; struct ShapeArgs { Mode mode; std::uint32_t sides; std::uint32_t layers_up; std::uint32_t layers_down; float base_diameter; float height; float thickness; float line_width; }; struct RedrawArgs { ShapeArgs shape; Vec4 background; float camera_yaw; float camera_pitch; float light_yaw; float light_pitch; }; } // namespace ffi using ffi::Mode; using ffi::RedrawArgs; using ffi::ShapeArgs; /// Cast an integer to @c Mode, returning a fallback if the input is out of range. inline static Mode modeFromInt(std::uint32_t mode) { if (mode > (std::uint32_t)Mode::Mesh) return Mode::Solid; return (Mode)mode; } class MutCore { friend class BoxCore; public: explicit operator bool() const { return ptr; } void configure(std::uint32_t width, std::uint32_t height) const; void redraw(const RedrawArgs& args) const; private: ffi::Core* ptr = nullptr; ffi::Core* use() const; }; class BoxCore { public: BoxCore() = default; BoxCore(const BoxCore&) = delete; BoxCore(BoxCore&&); BoxCore& operator=(const BoxCore&) = delete; BoxCore& operator=(BoxCore&&); ~BoxCore(); explicit operator bool() const { return !!ptr; } const MutCore* operator->() const { return &ptr; } void reset(); static BoxCore from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height); private: MutCore ptr; }; QByteArray make_obj(const ShapeArgs& args);