#include "yardim_penceresi.hpp" #include #include "fiko/core/kare_istek.hpp" #include "fiko/ui/dinamik_doku.hpp" #include "fiko/ui/pencere_cerceve.hpp" #include "imgui.h" #include "ayar_kalici.hpp" #include "yardim_cef.hpp" namespace fiko { namespace { ui::DinamikDoku g_doku; // kalıcı (boyut değişince yeniden kurulur; stall'sız yükleme) // Boyut DEBOUNCE: sürükleyerek boyutlandırırken panel boyutu HER KARE değişir. Her // değişimde CEF'e WasResized + DinamikDoku yeniden kurulumu (vkDeviceWaitIdle + realloc) // yapmak kareyi düşürüyordu (ölçüldü 07-17: "boyut ayarlarken geç yapıyor"). Boyut bu // süre kadar SABİT kalınca uygulanır; sürükleme boyunca mevcut doku panele ölçeklenerek // çizilir (hafif bulanık → oturunca netleşir). constexpr float kBoyutGecikmeSn = 0.15f; int g_sonG = 0, g_sonY = 0; float g_sabitSure = 0.0f; bool g_boyutBekliyor = false; bool g_surukluyor = false; // sol düğme panelde basıldı → bırakılana dek olayları yakala int g_gpuBosKare = 0; // GPU modda paint gelmeyen kare sayısı (fallback eşiği) } // namespace void yardimPenceresiCiz(VulkanBaglam& vulkan, ImGuiKatman& arayuz) { if (!yardimCefAcikMi()) return; ui::Pencere pen{"📖 Yardım###yardim_cef", yardimCefAcikBayrak(), {.boyut = {960, 680}, .minBoyut = {420, 320}}}; if (pen) { const ImVec2 alan = ImGui::GetContentRegionAvail(); const int g = (int)std::max(alan.x, 64.0f); const int y = (int)std::max(alan.y, 64.0f); // Boyutu DEBOUNCE et: sürükleme sürerken CEF'e/dokuya dokunma (stall+realloc fırtınası). if (g != g_sonG || y != g_sonY) { g_sonG = g; g_sonY = y; g_sabitSure = 0.0f; g_boyutBekliyor = true; kareIste(2); } else if (g_boyutBekliyor) { g_sabitSure += ImGui::GetIO().DeltaTime; if (g_sabitSure >= kBoyutGecikmeSn) { yardimCefBoyut(g, y); // boyut oturdu → CEF yeniden düzenlesin (tek sefer) g_boyutBekliyor = false; } else { kareIste(2); } } if (yardimCefGpuHizli()) { // GPU-HIZLI: OnAcceleratedPaint kancası D3D11 shared texture'ı DinamikDoku'ya // GPU-GPU kopyalar (CPU'ya inmez). Kancayı her kare güncelle (vulkan/arayuz kare- // yakalı; g_doku d3dModu'da kurulur). Handle kanca içinde geçerli (keyed-mutex yok). yardimCefPaylasimKanca([&vulkan, &arayuz](void* handle, int hg, int hy) -> bool { if (!g_doku.boyutla(vulkan, arayuz, hg, hy, /*d3dModu*/ true)) return false; return g_doku.yukleD3DPaylasim(handle, hg, hy, /*paylasimNT*/ true); }); // Doku daha dolmadıysa CEF'i paint'e zorla (kaçan ilk OnAcceleratedPaint kurtarma). // Kanca artık set → sonraki pompadaki paint kancaya gider, doku dolar. if (!g_doku.doku() || g_doku.genislik() != g || g_doku.yukseklik() != y) { yardimCefYenile(); kareIste(2); // OTOMATİK FALLBACK: GPU modda ~1.2sn (72 kare) hiç paint gelmediyse (accel=0), // bu CEF/makinede shared texture çalışmıyor → software'e düş + kalıcı ayarı kapat // (sonraki açılışlar direkt software). Kullanıcı fark etmeden yardım çalışır. int a = 0, p = 0, ok = 0; yardimCefTeshis(&a, &p, &ok); if (a == 0 && ++g_gpuBosKare > 72) { yardimCefSoftwareGec(); ayarYaz("ayar.yardim.gpu_hizlandirma", "0"); g_gpuBosKare = 0; } } else { g_gpuBosKare = 0; } } else { // Yeni OnPaint karesi varsa dokuya yükle (memcpy + küçük transfer; device-idle YOK). const unsigned char* rgba = nullptr; int kg = 0, ky = 0; if (yardimCefKareAl(&rgba, &kg, &ky)) { if (g_doku.boyutla(vulkan, arayuz, kg, ky)) g_doku.yukle(rgba); } } const ImVec2 p = ImGui::GetCursorScreenPos(); if (g_doku.doku()) { // Panele ÖLÇEKLE çiz: sürükleme sırasında doku hâlâ eski boyutta olabilir; boyut // oturunca doku panelle birebir eşleşir → net görüntü. ImGui::Image((ImTextureID)g_doku.doku(), alan); } else { ImGui::TextDisabled("Yardım yükleniyor…"); if (yardimCefGpuHizli()) { int a = 0, p = 0, ok = 0; yardimCefTeshis(&a, &p, &ok); ImGui::TextColored(ImVec4(1, 0.7f, 0.3f, 1), "GPU teşhis → accel=%d paint=%d kopyaOK=%d", a, p, ok); if (a == 0 && p > 0) ImGui::TextDisabled("OnAcceleratedPaint gelmiyor, software'e düşülmüş (GPU shared " "texture desteklenmiyor). GPU hızlandırmayı kapatın."); } ImGui::Dummy(alan); } // ImGui::Image ETKİLEŞİMLİ ÖĞE DEĞİL → üstünde sürüklemek ImGui PENCERESİNİ taşır // (scrollbar tutulamaz). Aynı alanı kaplayan görünmez düğme fareyi yakalar ve // pencere taşımasını engeller → sürükleme CEF'e gider. ImGui::SetCursorScreenPos(p); ImGui::InvisibleButton("##yardim_alan", alan, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle); // ---- Fare olaylarını CEF'e ilet (panel-yerel piksel) ---- ImGuiIO& io = ImGui::GetIO(); const bool uzerinde = ImGui::IsItemHovered(); // Doku panele ölçekli çizildiği için (debounce penceresinde boyutlar ayrışır) // fare panel-yerelinden TARAYICI pikseline eşlenir → tık noktası kaymaz. const float olcX = g_doku.genislik() > 0 ? (float)g_doku.genislik() / std::max(alan.x, 1.0f) : 1.0f; const float olcY = g_doku.yukseklik() > 0 ? (float)g_doku.yukseklik() / std::max(alan.y, 1.0f) : 1.0f; const int fx = (int)((io.MousePos.x - p.x) * olcX); const int fy = (int)((io.MousePos.y - p.y) * olcY); // Basılı düğme + tuş durumu → CEF modifiers. Sürükleme (scrollbar tutma, metin // seçme) bunsuz ÇALIŞMAZ: CEF hareket olayında düğmeyi basılı görmeli. YardimFareDurum fd; fd.sol = io.MouseDown[ImGuiMouseButton_Left]; fd.sag = io.MouseDown[ImGuiMouseButton_Right]; fd.orta = io.MouseDown[ImGuiMouseButton_Middle]; fd.shift = io.KeyShift; fd.ctrl = io.KeyCtrl; fd.alt = io.KeyAlt; // CAPTURE: panel üstünde basıldıysa, sürükleme bitene kadar imleç DIŞARI çıksa da // hareket/bırakma CEF'e gider (aksi halde scrollbar yarı yolda takılı kalır). if (uzerinde && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { g_surukluyor = true; yardimCefFareTik(fx, fy, false, false, 1, fd); } if (uzerinde && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) yardimCefFareTik(fx, fy, true, false, 1, fd); if (uzerinde || g_surukluyor) yardimCefFareHareket(fx, fy, !uzerinde && !g_surukluyor, fd); if (ImGui::IsMouseReleased(ImGuiMouseButton_Left) && (g_surukluyor || uzerinde)) { yardimCefFareTik(fx, fy, false, true, 1, fd); g_surukluyor = false; } if (uzerinde && ImGui::IsMouseReleased(ImGuiMouseButton_Right)) yardimCefFareTik(fx, fy, true, true, 1, fd); if (uzerinde && (io.MouseWheel != 0.0f || io.MouseWheelH != 0.0f)) yardimCefFareTeker(fx, fy, (int)(io.MouseWheelH * 40.0f), (int)(io.MouseWheel * 40.0f), fd); if (uzerinde || g_surukluyor) kareIste(2); // etkileşim sürerken uyuma (on-demand) yardimCefOdak(ImGui::IsWindowFocused()); } } } // namespace fiko