111 lines
3.9 KiB
C++
111 lines
3.9 KiB
C++
/*
|
|
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;
|
|
|
|
float WindowScale() const;
|
|
void RebuildFrame();
|
|
};
|
|
}
|