/* Crafter®.Graphics Copyright (C) 2026 Catcrafts® catcrafts.net This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3.0 as published by the Free Software Foundation; This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ module; #include "vulkan/vulkan.h" export module Crafter.Graphics:UIComponents; import std; import :UI; import :Font; import :FontAtlas; // Tier 3: stateless presentation functions. These append items to the user's // QuadItem / GlyphItem buffers — they do NOT dispatch. The user dispatches // via UIRenderer::DispatchQuads / DispatchText after their onBuild fills // everything, so a frame stays one quads dispatch + one text dispatch // regardless of how many components were drawn. // // State for components that need it (hovered, pressed, dragging, t01) is the // USER's responsibility — these functions are pure presentation. // // EXTENSION MODEL: each function below is short on purpose. If you want a // hexagon button, an icon-with-label button, a tristate checkbox — copy the // function body into your code and modify it. There is no override hook. export namespace Crafter { // Aggregate for the standard item buffers + the optional text-shaping // deps. Build one per frame in onBuild and pass it to component calls. // Any pointer left null causes the corresponding component to be a no-op // (so a frame that doesn't draw images can leave `images` unset). struct UIBuffer { QuadItem* quads = nullptr; std::uint32_t* quadCount = nullptr; std::uint32_t quadCap = 0; GlyphItem* glyphs = nullptr; std::uint32_t* glyphCount = nullptr; std::uint32_t glyphCap = 0; ImageItem* images = nullptr; std::uint32_t* imageCount = nullptr; std::uint32_t imageCap = 0; FontAtlas* atlas = nullptr; // for text-emitting components UIRenderer* renderer = nullptr; // for ShapeText }; // ─── per-component color blocks ───────────────────────────────────── // Inline POD aggregates. Users compose their own application-level theme // by holding a few of these together; the library has no Theme type. struct ButtonColors { std::array bg; std::array bgHover; std::array bgPressed; std::array text; std::array border = {0, 0, 0, 0}; float cornerRadius = 0; float borderThickness = 0; }; struct CheckboxColors { std::array bg; std::array bgHover; std::array check; std::array border = {0, 0, 0, 0}; float cornerRadius = 4; float borderThickness = 1; float checkInset = 4; // px on each side }; struct SliderColors { std::array track; std::array trackFilled; std::array thumb; std::array thumbHover; float trackHeight = 4; float thumbRadius = 8; }; struct ProgressColors { std::array bg; std::array fill; float cornerRadius = 0; }; // Where the X coordinate sits relative to the emitted glyph run. enum class TextAlign : std::uint8_t { Left, Center, Right }; // ─── component functions ─────────────────────────────────────────── // Background quad (color depends on state) + centered label glyphs. void DrawButton(UIBuffer& buf, Rect r, std::string_view label, bool hovered, bool pressed, Font& font, float fontSize, const ButtonColors& c); // Outlined quad + a smaller filled inset quad when `checked`. void DrawCheckbox(UIBuffer& buf, Rect r, bool checked, bool hovered, const CheckboxColors& c); // Thin track quad split at `t01` into filled/empty + a circular thumb // (drawn as a quad with cornerRadius = thumbRadius). void DrawSlider(UIBuffer& buf, Rect r, float t01, bool dragging, const SliderColors& c); // Background quad + a filled quad clipped to t01 of the inner width. void DrawProgressBar(UIBuffer& buf, Rect r, float t01, const ProgressColors& c); // Single-line text emit. `(x, baselineY)` is the start position; horizontal // alignment shifts the run after shaping. Returns the advance width that // was written. No line-wrap, no kerning — same shaping rules as // UIRenderer::ShapeText (which this calls). float DrawText(UIBuffer& buf, std::string_view text, float x, float baselineY, Font& font, float fontSize, std::array color, TextAlign align = TextAlign::Left); // Sampled image quad. The texture and sampler must already have heap // slots (UIRenderer::RegisterImage / RegisterSampler). `uv` is // {u0, v0, u1, v1} into the source texture; defaults to the full image. void DrawImage(UIBuffer& buf, Rect r, std::uint32_t textureSlot, std::uint32_t samplerSlot, std::array tint = {1, 1, 1, 1}, std::array uv = {0, 0, 1, 1}); }