#include "fiko/ui/bilesen.hpp" #include #include #include #include "fiko/ui/animasyon.hpp" #include "fiko/ui/tema.hpp" #include "imgui_internal.h" namespace fiko::ui { void glowCerceve(ImDrawList* dl, ImVec2 min, ImVec2 max, const ImVec4& renk, float yuvarlak, float siddet) { if (siddet <= 0.01f) return; const float s = siddet * tema().glowSiddet; for (int i = 1; i <= 3; ++i) { const float y = (float)i * 1.6f; dl->AddRect({min.x - y, min.y - y}, {max.x + y, max.y + y}, u32(renk, 0.16f * s / (float)i), yuvarlak + y, 0, 2.0f); } } namespace { // Son eklenen vertexlere dikey gradient (yuvarlak köşe korunur). void dikeyGradient(ImDrawList* dl, int vtx0, ImVec2 min, ImVec2 max, ImU32 ust, ImU32 alt) { ImGui::ShadeVertsLinearColorGradientKeepAlpha(dl, vtx0, dl->VtxBuffer.Size, min, {min.x, max.y}, ust, alt); } struct KartDurum { ImVec2 baslangic; float genislik; ImGuiID kimlik; }; KartDurum g_kart; bool g_kartAcik = false; } // namespace bool buton(const char* etiket, ImVec2 boyut, ButonTip tip) { const Tema& t = tema(); ImGuiWindow* w = ImGui::GetCurrentWindow(); if (w->SkipItems) return false; const ImVec2 etiketBoyut = ImGui::CalcTextSize(etiket, nullptr, true); const ImGuiStyle& st = ImGui::GetStyle(); if (boyut.x <= 0) boyut.x = etiketBoyut.x + st.FramePadding.x * 2 + 14.0f; if (boyut.y <= 0) boyut.y = etiketBoyut.y + st.FramePadding.y * 2 + 4.0f; // Etiket ImGui ID'si değil — elle çizilen metin. Aynı etiket birden fazla butonda // pencere widget'larıyla ID çışmasını önler: düğme çağrı-sitenin adresiyle örneklenir, // etiket yalnızca metin olarak kullanılır. (Çakışan ID animasyon durumunu + fare // hit-test'ini karıştırıyordu.) ImGui::PushID(etiket); const bool tiklandi = ImGui::InvisibleButton("##neonbuton", boyut); const ImGuiID id = ImGui::GetItemID(); const bool hover = ImGui::IsItemHovered(); const bool basili = ImGui::IsItemActive(); const ImVec2 min = ImGui::GetItemRectMin(), max = ImGui::GetItemRectMax(); ImGui::PopID(); const float h = animf(id, hover ? 1.0f : 0.0f, 14.0f); const float b = yay(id + 1, basili ? 1.0f : 0.0f); const float dar = 1.5f * b; // basılıyken hafif içe çökme const ImVec2 rMin{min.x + dar, min.y + dar}, rMax{max.x - dar, max.y - dar}; ImVec4 ana, kenarR = t.vurgu; switch (tip) { case ButonTip::Birincil: ana = karisim(t.cerceve, t.vurgu, 0.35f + 0.35f * h); break; case ButonTip::Ikincil: ana = karisim(t.cerceve, t.vurgu2, 0.30f + 0.35f * h); kenarR = t.vurgu2; break; case ButonTip::Hayalet: ana = karisim(t.cerceve, t.vurgu, 0.10f * h); ana.w = 0.35f + 0.5f * h; break; case ButonTip::Tehlike: ana = karisim(t.cerceve, t.hata, 0.35f + 0.40f * h); kenarR = t.hata; break; } ImDrawList* dl = w->DrawList; glowCerceve(dl, rMin, rMax, kenarR, t.yuvarlak, h * (0.7f + 0.3f * b)); const int vtx0 = dl->VtxBuffer.Size; dl->AddRectFilled(rMin, rMax, u32(ana), t.yuvarlak); dikeyGradient(dl, vtx0, rMin, rMax, u32(karisim(ana, {1, 1, 1, ana.w}, 0.10f)), u32(karisim(ana, {0, 0, 0, ana.w}, 0.18f))); dl->AddRect(rMin, rMax, u32(kenarR, 0.25f + 0.6f * h), t.yuvarlak, 0, 1.0f); const ImVec2 mPos{(rMin.x + rMax.x - etiketBoyut.x) * 0.5f, (rMin.y + rMax.y - etiketBoyut.y) * 0.5f}; dl->AddText(mPos, u32(tip == ButonTip::Hayalet ? karisim(t.metinSoluk, t.metin, h) : t.metin), etiket, ImGui::FindRenderedTextEnd(etiket)); return tiklandi; } bool ikonButon(const char* ikon, const char* ipucu, bool aktif) { const Tema& t = tema(); const float k = ImGui::GetFrameHeight() + 6.0f; // İkon ImGui ID'si değil — elle çizilen metin. Çakışan ID'leri önler: düğme // çağrı-sitenin adresiyle örneklenir, ikon yalnızca metin olarak kullanılır. ImGui::PushID(ikon); const bool tiklandi = ImGui::InvisibleButton("##neikon", {k, k}); const ImGuiID id = ImGui::GetItemID(); const bool hover = ImGui::IsItemHovered(); const float h = animf(id, (hover || aktif) ? 1.0f : 0.0f, 14.0f); const ImVec2 min = ImGui::GetItemRectMin(), max = ImGui::GetItemRectMax(); ImDrawList* dl = ImGui::GetWindowDrawList(); if (aktif) glowCerceve(dl, min, max, t.vurgu, t.yuvarlak, 0.8f); dl->AddRectFilled(min, max, u32(karisim(t.cerceve, t.vurgu, aktif ? 0.45f : 0.25f * h)), t.yuvarlak); dl->AddRect(min, max, u32(t.vurgu, 0.15f + 0.6f * h), t.yuvarlak); const ImVec2 ib = ImGui::CalcTextSize(ikon); dl->AddText({(min.x + max.x - ib.x) * 0.5f, (min.y + max.y - ib.y) * 0.5f}, u32(aktif ? t.vurgu : karisim(t.metinSoluk, t.metin, h)), ikon); if (ipucu && hover) ImGui::SetTooltip("%s", ipucu); ImGui::PopID(); return tiklandi; } bool hedefButon(const char* etiket, bool aktif) { const Tema& t = tema(); char buf[128]; std::snprintf(buf, sizeof(buf), "🎯 %s", etiket); ImGui::PushStyleColor(ImGuiCol_Text, aktif ? t.vurgu : t.metin); const bool tiklandi = buton(buf, {0, 0}, aktif ? ButonTip::Birincil : ButonTip::Hayalet); ImGui::PopStyleColor(); return tiklandi; } void kartBasla(const char* kimlik, float genislik) { IM_ASSERT(!g_kartAcik && "kartBasla iç içe çağrılamaz"); g_kartAcik = true; ImGuiWindow* w = ImGui::GetCurrentWindow(); g_kart.kimlik = w->GetID(kimlik); g_kart.genislik = genislik > 0 ? genislik : ImGui::GetContentRegionAvail().x; g_kart.baslangic = ImGui::GetCursorScreenPos(); w->DrawList->ChannelsSplit(2); w->DrawList->ChannelsSetCurrent(1); ImGui::SetCursorScreenPos({g_kart.baslangic.x + 12.0f, g_kart.baslangic.y + 10.0f}); ImGui::BeginGroup(); ImGui::PushClipRect(g_kart.baslangic, {g_kart.baslangic.x + g_kart.genislik - 12.0f, FLT_MAX}, true); ImGui::PushItemWidth(g_kart.genislik - 24.0f > 60.0f ? g_kart.genislik * 0.5f : -1.0f); } void kartBitir() { IM_ASSERT(g_kartAcik && "kartBitir için önce kartBasla"); g_kartAcik = false; const Tema& t = tema(); ImGui::PopItemWidth(); ImGui::PopClipRect(); ImGui::EndGroup(); ImVec2 min = g_kart.baslangic; ImVec2 max{min.x + g_kart.genislik, ImGui::GetItemRectMax().y + 10.0f}; const bool hover = ImGui::IsMouseHoveringRect(min, max); const float h = animf(g_kart.kimlik, hover ? 1.0f : 0.0f, 10.0f); ImDrawList* dl = ImGui::GetWindowDrawList(); dl->ChannelsSetCurrent(0); // gölge + glow (hover'da yükselme hissi) dl->AddRectFilled({min.x + 2, min.y + 3 + 2 * h}, {max.x + 2, max.y + 3 + 2 * h}, u32({0, 0, 0, 1}, t.koyu ? 0.35f : 0.15f), t.yuvarlak + 2); glowCerceve(dl, min, max, t.vurgu, t.yuvarlak + 2, 0.5f * h); const int vtx0 = dl->VtxBuffer.Size; dl->AddRectFilled(min, max, u32(t.panel), t.yuvarlak + 2); dikeyGradient(dl, vtx0, min, max, u32(karisim(t.panel, t.vurgu, 0.05f + 0.05f * h)), u32(karisim(t.panel, {0, 0, 0, 1}, t.koyu ? 0.25f : 0.02f))); dl->AddRect(min, max, u32(t.vurgu, 0.15f + 0.45f * h), t.yuvarlak + 2, 0, 1.2f); // üst kenarda ince neon şerit dl->AddLine({min.x + t.yuvarlak, min.y + 1}, {max.x - t.yuvarlak, min.y + 1}, u32(t.vurgu, 0.35f + 0.4f * h), 1.5f); dl->ChannelsMerge(); ImGui::SetCursorScreenPos({min.x, max.y}); ImGui::Dummy({g_kart.genislik, 6.0f}); } bool anahtar(const char* etiket, bool* deger) { const Tema& t = tema(); const float yk = ImGui::GetFrameHeight() * 0.85f; const ImVec2 boyut{yk * 1.9f, yk}; ImGui::PushID(etiket); const bool tiklandi = ImGui::InvisibleButton("##anahtar", boyut); if (tiklandi) *deger = !*deger; const ImGuiID id = ImGui::GetItemID(); const bool hover = ImGui::IsItemHovered(); const ImVec2 min = ImGui::GetItemRectMin(), max = ImGui::GetItemRectMax(); const float a = animf(id, *deger ? 1.0f : 0.0f, 16.0f); const float h = animf(id + 1, hover ? 1.0f : 0.0f, 14.0f); const float r = yk * 0.5f; ImDrawList* dl = ImGui::GetWindowDrawList(); const ImVec4 iz = karisim(karisim(t.cerceve, t.metinSoluk, 0.15f), t.vurgu, a * 0.75f); dl->AddRectFilled(min, max, u32(iz), r); dl->AddRect(min, max, u32(t.vurgu, 0.15f + 0.45f * (h + a) * 0.5f), r); const float tx = min.x + r + (max.x - min.x - yk) * a; const float ty = (min.y + max.y) * 0.5f; if (a > 0.05f) for (int i = 1; i <= 2; ++i) dl->AddCircle({tx, ty}, r - 2 + i * 2.0f, u32(t.vurgu, 0.20f * a / i * tema().glowSiddet)); dl->AddCircleFilled({tx, ty}, r - 2.5f, u32(karisim(t.metin, t.vurgu, a * 0.25f))); if (etiket[0]) { ImGui::SameLine(); ImGui::AlignTextToFramePadding(); ImGui::TextUnformatted(etiket); } ImGui::PopID(); return tiklandi; } void ilerleme(float oran, const char* metin, float genislik) { const Tema& t = tema(); if (oran < 0) oran = 0; if (oran > 1) oran = 1; if (genislik <= 0) genislik = ImGui::GetContentRegionAvail().x; const float yk = ImGui::GetFrameHeight() * 0.75f; const ImVec2 min = ImGui::GetCursorScreenPos(); const ImVec2 max{min.x + genislik, min.y + yk}; ImGui::Dummy({genislik, yk}); // ID içerik-yerel konumdan: aynı karedeki birden çok çubuk çakışmaz, scroll etkilemez. ImGuiWindow* w = ImGui::GetCurrentWindow(); const int yerel = (int)(min.x - w->Pos.x + w->Scroll.x) * 8191 + (int)(min.y - w->Pos.y + w->Scroll.y); const ImGuiID id = w->GetID((void*)(intptr_t)yerel); const float o = animf(id, oran, 10.0f); ImDrawList* dl = ImGui::GetWindowDrawList(); dl->AddRectFilled(min, max, u32(t.cerceve), yk * 0.5f); if (o > 0.005f) { const float dolu = min.x + (genislik)*o; const int vtx0 = dl->VtxBuffer.Size; dl->AddRectFilled(min, {dolu, max.y}, u32(t.vurgu), yk * 0.5f); ImGui::ShadeVertsLinearColorGradientKeepAlpha(dl, vtx0, dl->VtxBuffer.Size, min, {dolu, min.y}, u32(t.vurgu), u32(t.vurgu2)); // kayan parlama bandı const float faz = std::fmod(zaman() * 0.6f, 1.3f) - 0.15f; const float bx = min.x + genislik * faz * o + 0.0f; if (bx > min.x && bx < dolu) { const float bw = 18.0f; dl->PushClipRect(min, {dolu, max.y}, true); const int v2 = dl->VtxBuffer.Size; dl->AddRectFilled({bx - bw, min.y}, {bx + bw, max.y}, u32({1, 1, 1, 0.30f})); ImGui::ShadeVertsLinearColorGradientKeepAlpha(dl, v2, dl->VtxBuffer.Size, {bx - bw, min.y}, {bx + bw, min.y}, u32({1, 1, 1, 0.0f}), u32({1, 1, 1, 0.0f})); dl->AddRectFilled({bx - 3, min.y}, {bx + 3, max.y}, u32({1, 1, 1, 0.25f})); dl->PopClipRect(); } glowCerceve(dl, min, {dolu, max.y}, t.vurgu, yk * 0.5f, 0.35f); } dl->AddRect(min, max, u32(t.vurgu, 0.20f), yk * 0.5f); if (metin) { const ImVec2 mb = ImGui::CalcTextSize(metin); dl->AddText({(min.x + max.x - mb.x) * 0.5f, (min.y + max.y - mb.y) * 0.5f}, u32(t.metin), metin); } } void rozet(const char* metin, const ImVec4& renk) { const ImVec2 mb = ImGui::CalcTextSize(metin); const ImVec2 min = ImGui::GetCursorScreenPos(); const ImVec2 max{min.x + mb.x + 14.0f, min.y + mb.y + 5.0f}; ImGui::Dummy({max.x - min.x, max.y - min.y}); ImDrawList* dl = ImGui::GetWindowDrawList(); const float r = (max.y - min.y) * 0.5f; dl->AddRectFilled(min, max, u32(renk, 0.18f), r); dl->AddRect(min, max, u32(renk, 0.65f), r, 0, 1.0f); dl->AddText({min.x + 7.0f, min.y + 2.5f}, u32(renk), metin); } void durumLed(int durum, float yaricap) { const Tema& t = tema(); ImVec4 renk; float puls = 0.0f; switch (durum) { case 1: renk = t.basari; puls = nabiz(1.2f); break; case 2: renk = t.uyari; break; case 3: renk = t.hata; puls = nabiz(2.5f); break; default: renk = t.metinSoluk; break; } const ImVec2 p = ImGui::GetCursorScreenPos(); const float fh = ImGui::GetFrameHeight(); const ImVec2 c{p.x + yaricap + 2, p.y + fh * 0.5f}; ImGui::Dummy({yaricap * 2 + 4, fh}); ImDrawList* dl = ImGui::GetWindowDrawList(); if (durum == 1 || durum == 3) dl->AddCircleFilled(c, yaricap + 3.0f + 2.0f * puls, u32(renk, 0.18f + 0.15f * puls)); dl->AddCircleFilled(c, yaricap, u32(renk, 0.85f + 0.15f * puls)); dl->AddCircleFilled({c.x - yaricap * 0.3f, c.y - yaricap * 0.3f}, yaricap * 0.35f, u32({1, 1, 1, 0.5f})); } void baslikSeridi(const char* ikon, const char* baslik) { const Tema& t = tema(); ImGui::Spacing(); if (ikon && ikon[0]) { ImGui::TextColored(t.vurgu, "%s", ikon); ImGui::SameLine(0, 6.0f); } ImGui::TextUnformatted(baslik); const ImVec2 min = ImGui::GetItemRectMin(); const ImVec2 max = ImGui::GetItemRectMax(); const float gen = ImGui::GetContentRegionAvail().x + (max.x - min.x); ImDrawList* dl = ImGui::GetWindowDrawList(); const float y = max.y + 3.0f; const float x0 = ikon && ikon[0] ? min.x - ImGui::CalcTextSize(ikon).x - 6.0f : min.x; const int vtx0 = dl->VtxBuffer.Size; dl->AddRectFilled({x0, y}, {x0 + gen, y + 2.0f}, u32(t.vurgu, 0.7f)); ImGui::ShadeVertsLinearColorGradientKeepAlpha(dl, vtx0, dl->VtxBuffer.Size, {x0, y}, {x0 + gen, y}, u32(t.vurgu, 0.7f), u32(t.vurgu2, 0.0f)); // süpürme ışığı const float faz = std::fmod(zaman() * 0.35f, 1.4f); const float sx = x0 + gen * faz; if (faz < 1.0f) { const int v2 = dl->VtxBuffer.Size; dl->AddRectFilled({sx - 24, y}, {sx + 24, y + 2.0f}, u32({1, 1, 1, 0.55f})); ImGui::ShadeVertsLinearColorGradientKeepAlpha(dl, v2, dl->VtxBuffer.Size, {sx - 24, y}, {sx + 24, y}, u32({1, 1, 1, 0.0f}), u32({1, 1, 1, 0.0f})); dl->AddRectFilled({sx - 3, y - 1}, {sx + 3, y + 3.0f}, u32({1, 1, 1, 0.35f})); } ImGui::Dummy({1, 6.0f}); } void neonAyrac() { const Tema& t = tema(); const float gen = ImGui::GetContentRegionAvail().x; const ImVec2 p = ImGui::GetCursorScreenPos(); ImGui::Dummy({gen, 7.0f}); ImDrawList* dl = ImGui::GetWindowDrawList(); const float y = p.y + 3.0f; const int vtx0 = dl->VtxBuffer.Size; dl->AddRectFilled({p.x, y}, {p.x + gen, y + 1.5f}, u32(t.vurgu, 0.55f)); ImGui::ShadeVertsLinearColorGradientKeepAlpha(dl, vtx0, dl->VtxBuffer.Size, {p.x, y}, {p.x + gen, y}, u32(t.vurgu, 0.55f), u32(t.vurgu2, 0.55f)); } bool vektorGirdi3(const char* etiket, float* v, float adim, const char* fmt) { const Tema& t = tema(); static const ImVec4 eksenRenk[3] = { {0.95f, 0.30f, 0.30f, 1}, {0.30f, 0.85f, 0.35f, 1}, {0.30f, 0.55f, 1.0f, 1}}; static const char* eksenAd[3] = {"##x", "##y", "##z"}; bool degisti = false; ImGui::PushID(etiket); if (etiket[0] && etiket[0] != '#') { ImGui::AlignTextToFramePadding(); ImGui::TextUnformatted(etiket); ImGui::SameLine(); } const float kalan = ImGui::GetContentRegionAvail().x; const float parca = (kalan - 2 * ImGui::GetStyle().ItemInnerSpacing.x) / 3.0f; for (int i = 0; i < 3; ++i) { if (i) ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); const ImVec2 p = ImGui::GetCursorScreenPos(); ImGui::SetNextItemWidth(parca); ImGui::PushStyleColor(ImGuiCol_FrameBg, karisim(t.cerceve, eksenRenk[i], 0.08f)); degisti |= ImGui::DragFloat(eksenAd[i], &v[i], adim, 0, 0, fmt); ImGui::PopStyleColor(); ImDrawList* dl = ImGui::GetWindowDrawList(); const ImVec2 mn = ImGui::GetItemRectMin(), mx = ImGui::GetItemRectMax(); dl->AddRectFilled({mn.x, mn.y + 2}, {mn.x + 3.0f, mx.y - 2}, u32(eksenRenk[i], 0.9f), 1.5f); (void)p; } ImGui::PopID(); return degisti; } bool olcuGirdi(const char* etiket, float* deger, const char* birim, float adim, float genislik) { char fmt[32]; std::snprintf(fmt, sizeof(fmt), "%%.3f %s", birim); if (genislik > 0) ImGui::SetNextItemWidth(genislik); return ImGui::DragFloat(etiket, deger, adim, 0, 0, fmt); } void hudKoseleri(ImDrawList* dl, ImVec2 min, ImVec2 max, float uzunluk, float kalinlik) { const Tema& t = tema(); const ImU32 parlak = u32(t.vurgu, 0.85f); const ImU32 soluk = u32(t.vurgu, 0.20f * t.glowSiddet); const float u = uzunluk; const ImVec2 koseler[4] = {min, {max.x, min.y}, max, {min.x, max.y}}; const float yonX[4] = {1, -1, -1, 1}, yonY[4] = {1, 1, -1, -1}; for (int i = 0; i < 4; ++i) { const ImVec2 k = koseler[i]; // glow alt katman + parlak üst katman dl->AddLine(k, {k.x + u * yonX[i], k.y}, soluk, kalinlik + 3.0f); dl->AddLine(k, {k.x, k.y + u * yonY[i]}, soluk, kalinlik + 3.0f); dl->AddLine(k, {k.x + u * yonX[i], k.y}, parlak, kalinlik); dl->AddLine(k, {k.x, k.y + u * yonY[i]}, parlak, kalinlik); } } void yayMetin(ImDrawList* dl, ImVec2 merkez, float yaricap, float ekranAci, const char* metin, ImU32 renk, bool ustYay, float fontBoyut) { if (!metin || !metin[0] || (renk & IM_COL32_A_MASK) == 0 || yaricap < 1.0f) return; ImFont* font = ImGui::GetFont(); const float boyut = fontBoyut > 0.0f ? fontBoyut : ImGui::GetFontSize(); ImFontBaked* baked = font->GetFontBaked(boyut); if (!baked) return; const float olcek = boyut / baked->Size; // Glif kodlarını + toplam yay uzunluğunu (advance) tek geçişte topla (stack). unsigned int kod[64]; float ilerle[64]; int n = 0; float toplamGen = 0.0f; for (const char* s = metin; *s && n < 64;) { unsigned int c = 0; s += ImTextCharFromUtf8(&c, s, nullptr); if (!c) break; const ImFontGlyph* g = baked->FindGlyph((ImWchar)c); if (!g) continue; kod[n] = c; ilerle[n] = g->AdvanceX * olcek; toplamGen += ilerle[n]; ++n; } if (n == 0) return; // Yayı açıya çevir: metin ORTASI ekranAci'da; harfler yay boyunca dizilir. // Üst yayda soldan-sağa okumak için saat yönü (+), alt yayda ters (-). const float yonIsaret = ustYay ? 1.0f : -1.0f; float aci = ekranAci - yonIsaret * (toplamGen * 0.5f) / yaricap; // baş açısı ImTextureRef tex = font->OwnerAtlas->TexRef; dl->PushTexture(tex); dl->PrimReserve(n * 6, n * 4); for (int i = 0; i < n; ++i) { const ImFontGlyph* g = baked->FindGlyph((ImWchar)kod[i]); const float yariAdv = ilerle[i] * 0.5f; const float aOrta = aci + yonIsaret * (yariAdv / yaricap); // glif merkez açısı // Yay üzerindeki taban noktası + teğet yönü. Üst yay: harf tabanı içeride // (yarıçapa doğru), tepe dışarıda. Alt yay: tersine (içe bakar). const float cs = std::cos(aOrta), sn = std::sin(aOrta); const ImVec2 taban{merkez.x + cs * yaricap, merkez.y + sn * yaricap}; // Yerel eksen: teğet (okuma yönü) + normal (yukarı = merkezden dışa/içe). const float tSgn = ustYay ? 1.0f : -1.0f; const ImVec2 tex_t{-sn * tSgn, cs * tSgn}; // teğet birim (okuma yönü) const ImVec2 nrm{cs * tSgn, sn * tSgn}; // normal birim (harf üstü yönü) // Glif quad'ı yerel uzayda: x=teğet ekseni (advance), y=normal ekseni (yukarı). // ImGui Y0X0 * olcek - yariAdv, x1 = g->X1 * olcek - yariAdv; const float y0 = -(g->Y0 * olcek), y1 = -(g->Y1 * olcek); const auto yereldenEkran = [&](float lx, float ly) -> ImVec2 { return {taban.x + tex_t.x * lx + nrm.x * ly, taban.y + tex_t.y * lx + nrm.y * ly}; }; const ImVec2 p0 = yereldenEkran(x0, y0); // sol-üst const ImVec2 p1 = yereldenEkran(x1, y0); // sağ-üst const ImVec2 p2 = yereldenEkran(x1, y1); // sağ-alt const ImVec2 p3 = yereldenEkran(x0, y1); // sol-alt dl->PrimQuadUV(p0, p1, p2, p3, {g->U0, g->V0}, {g->U1, g->V0}, {g->U1, g->V1}, {g->U0, g->V1}, renk); aci += yonIsaret * (ilerle[i] / yaricap); } dl->PopTexture(); } void marka(float olcek) { const Tema& t = tema(); const char* metin = "FikoYT"; ImGui::PushFont(nullptr, ImGui::GetFontSize() * olcek); const ImVec2 mb = ImGui::CalcTextSize(metin); const ImVec2 min = ImGui::GetCursorScreenPos(); const ImVec2 max{min.x + mb.x + 18.0f, min.y + mb.y + 8.0f}; ImGui::Dummy({max.x - min.x, max.y - min.y}); ImDrawList* dl = ImGui::GetWindowDrawList(); dl->AddRectFilled(min, max, u32(t.panel, 0.9f), (max.y - min.y) * 0.5f); dl->AddRect(min, max, u32(t.vurgu, 0.5f), (max.y - min.y) * 0.5f, 0, 1.2f); const ImVec2 tp{min.x + 9.0f, min.y + 4.0f}; // akan gradient: harf başına renk (vurgu ↔ vurgu2 arasında zamanla kayar) float x = tp.x; for (int i = 0; metin[i]; ++i) { const char harf[2] = {metin[i], 0}; const float f = 0.5f + 0.5f * std::sin(zaman() * 2.0f + (float)i * 0.7f); const ImVec4 renk = karisim(t.vurgu, t.vurgu2, f); dl->AddText({x + 0.5f, tp.y + 0.5f}, u32(renk, 0.35f), harf); // hafif glow gölgesi dl->AddText({x, tp.y}, u32(renk), harf); x += ImGui::CalcTextSize(harf).x; } ImGui::PopFont(); } } // namespace fiko::ui