Crafter.Graphics/interfaces/Crafter.Graphics-UIScene.cppm

112 lines
3.9 KiB
Text
Raw Normal View History

2026-05-01 23:35:37 +02:00
/*
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:UIScene;
import std;
import :Window;
import :Types;
import :DescriptorHeapVulkan;
import Crafter.Event;
import :UIWidget;
import :UIWidgets;
import :UILayout;
import :UIDrawList;
import :UIRenderer;
import :UIHit;
export namespace Crafter::UI {
// The single user-facing wrapper that ties the widget tree to the
// window's frame loop. Owns the renderer + draw list, optionally
// owns a default descriptor heap, registers itself as a RenderPass on
// the window, and routes mouse clicks through the hit tester.
//
// Typical usage:
//
// Crafter::Window window(1280, 720, "Demo");
// window.StartInit(); window.FinishInit();
// Crafter::UI::UIScene scene;
// scene.Initialize(window);
// scene.Root(VStack{}.children(
// Button{"Play"}.onClick([&]{ ... }),
// ...
// ));
// window.Render();
// window.StartUpdate(); // continuous rendering
// window.StartSync();
class UIScene {
public:
UIRenderer renderer;
DrawList drawList;
UIScene() = default;
UIScene(const UIScene&) = delete;
UIScene& operator=(const UIScene&) = delete;
~UIScene();
void Initialize(Window& window,
const std::filesystem::path& spvPath = "ui.comp.spv");
// Replace the widget tree. Takes ownership and clears focus
// (the previously-focused widget will be destroyed with the
// old tree).
template<typename W>
requires std::derived_from<std::remove_cvref_t<W>, Widget>
void Root(W&& root) {
SetFocus(nullptr);
using T = std::remove_cvref_t<W>;
auto p = std::make_unique<T>(std::move(root));
p->parent = nullptr;
root_ = std::move(p);
}
// Focus management. Calling with nullptr blurs whatever was focused.
void SetFocus(Widget* w);
Widget* Focused() const { return focused_; }
// Optional surface-clearing colour. The swapchain image is
// STORAGE-only (can't be vkCmdClearColorImage'd), so we paint a
// full-surface rect at the start of every frame's draw list when
// this is set.
UIScene& background(Color c) { background_ = c; return *this; }
Widget* root() { return root_.get(); }
const Widget* root() const { return root_.get(); }
private:
Window* window_ = nullptr;
std::unique_ptr<Widget> root_;
std::optional<Color> background_;
// Auto-allocated heap for UI-only apps. If the user already attached
// a heap to the window, we leave it alone and don't own one.
DescriptorHeapVulkan ownedHeap_;
bool ownsHeap_ = false;
std::unique_ptr<EventListener<void>> mouseListener_;
std::unique_ptr<EventListener<FrameTime>> updateListener_;
std::unique_ptr<EventListener<const std::string_view>> textListener_;
std::unique_ptr<EventListener<CrafterKeys>> keyListener_;
Widget* focused_ = nullptr;
2026-05-02 00:03:24 +02:00
float elapsedSec_ = 0.0f;
2026-05-01 23:35:37 +02:00
float WindowScale() const;
void RebuildFrame();
};
}