6#include "common/config.h"
10#include <imgui_internal.h>
11#include <imgui_impl_sdl.h>
18#include <imgui_impl_vulkan.h>
19#include <vulkan/vulkan.h>
20#include <SDL2/SDL_vulkan.h>
35#ifndef EVENGINE_WEBGPU
36void checkVk(VkResult err) {
38 throw eve::Exception(
"ImGui Vulkan error: VkResult = %d",
int(err));
43constexpr float kBaseFontSizePx = 17.f;
46constexpr ImWchar kCjkProbeCodepoint = 0x4E2D;
48constexpr ImWchar kIconProbeCodepoint = 0xF002;
50std::vector<const char *> regularFontCandidates() {
52 static const std::string winDir = [] {
53 const char *
dir = getenv(
"WINDIR");
56 static const std::vector<std::string>
paths = {
57 winDir +
"\\Fonts\\segoeui.ttf", winDir +
"\\Fonts\\arial.ttf",
58 winDir +
"\\Fonts\\tahoma.ttf", winDir +
"\\Fonts\\msyh.ttc",
60#elif defined(__APPLE__)
61 static const std::vector<std::string>
paths = {
62 "/System/Library/Fonts/Helvetica.ttc",
63 "/System/Library/Fonts/SFNS.ttf",
64 "/Library/Fonts/Arial.ttf",
66#elif defined(EVENGINE_ANDROID)
67 static const std::vector<std::string>
paths = {
68 "/system/fonts/Roboto-Regular.ttf",
69 "/system/fonts/NotoSansCJK-Regular.ttc",
70 "/system/fonts/DroidSansFallback.ttf",
73 static const std::vector<std::string>
paths = {
74 "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
75 "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
76 "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
77 "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
78 "/usr/share/fonts/truetype/arphic/uming.ttc",
81 std::vector<const char *> out;
82 out.reserve(
paths.size());
83 for (
const auto &
p :
paths) out.push_back(
p.c_str());
90std::vector<const char *> cjkFontCandidates() {
92 static const std::string winDir = [] {
93 const char *
dir = getenv(
"WINDIR");
96 static const std::vector<std::string>
paths = {
97 winDir +
"\\Fonts\\msyh.ttc",
98 winDir +
"\\Fonts\\simhei.ttf",
99 winDir +
"\\Fonts\\simsun.ttc",
100 winDir +
"\\Fonts\\Deng.ttf",
101 winDir +
"\\Fonts\\msjh.ttc",
103#elif defined(__APPLE__)
104 static const std::vector<std::string>
paths = {
105 "/System/Library/Fonts/PingFang.ttc",
106 "/System/Library/Fonts/STHeiti Light.ttc",
107 "/System/Library/Fonts/Hiragino Sans GB.ttc",
108 "/System/Library/Fonts/Supplemental/Songti.ttc",
109 "/Library/Fonts/Arial Unicode.ttf",
111#elif defined(EVENGINE_ANDROID)
112 static const std::vector<std::string>
paths = {
113 "/system/fonts/NotoSansCJK-Regular.ttc",
114 "/system/fonts/DroidSansFallback.ttf",
115 "/system/fonts/NotoSansSC-Regular.otf",
118 static const std::vector<std::string>
paths = {
119 "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
120 "/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
121 "/usr/share/fonts/opentype/noto/NotoSansCJKsc-Regular.otf",
122 "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
123 "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
124 "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf",
125 "/usr/share/fonts/truetype/arphic/uming.ttc",
128 std::vector<const char *> out;
129 out.reserve(
paths.size());
130 for (
const auto &
p :
paths) out.push_back(
p.c_str());
134std::vector<std::string> iconFontCandidates() {
135 std::vector<std::string>
paths;
136 if (
const char *overridePath = getenv(
"EVENGINE_ICON_FONT")) {
137 if (*overridePath)
paths.emplace_back(overridePath);
139 if (
char *basePath = SDL_GetBasePath()) {
140 const std::filesystem::path base(basePath);
143 (base /
"../../share/eve/fonts/FontAwesome.ttf").lexically_normal().
string());
146 (base /
"../../../share/eve/fonts/FontAwesome.ttf").lexically_normal().
string());
148 (base /
"../share/eve/fonts/FontAwesome.ttf").lexically_normal().
string());
151 paths.emplace_back(
"share/eve/fonts/FontAwesome.ttf");
152 paths.emplace_back(
"fonts/FontAwesome.ttf");
153 paths.emplace_back(
"test/fonts/FontAwesome.ttf");
157bool fileExists(
const char *
path) {
159 FILE *
f = fopen(
path,
"rb");
160 if (!
f)
return false;
168 return std::make_unique<ImGuiBackend>();
174 if (initialized_)
return true;
175 if (!
window || !gfx)
return false;
176 StartupStage initStage(
"ui: ImGui backend init (first frame)");
180 dpiScale_ = computeDpiScale();
181 uiScale_ = computeInitialScale();
183 IMGUI_CHECKVERSION();
184 ctx_ = ::ImGui::CreateContext();
190 ImGui_ImplSDL2_InitForVulkan(
window);
192#ifdef EVENGINE_WEBGPU
194 if (!wgg)
return false;
198 fontsUploaded_ =
true;
202 if (!vkg)
return false;
203 if (!vkg->getSwapchainRenderPass())
return false;
206 VkDescriptorPoolSize poolSizes[] = {
207 {VK_DESCRIPTOR_TYPE_SAMPLER, 1000},
208 {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000},
209 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000},
210 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000},
211 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000},
212 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000},
213 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000},
214 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000},
215 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000},
216 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000},
217 {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000},
219 VkDescriptorPoolCreateInfo poolInfo{};
220 poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
221 poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
222 poolInfo.maxSets = 1000 * uint32_t(
sizeof(poolSizes) /
sizeof(poolSizes[0]));
223 poolInfo.poolSizeCount = uint32_t(
sizeof(poolSizes) /
sizeof(poolSizes[0]));
224 poolInfo.pPoolSizes = poolSizes;
226 VkDescriptorPool pool = VK_NULL_HANDLE;
227 checkVk(vkCreateDescriptorPool(
static_cast<VkDevice
>(
device.instance), &poolInfo,
nullptr, &pool));
228 imguiDescriptorPool_ = pool;
230 uint32_t imageCount = vkg->getSwapchainImageCount();
231 if (imageCount < 2) imageCount = 2;
233 vkg->ensureUiColorResources();
235 ImGui_ImplVulkan_InitInfo initInfo{};
236 initInfo.Instance =
static_cast<VkInstance
>(vkg->getInstance().instance);
237 initInfo.PhysicalDevice =
static_cast<VkPhysicalDevice
>(
device.physical_device.instance);
238 initInfo.Device =
static_cast<VkDevice
>(
device.instance);
239 initInfo.QueueFamily =
device.get_queue_index(vkb::QueueType::graphics);
240 initInfo.Queue =
static_cast<VkQueue
>(
device.getQueue(vkb::QueueType::graphics));
241 initInfo.PipelineCache = VK_NULL_HANDLE;
242 initInfo.DescriptorPool = pool;
243 initInfo.MinImageCount = imageCount;
244 initInfo.ImageCount = imageCount;
245 initInfo.MSAASamples =
static_cast<VkSampleCountFlagBits
>(vkg->getUiMsaaSamples());
246 initInfo.CheckVkResultFn = [](VkResult err) {
247 if (err != 0) fprintf(stderr,
"ImGui Vulkan: VkResult %d\n",
int(err));
250 ImGui_ImplVulkan_Init(&initInfo,
static_cast<VkRenderPass
>(vkg->getUiMsaaRenderPass()));
253 StartupStage fontStage(
" ui: font load + atlas upload");
256 vkb::executeImmediately(
device.instance, vkg->getUploadPool(),
257 device.getQueue(vkb::QueueType::graphics), [&](vk::CommandBuffer cb) {
258 ImGui_ImplVulkan_CreateFontsTexture(static_cast<VkCommandBuffer>(cb));
260 ImGui_ImplVulkan_DestroyFontUploadObjects();
261 fontsUploaded_ =
true;
271void ImGuiBackend::windowDestroyedThunk(
void *userdata) {
277 if (!initialized_)
return;
279 if (GImGui && GImGui->WithinFrameScope) ImGui::EndFrame();
285#ifdef EVENGINE_WEBGPU
287 ImGui_ImplSDL2_Shutdown();
288 ImGui::DestroyContext();
292 vkDeviceWaitIdle(
static_cast<VkDevice
>(vkg->getDevice().instance));
298 ::ImGuiContext *prev = ::ImGui::GetCurrentContext();
299 ::ImGuiContext *mine = ctx_;
300 ::ImGui::SetCurrentContext(mine);
301 ::ImGui_ImplVulkan_Shutdown();
302 ::ImGui_ImplSDL2_Shutdown();
303 ::ImGui::DestroyContext(mine);
307 if (prev && prev != mine) ::ImGui::SetCurrentContext(prev);
308 else ::ImGui::SetCurrentContext(
nullptr);
310 if (imguiDescriptorPool_ && vkg) {
311 vkDestroyDescriptorPool(
static_cast<VkDevice
>(vkg->getDevice().instance),
312 static_cast<VkDescriptorPool
>(imguiDescriptorPool_),
nullptr);
313 imguiDescriptorPool_ =
nullptr;
315 if (imguiTexturePool_ && vkg) {
316 vkDestroyDescriptorPool(
static_cast<VkDevice
>(vkg->getDevice().instance),
317 static_cast<VkDescriptorPool
>(imguiTexturePool_),
nullptr);
318 imguiTexturePool_ =
nullptr;
320 if (imguiTextureLayout_ && vkg) {
321 vkDestroyDescriptorSetLayout(
static_cast<VkDevice
>(vkg->getDevice().instance),
322 static_cast<VkDescriptorSetLayout
>(imguiTextureLayout_),
324 imguiTextureLayout_ =
nullptr;
328 queuedTextureDraws_.clear();
331 fontsUploaded_ =
false;
332 initialized_ =
false;
336 if (!initialized_ || !event)
return;
337 ImGui_ImplSDL2_ProcessEvent(event);
341 if (!initialized_ || !window_)
return;
342 queuedTextureDraws_.clear();
344 if (GImGui && GImGui->WithinFrameScope) ImGui::EndFrame();
347#ifdef EVENGINE_WEBGPU
350 ImGui_ImplVulkan_NewFrame();
352 ImGui_ImplSDL2_NewFrame(window_);
358void ImGuiBackend::applyScale(
float scale) {
359 if (!initialized_)
return;
371 if (!initialized_)
return;
375float ImGuiBackend::computeInitialScale()
const {
376#if defined(EVENGINE_ANDROID) || defined(EVENGINE_IOS)
378 if (SDL_GetDisplayDPI(0, &ddpi,
nullptr,
nullptr) != 0 || ddpi < 1.f) ddpi = 320.f;
379 float s = ddpi / 160.f;
380 return std::clamp(
s, 1.75f, 3.25f);
385 return computeDpiScale();
396float ImGuiBackend::computeDpiScale()
const {
398 const int display = window_ ? SDL_GetWindowDisplayIndex(window_) : 0;
400 if (display >= 0 && SDL_GetDisplayDPI(display, &ddpi,
nullptr,
nullptr) == 0 && ddpi > 0.f)
401 return std::clamp(ddpi / 96.f, 1.f, 4.f);
404 int logicalW = 0, logicalH = 0, pixelW = 0, pixelH = 0;
405 SDL_GetWindowSize(window_, &logicalW, &logicalH);
406#ifdef EVENGINE_WEBGPU
408 SDL_GetWindowSize(window_, &pixelW, &pixelH);
410 SDL_Vulkan_GetDrawableSize(window_, &pixelW, &pixelH);
412 if (logicalW > 0 && pixelW > 0) {
413 float s = float(pixelW) / float(logicalW);
414 if (
s > 0.f)
return std::clamp(
s, 1.f, 4.f);
420void ImGuiBackend::loadFonts() {
421 ImGuiIO &io = ImGui::GetIO();
422 ImFontAtlas *atlas = io.Fonts;
430 const float sizePx = kBaseFontSizePx * dpiScale_;
435 cfg.PixelSnapH =
true;
438 cfg.RasterizerMultiply = 1.12f;
442 ImFontGlyphRangesBuilder rangeBuilder;
443 rangeBuilder.AddRanges(atlas->GetGlyphRangesDefault());
444 rangeBuilder.AddRanges(atlas->GetGlyphRangesChineseFull());
445 rangeBuilder.BuildRanges(&fontRanges_);
446 cfg.GlyphRanges = fontRanges_.Data;
449 std::string primaryPath;
450 for (
const char *
path : regularFontCandidates()) {
451 if (!fileExists(
path))
continue;
452 if (atlas->AddFontFromFileTTF(
path, sizePx, &cfg)) {
458 if (!added) atlas->AddFontDefault(&cfg);
473 ImFontGlyphRangesBuilder cjkRangeBuilder;
474 cjkRangeBuilder.AddRanges(atlas->GetGlyphRangesChineseFull());
475 cjkRangeBuilder.BuildRanges(&cjkRanges_);
476 bool primaryIsCjk =
false;
477 for (
const char *
path : cjkFontCandidates()) {
478 if (primaryPath ==
path) {
484 ImFontConfig cjkCfg{};
487 cjkCfg.OversampleH = 1;
488 cjkCfg.OversampleV = 1;
489 cjkCfg.MergeMode =
true;
490 cjkCfg.GlyphRanges = cjkRanges_.Data;
491 for (
const char *
path : cjkFontCandidates()) {
492 if (!fileExists(
path))
continue;
493 if (atlas->AddFontFromFileTTF(
path, sizePx, &cjkCfg, cjkRanges_.Data))
break;
497 ImFontConfig iconCfg{};
498 iconCfg.OversampleH = 2;
499 iconCfg.OversampleV = 2;
500 iconCfg.MergeMode =
true;
501 iconCfg.PixelSnapH =
true;
502 static const ImWchar iconRanges[] = {0xF000, 0xF8FF, 0};
503 for (
const std::string &
path : iconFontCandidates()) {
504 if (!fileExists(
path.c_str()))
continue;
505 if (atlas->AddFontFromFileTTF(
path.c_str(), sizePx, &iconCfg, iconRanges))
break;
509void ImGuiBackend::checkFontCoverage()
const {
511 ImFontAtlas *atlas = ImGui::GetIO().Fonts;
512 if (!atlas || atlas->Fonts.Size == 0)
return;
513 const ImFont *font = atlas->Fonts[0];
514 if (font && font->FindGlyphNoFallback(kCjkProbeCodepoint) ==
nullptr)
516 "[ui] warning: no CJK-capable system font found; Chinese text will render as '?'\n");
517 if (font && font->FindGlyphNoFallback(kIconProbeCodepoint) ==
nullptr)
519 "[ui] warning: editor icon font not found; semantic icons will render as '?'\n");
522void ImGuiBackend::rebuildFonts() {
523#ifdef EVENGINE_WEBGPU
527 fontsUploaded_ =
true;
532 ImGui_ImplVulkan_DestroyFontUploadObjects();
533 auto &
device = vkg->getDevice();
534 vkb::executeImmediately(
device.instance, vkg->getUploadPool(),
535 device.getQueue(vkb::QueueType::graphics),
536 [&](vk::CommandBuffer cb) {
537 ImGui_ImplVulkan_CreateFontsTexture(
538 static_cast<VkCommandBuffer>(cb));
540 ImGui_ImplVulkan_DestroyFontUploadObjects();
541 fontsUploaded_ =
true;
545uint64_t ImGuiBackend::registerTexture(graphics::Texture *tex) {
546 if (!initialized_ || !tex || !tex->gpuHandle)
return 0;
547 RegisteredTexture reg;
549#ifdef EVENGINE_WEBGPU
551 reg.imId = (ImTextureID)(intptr_t)gt->
view.Get();
552 if (!reg.imId)
return 0;
557 const VkDevice
device =
static_cast<VkDevice
>(vkg->getDevice().instance);
558 if (!imguiTextureLayout_) {
559 VkDescriptorSetLayoutBinding
binding{};
561 binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
563 binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
564 VkDescriptorSetLayoutCreateInfo
info{};
565 info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
566 info.bindingCount = 1;
568 VkDescriptorSetLayout
layout = VK_NULL_HANDLE;
570 imguiTextureLayout_ =
layout;
572 if (!imguiTexturePool_) {
573 VkDescriptorPoolSize
size{};
574 size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
575 size.descriptorCount = 512;
576 VkDescriptorPoolCreateInfo
info{};
577 info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
578 info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
580 info.poolSizeCount = 1;
582 VkDescriptorPool pool = VK_NULL_HANDLE;
583 checkVk(vkCreateDescriptorPool(
device, &
info,
nullptr, &pool));
584 imguiTexturePool_ = pool;
586 VkDescriptorSet set = VK_NULL_HANDLE;
587 VkDescriptorSetAllocateInfo ai{};
588 ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
589 ai.descriptorPool =
static_cast<VkDescriptorPool
>(imguiTexturePool_);
590 ai.descriptorSetCount = 1;
591 const VkDescriptorSetLayout
layout =
static_cast<VkDescriptorSetLayout
>(imguiTextureLayout_);
593 checkVk(vkAllocateDescriptorSets(
device, &ai, &set));
594 VkDescriptorImageInfo imageInfo{};
595 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
596 imageInfo.imageView =
static_cast<VkImageView
>(gt->imageView());
597 imageInfo.sampler =
static_cast<VkSampler
>(gt->sampler);
598 VkWriteDescriptorSet write{};
599 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
601 write.dstBinding = 0;
602 write.descriptorCount = 1;
603 write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
604 write.pImageInfo = &imageInfo;
605 vkUpdateDescriptorSets(
device, 1, &write, 0,
nullptr);
608 reg.width = tex->getWidth();
609 reg.height = tex->getHeight();
610 const uint64_t
key = nextTextureKey_++;
611 textures_[
key] = reg;
615void ImGuiBackend::unregisterTexture(uint64_t
id) {
616 auto it = textures_.find(
id);
617 if (it == textures_.end())
return;
618#ifndef EVENGINE_WEBGPU
620 if (vkg && imguiTexturePool_) {
621 VkDescriptorSet set =
static_cast<VkDescriptorSet
>(it->second.imId);
622 vkFreeDescriptorSets(
static_cast<VkDevice
>(vkg->getDevice().instance),
623 static_cast<VkDescriptorPool
>(imguiTexturePool_), 1, &set);
629bool ImGuiBackend::textureSize(uint64_t
id,
int *
w,
int *
h)
const {
630 auto it = textures_.find(
id);
631 if (it == textures_.end())
return false;
632 if (
w) *
w = it->second.width;
633 if (
h) *
h = it->second.height;
637void *ImGuiBackend::textureHandle(uint64_t
id)
const {
638 auto it = textures_.find(
id);
639 return it == textures_.end() ? nullptr :
static_cast<void *
>(it->second.imId);
642bool ImGuiBackend::usesQueuedTextureDraws()
const {
643#ifdef EVENGINE_WEBGPU
653void ImGuiBackend::queueTextureDraw(uint64_t
id,
float x,
float y,
float w,
float h,
float u0,
654 float v0,
float u1,
float v1,
float r,
float g,
float b,
655 float a,
bool opaque) {
656 if (!usesQueuedTextureDraws() ||
id == 0 || textures_.find(
id) == textures_.end())
return;
657 const ImVec2
scale = ImGui::GetIO().DisplayFramebufferScale;
658 const ImVec4
clip = ImGui::GetWindowDrawList()->_ClipRectStack.back();
659 queuedTextureDraws_.push_back({
id,
678 queuedTextureDraws_.size()});
679 ImDrawList*
list = ImGui::GetWindowDrawList();
680 list->AddCallback(textureDrawThunk, &queuedTextureDraws_.back());
681 list->AddCallback(ImDrawCallback_ResetRenderState,
nullptr);
685 if (!initialized_)
return false;
686 return ImGui::GetIO().WantCaptureMouse;
690 if (!initialized_)
return false;
691 return ImGui::GetIO().WantCaptureKeyboard;
694void ImGuiBackend::renderDrawData(
void *commandBuffer) {
695 if (!initialized_ || !commandBuffer)
return;
696 if (!GImGui || !GImGui->WithinFrameScope)
return;
699#ifdef EVENGINE_WEBGPU
700 WGPURenderPassEncoder enc = *
static_cast<WGPURenderPassEncoder *
>(commandBuffer);
703 activeCommandBuffer_ = commandBuffer;
705 ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(),
static_cast<VkCommandBuffer
>(commandBuffer));
707 activeCommandBuffer_ =
nullptr;
710 activeCommandBuffer_ =
nullptr;
714void ImGuiBackend::textureDrawThunk(
const ImDrawList*,
const ImDrawCmd* command) {
715#ifndef EVENGINE_WEBGPU
716 const auto&
queued = *
static_cast<const QueuedTextureDraw*
>(command->UserCallbackData);
717 auto& owner = *
queued.owner;
719 if (!vkg || !owner.activeCommandBuffer_)
return;
720 const auto found = owner.textures_.find(
queued.id);
721 if (
found == owner.textures_.end() || !
found->second.texture)
return;
738 vkg->drawUiTextureRects(owner.activeCommandBuffer_, {draw},
queued.bufferIndex);
744bool ImGuiBackend::presentOverlayThunk(
void *userdata,
void *commandBuffer) {
746 if (!self || !self->initialized_ || !GImGui || !GImGui->WithinFrameScope)
return false;
747 if (commandBuffer) self->renderDrawData(commandBuffer);
std::array< float, 3 > scale
eve::action::ActionVfxBinding binding
std::map< std::string, std::string > paths
EVENGINE_API_FOUNDATION public API.
void addWindowDestroyedCallback(WindowDestroyedCallback cb, void *userdata)
Adds window destroyed callback.
void * getPresentOverlayUser() const
Returns the present overlay user.
void setPresentOverlay(PresentOverlayFn fn, void *userdata)
Sets the present overlay.
EVENGINE_API_BACKENDS public API.
vkb::Device & getDevice()
Returns the device.
EVENGINE_API_BACKENDS public API.
Dear ImGui + SDL input + Vulkan present overlay.
void shutdown() override
Shutdown.
bool wantCaptureKeyboard() const override
Want capture keyboard.
void newFrame() override
Creates a frame. @ownership Caller deletes unless documented otherwise.
bool init(SDL_Window *window, eve::graphics::Graphics *gfx) override
Initializes .
~ImGuiBackend() override
Releases ImGuiBackend resources.
ImGuiBackend()=default
Constructs a ImGuiBackend.
bool wantCaptureMouse() const override
Want capture mouse.
void setScale(float scale) override
Sets the scale.
void processEvent(const SDL_Event *event) override
Process event.
IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame()
Im gui impl wgpu new frame.
IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateFontsTexture()
Im gui impl wgpu create fonts texture.
IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData *draw_data, WGPURenderPassEncoder pass_encoder)
Im gui impl wgpu render draw data.
IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format)
Im gui impl wgpu init.
IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown()
Im gui impl wgpu shutdown.
IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects()
Im gui impl wgpu invalidate device objects.
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
void setThemeDpiScale(float dpiScale)
Sets the theme dpi scale.
void setThemeUiScale(float scale)
Logical (point-space) UI scale. Default 1.0.
WidgetDesc window(std::string title, std::vector< WidgetDesc > children, std::string id)
Top-level window widget with a title bar.
Theme & globalTheme()
Global theme.
void applyThemeToImGui(const Theme &theme)
Push tokens into ImGui style. Metrics are multiplied by uiScale (default: themeUiScale()).
std::unique_ptr< UIBackend > createImGuiBackend()
Default backend: Dear ImGui + SDL + Vulkan (see ui/imgui/).
WidgetDesc list(std::string listId, const std::vector< std::string > &items, const std::function< WidgetDesc(const std::string &, int)> &itemFn)
Expand a string list into a Group of item widgets. itemFn(label, index) builds each row; keys default...
Backend-internal textured rectangle queued by a UI presenter.
Texture resources backed by a wgpu texture + view + sampler + bind groups.