#include "fiko/ui/bilesen_cadcam.hpp" #include #include #include #include #include "fiko/ui/animasyon.hpp" #include "fiko/ui/bilesen.hpp" #include "fiko/ui/tema.hpp" #include "imgui_internal.h" namespace fiko::ui { namespace { constexpr float PI = 3.14159265f; const ImVec4 EKSEN[3] = { {0.95f, 0.30f, 0.30f, 1}, {0.30f, 0.85f, 0.35f, 1}, {0.30f, 0.55f, 1.0f, 1}}; void metniOrtala(ImDrawList* dl, ImVec2 merkez, float boyut, ImU32 renk, const char* metin) { ImFont* f = ImGui::GetFont(); const ImVec2 mb = f->CalcTextSizeA(boyut, FLT_MAX, 0.0f, metin); dl->AddText(f, boyut, {merkez.x - mb.x * 0.5f, merkez.y - mb.y * 0.5f}, renk, metin); } // Etiketi (varsa) frame padding hizalı yazıp SameLine yapar. void onEtiket(const char* etiket) { if (etiket && etiket[0] && etiket[0] != '#') { ImGui::AlignTextToFramePadding(); ImGui::TextUnformatted(etiket); ImGui::SameLine(); } } // Mini triad ikonu (XYZ ok) — CSYS göstergesi. void triadCiz(ImDrawList* dl, ImVec2 m, float r, float alfa) { const ImVec2 yon[3] = {{r, r * 0.35f}, {-r * 0.5f, -r}, {-r * 0.85f, r * 0.7f}}; for (int i = 0; i < 3; ++i) { const ImVec2 u{m.x + yon[i].x, m.y + yon[i].y}; dl->AddLine(m, u, u32(EKSEN[i], alfa), 1.8f); dl->AddCircleFilled(u, 2.0f, u32(EKSEN[i], alfa)); } } // mm cinsinden birim katsayıları (birimDonusturucu). const char* BIRIM_AD[5] = {"mm", "cm", "inch", "ft", "thou"}; const float BIRIM_MM[5] = {1.0f, 10.0f, 25.4f, 304.8f, 0.0254f}; } // namespace bool toleransGirisi(const char* etiket, float* nominal, float* ustSapma, float* altSapma, const char* birim) { const Tema& t = tema(); ImGui::PushID(etiket); onEtiket(etiket); bool degisti = false; const float w = ImMax(60.0f, (ImGui::GetContentRegionAvail().x - 16.0f) / 3.0f); ImGui::SetNextItemWidth(w); degisti |= ImGui::DragFloat("##nom", nominal, 0.05f, 0, 0, "%.3f"); ImGui::SameLine(0, 6); ImGui::PushStyleColor(ImGuiCol_Text, t.basari); ImGui::SetNextItemWidth(w * 0.8f); degisti |= ImGui::DragFloat("##ust", ustSapma, 0.005f, 0, 0, "+%.3f"); ImGui::PopStyleColor(); ImGui::SameLine(0, 6); ImGui::PushStyleColor(ImGuiCol_Text, t.hata); ImGui::SetNextItemWidth(w * 0.8f); degisti |= ImGui::DragFloat("##alt", altSapma, 0.005f, 0, 0, "-%.3f"); ImGui::PopStyleColor(); // canlı min/max aralık hapı char buf[80]; std::snprintf(buf, sizeof(buf), "[%.3f … %.3f] %s", *nominal - std::fabs(*altSapma), *nominal + std::fabs(*ustSapma), birim); const ImVec2 p = ImGui::GetCursorScreenPos(); ImFont* f = ImGui::GetFont(); const float fs = 12.0f; const ImVec2 tb = f->CalcTextSizeA(fs, FLT_MAX, 0.0f, buf); ImGui::Dummy({tb.x + 16.0f, fs + 8.0f}); ImDrawList* dl = ImGui::GetWindowDrawList(); dl->AddRectFilled(p, {p.x + tb.x + 16.0f, p.y + fs + 8.0f}, u32(t.panel, 0.7f), (fs + 8.0f) * 0.5f); dl->AddText(f, fs, {p.x + 8.0f, p.y + 4.0f}, u32(t.vurgu), buf); ImGui::PopID(); return degisti; } bool gdtCipi(const char* sembol, float deger, const char* datum, const char* birim) { const Tema& t = tema(); ImFont* f = ImGui::GetFont(); const float fs = 13.0f, yk = 24.0f; char valBuf[48]; std::snprintf(valBuf, sizeof(valBuf), "%.3f %s", deger, birim); const float symG = f->CalcTextSizeA(fs + 2.0f, FLT_MAX, 0.0f, sembol).x + 14.0f; const float valG = f->CalcTextSizeA(fs, FLT_MAX, 0.0f, valBuf).x + 14.0f; const float datG = datum ? f->CalcTextSizeA(fs, FLT_MAX, 0.0f, datum).x + 14.0f : 0.0f; const float toplam = symG + valG + datG; ImGui::PushID(sembol); const ImVec2 p = ImGui::GetCursorScreenPos(); const bool tik = ImGui::InvisibleButton("##gdt", {toplam, yk}); const ImGuiID id = ImGui::GetItemID(); const float h = animf(id, ImGui::IsItemHovered() ? 1.0f : 0.0f, 12.0f); ImGui::PopID(); ImDrawList* dl = ImGui::GetWindowDrawList(); const ImVec2 mx{p.x + toplam, p.y + yk}; dl->AddRectFilled(p, mx, u32(t.panel, 0.95f), 4.0f); dl->AddRect(p, mx, u32(t.vurgu, 0.3f + 0.5f * h), 4.0f, 0, 1.2f); // bölmeler (feature control frame gibi dikey çizgiler) float x = p.x; dl->AddText(f, fs + 2.0f, {x + 7.0f, p.y + (yk - fs - 2.0f) * 0.5f}, u32(t.vurgu2), sembol); x += symG; dl->AddLine({x, p.y + 2.0f}, {x, mx.y - 2.0f}, u32(t.kenar, 0.9f), 1.0f); dl->AddText(f, fs, {x + 7.0f, p.y + (yk - fs) * 0.5f}, u32(t.metin), valBuf); x += valG; if (datum) { dl->AddLine({x, p.y + 2.0f}, {x, mx.y - 2.0f}, u32(t.kenar, 0.9f), 1.0f); dl->AddText(f, fs, {x + 7.0f, p.y + (yk - fs) * 0.5f}, u32(t.vurgu), datum); } return tik; } bool csysSecici(const char* etiket, int* secili) { const Tema& t = tema(); static const char* ETK[3] = {"Dünya", "Yerel", "Seçili"}; ImGui::PushID(etiket); onEtiket(etiket); bool degisti = false; const ImVec2 basP = ImGui::GetCursorScreenPos(); for (int i = 0; i < 3; ++i) { if (i) ImGui::SameLine(0, 6); ImGui::PushID(i); const bool s = *secili == i; ImFont* f = ImGui::GetFont(); const float tw = f->CalcTextSizeA(13.0f, FLT_MAX, 0.0f, ETK[i]).x; const float w = 26.0f + tw + 12.0f, yk = ImGui::GetFrameHeight(); const ImVec2 p = ImGui::GetCursorScreenPos(); if (ImGui::InvisibleButton("##opt", {w, yk}) && !s) { *secili = i; degisti = true; } const float h = animf(ImGui::GetItemID(), (s || ImGui::IsItemHovered()) ? 1.0f : 0.0f, 12.0f); ImDrawList* dl = ImGui::GetWindowDrawList(); const ImVec2 mx{p.x + w, p.y + yk}; dl->AddRectFilled(p, mx, u32(karisim(t.cerceve, t.vurgu, s ? 0.28f : 0.06f * h)), t.yuvarlak); dl->AddRect(p, mx, u32(t.vurgu, s ? 0.85f : 0.2f * h), t.yuvarlak, 0, s ? 1.6f : 1.0f); triadCiz(dl, {p.x + 14.0f, p.y + yk * 0.5f}, 8.0f, s ? 1.0f : 0.5f + 0.4f * h); dl->AddText(f, 13.0f, {p.x + 26.0f, p.y + (yk - 13.0f) * 0.5f}, u32(s ? t.metin : t.metinSoluk), ETK[i]); ImGui::PopID(); } (void)basP; ImGui::PopID(); return degisti; } bool malzemeKarti(const char* ad, float yogunluk, const ImVec4& renk, bool secili, ImVec2 boyut) { const Tema& t = tema(); if (boyut.x <= 0) boyut.x = 160.0f; if (boyut.y <= 0) boyut.y = 56.0f; ImGui::PushID(ad); const bool tik = ImGui::InvisibleButton("##mat", boyut); const ImGuiID id = ImGui::GetItemID(); const float h = animf(id, ImGui::IsItemHovered() ? 1.0f : 0.0f, 12.0f); const ImVec2 mn = ImGui::GetItemRectMin(), mx = ImGui::GetItemRectMax(); ImGui::PopID(); ImDrawList* dl = ImGui::GetWindowDrawList(); if (secili || h > 0.05f) glowCerceve(dl, mn, mx, secili ? t.vurgu : t.vurgu2, t.yuvarlak + 1, secili ? 1.0f : 0.6f * h); dl->AddRectFilled(mn, mx, u32(t.panel), t.yuvarlak + 1); dl->AddRect(mn, mx, u32(secili ? t.vurgu : t.kenar, secili ? 0.9f : 0.5f + 0.4f * h), t.yuvarlak + 1, 0, secili ? 1.8f : 1.0f); // malzeme renk örneği (sol küre) const ImVec2 sm{mn.x + 20.0f, (mn.y + mx.y) * 0.5f}; dl->AddCircleFilled(sm, 13.0f, u32(renk)); dl->AddCircleFilled({sm.x - 4.0f, sm.y - 4.0f}, 4.0f, u32(t.metin, 0.35f)); // parlama dl->AddCircle(sm, 13.0f, u32(t.metin, 0.4f), 0, 1.0f); // ad + yoğunluk ImFont* f = ImGui::GetFont(); dl->AddText(f, 14.0f, {mn.x + 40.0f, mn.y + 9.0f}, u32(t.metin), ad); char yb[40]; std::snprintf(yb, sizeof(yb), "%.2f g/cm³", yogunluk); dl->AddText(f, 11.0f, {mn.x + 40.0f, mn.y + 28.0f}, u32(t.metinSoluk), yb); return tik; } bool takimKartiCadCam(const char* tip, float cap, int dis, float uzunluk, bool secili, ImVec2 boyut) { const Tema& t = tema(); if (boyut.x <= 0) boyut.x = 180.0f; if (boyut.y <= 0) boyut.y = 64.0f; ImGui::PushID(tip); const bool tik = ImGui::InvisibleButton("##takim", boyut); const ImGuiID id = ImGui::GetItemID(); const float h = animf(id, ImGui::IsItemHovered() ? 1.0f : 0.0f, 12.0f); const ImVec2 mn = ImGui::GetItemRectMin(), mx = ImGui::GetItemRectMax(); ImGui::PopID(); ImDrawList* dl = ImGui::GetWindowDrawList(); if (secili || h > 0.05f) glowCerceve(dl, mn, mx, t.vurgu, t.yuvarlak + 1, secili ? 1.0f : 0.55f * h); dl->AddRectFilled(mn, mx, u32(t.panel), t.yuvarlak + 1); dl->AddRect(mn, mx, u32(secili ? t.vurgu : t.kenar, secili ? 0.9f : 0.5f + 0.4f * h), t.yuvarlak + 1, 0, secili ? 1.8f : 1.0f); // sol: takım silüeti (koni sap + kesici) — çapa orantılı const float cx = mn.x + 22.0f, cy0 = mn.y + 10.0f, cy1 = mx.y - 10.0f; const float yw = ImClamp(cap * 1.4f, 4.0f, 16.0f); dl->AddRectFilled({cx - yw * 0.35f, cy0}, {cx + yw * 0.35f, (cy0 + cy1) * 0.5f}, u32(t.metinSoluk, 0.7f), 1.0f); // sap dl->AddTriangleFilled({cx - yw * 0.5f, (cy0 + cy1) * 0.5f}, {cx + yw * 0.5f, (cy0 + cy1) * 0.5f}, {cx, cy1}, u32(t.vurgu)); // kesici uç // başlık + teknik satırlar ImFont* f = ImGui::GetFont(); dl->AddText(f, 14.0f, {mn.x + 42.0f, mn.y + 8.0f}, u32(t.metin), tip); char b1[48], b2[48]; std::snprintf(b1, sizeof(b1), "⌀%.1f Z%d", cap, dis); std::snprintf(b2, sizeof(b2), "L %.0f mm", uzunluk); dl->AddText(f, 11.0f, {mn.x + 42.0f, mn.y + 28.0f}, u32(t.vurgu), b1); dl->AddText(f, 11.0f, {mn.x + 42.0f, mn.y + 44.0f}, u32(t.metinSoluk), b2); return tik; } bool feedsSpeedsPaneli(const char* kimlik, float takimCap, int dis, float* devir, float* ilerleme, float* kesmeHizi, float* talas) { const Tema& t = tema(); ImGui::PushID(kimlik); bool degisti = false; const float capM = ImMax(takimCap, 0.001f); const int z = ImMax(dis, 1); // devir ↔ kesme hızı: Vc = π·D·n / 1000 (m/dk) ImGui::SetNextItemWidth(-FLT_MIN); if (ImGui::DragFloat("Devir (RPM)", devir, 10.0f, 0.0f, 0, "%.0f")) { *kesmeHizi = PI * capM * *devir / 1000.0f; *ilerleme = *devir * (float)z * *talas; degisti = true; } ImGui::SetNextItemWidth(-FLT_MIN); if (ImGui::DragFloat("Kesme hızı (m/dk)", kesmeHizi, 1.0f, 0.0f, 0, "%.1f")) { *devir = *kesmeHizi * 1000.0f / (PI * capM); *ilerleme = *devir * (float)z * *talas; degisti = true; } ImGui::SetNextItemWidth(-FLT_MIN); if (ImGui::DragFloat("Diş talaşı fz (mm)", talas, 0.005f, 0.0f, 0, "%.3f")) { *ilerleme = *devir * (float)z * *talas; degisti = true; } ImGui::SetNextItemWidth(-FLT_MIN); if (ImGui::DragFloat("İlerleme (mm/dk)", ilerleme, 5.0f, 0.0f, 0, "%.0f")) { if (*devir * (float)z > 1e-3f) *talas = *ilerleme / (*devir * (float)z); degisti = true; } // canlı özet şeridi const ImVec2 p = ImGui::GetCursorScreenPos(); const float gen = ImGui::GetContentRegionAvail().x, yk = 22.0f; ImGui::Dummy({gen, yk + 4.0f}); ImDrawList* dl = ImGui::GetWindowDrawList(); dl->AddRectFilled(p, {p.x + gen, p.y + yk}, u32(t.panel, 0.6f), t.yuvarlak); ImFont* f = ImGui::GetFont(); char buf[96]; std::snprintf(buf, sizeof(buf), "⌀%.1f Z%d Vc %.0f m/dk fz %.3f mm", takimCap, z, *kesmeHizi, *talas); dl->AddText(f, 12.0f, {p.x + 8.0f, p.y + (yk - 12.0f) * 0.5f}, u32(t.vurgu), buf); ImGui::PopID(); return degisti; } bool birimDonusturucu(const char* etiket, float* deger, int* kaynakBirim, int* hedefBirim) { const Tema& t = tema(); ImGui::PushID(etiket); onEtiket(etiket); bool uygulandi = false; ImGui::SetNextItemWidth(90.0f); float giris = *deger; const bool girisDegisti = ImGui::DragFloat("##val", &giris, 0.1f, 0, 0, "%.4f"); ImGui::SameLine(0, 4); ImGui::SetNextItemWidth(76.0f); ImGui::Combo("##src", kaynakBirim, BIRIM_AD, 5); ImGui::SameLine(0, 4); ImGui::TextUnformatted("→"); ImGui::SameLine(0, 4); ImGui::SetNextItemWidth(76.0f); const bool hedefDegisti = ImGui::Combo("##dst", hedefBirim, BIRIM_AD, 5); const int s = ImClamp(*kaynakBirim, 0, 4), d = ImClamp(*hedefBirim, 0, 4); const float sonuc = giris * BIRIM_MM[s] / BIRIM_MM[d]; ImGui::SameLine(0, 6); if (buton("=", {28, 0})) { *deger = sonuc; *kaynakBirim = d; // sonuç artık hedef birimde uygulandi = true; } // canlı sonuç rozeti char buf[64]; std::snprintf(buf, sizeof(buf), "%.4f %s", sonuc, BIRIM_AD[d]); rozet(buf, t.vurgu); if (!uygulandi && girisDegisti) *deger = giris; (void)hedefDegisti; ImGui::PopID(); return uygulandi; } bool ifadeGirisi(const char* etiket, char* tampon, int tamponBoyut, bool gecerli, const char* hataMesaj, float genislik) { const Tema& t = tema(); ImGui::PushID(etiket); onEtiket(etiket); if (genislik <= 0) genislik = ImGui::GetContentRegionAvail().x - 30.0f; const ImVec4 kenarRenk = gecerli ? t.basari : t.hata; ImGui::PushStyleColor(ImGuiCol_Border, kenarRenk); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.5f); ImGui::SetNextItemWidth(genislik); const bool degisti = ImGui::InputTextWithHint("##ifade", "f(x) = …", tampon, tamponBoyut); ImGui::PopStyleVar(); ImGui::PopStyleColor(); ImGui::SameLine(0, 6); const ImVec2 p = ImGui::GetCursorScreenPos(); const float r = ImGui::GetFrameHeight() * 0.5f; const ImVec2 m{p.x + r, p.y + r}; ImGui::Dummy({r * 2.0f, r * 2.0f}); ImDrawList* dl = ImGui::GetWindowDrawList(); dl->AddCircleFilled(m, r, u32(kenarRenk, 0.18f)); dl->AddCircle(m, r, u32(kenarRenk, 0.9f), 0, 1.4f); metniOrtala(dl, m, 14.0f, u32(kenarRenk), gecerli ? "✓" : "✕"); if (!gecerli && hataMesaj && ImGui::IsItemHovered()) ImGui::SetTooltip("%s", hataMesaj); ImGui::PopID(); return degisti; } bool snapGridCubugu(const char* kimlik, unsigned* modlar, float* gridAdim) { const Tema& t = tema(); static const char* IKON[5] = {"⌐", "◑", "⊙", "✕", "▦"}; static const char* IPUC[5] = {"Uç", "Orta", "Merkez", "Kesişim", "Izgara"}; ImGui::PushID(kimlik); bool degisti = false; for (int i = 0; i < 5; ++i) { if (i) ImGui::SameLine(0, 4); const unsigned bit = 1u << i; const bool aktif = (*modlar & bit) != 0; if (ikonButon(IKON[i], IPUC[i], aktif)) { *modlar ^= bit; degisti = true; } } ImGui::SameLine(0, 10); ImGui::AlignTextToFramePadding(); ImGui::TextColored(t.metinSoluk, "adım"); ImGui::SameLine(0, 4); ImGui::SetNextItemWidth(70.0f); degisti |= ImGui::DragFloat("##grid", gridAdim, 0.1f, 0.001f, 1000.0f, "%.2f"); ImGui::PopID(); return degisti; } bool kesitDuzlemKontrol(const char* etiket, int* eksen, float* ofset, bool* ters, bool* aktif, float ofsetMin, float ofsetMax) { const Tema& t = tema(); static const char* EKS[3] = {"X", "Y", "Z"}; ImGui::PushID(etiket); onEtiket(etiket); bool degisti = false; degisti |= anahtar("##aktif", aktif); ImGui::SameLine(0, 8); // eksen mini seçici (renk kodlu) for (int i = 0; i < 3; ++i) { if (i) ImGui::SameLine(0, 3); ImGui::PushID(i); const bool s = *eksen == i; const float yk = ImGui::GetFrameHeight(); const ImVec2 p = ImGui::GetCursorScreenPos(); if (ImGui::InvisibleButton("##eks", {yk, yk}) && !s) { *eksen = i; degisti = true; } const float h = animf(ImGui::GetItemID(), (s || ImGui::IsItemHovered()) ? 1.0f : 0.0f, 12.0f); ImDrawList* dl = ImGui::GetWindowDrawList(); const ImVec2 mx{p.x + yk, p.y + yk}; dl->AddRectFilled(p, mx, u32(karisim(t.cerceve, EKSEN[i], s ? 0.5f : 0.12f * h)), t.yuvarlak); dl->AddRect(p, mx, u32(EKSEN[i], s ? 0.9f : 0.3f * h), t.yuvarlak, 0, s ? 1.6f : 1.0f); metniOrtala(dl, {p.x + yk * 0.5f, p.y + yk * 0.5f}, 14.0f, u32(s ? t.metin : t.metinSoluk), EKS[i]); ImGui::PopID(); } ImGui::SameLine(0, 8); ImGui::SetNextItemWidth(-70.0f); degisti |= ImGui::SliderFloat("##ofset", ofset, ofsetMin, ofsetMax, "%.2f"); ImGui::SameLine(0, 6); if (ikonButon("⇄", "Ters çevir", *ters)) { *ters = !*ters; degisti = true; } ImGui::PopID(); return degisti; } void durumCubugu(const float imlec[3], const char* birim, int secimSayisi, const char* ipucu) { const Tema& t = tema(); const float gen = ImGui::GetContentRegionAvail().x; const float yk = 26.0f; const ImVec2 p = ImGui::GetCursorScreenPos(); ImGui::Dummy({gen, yk}); ImDrawList* dl = ImGui::GetWindowDrawList(); const ImVec2 mx{p.x + gen, p.y + yk}; dl->AddRectFilled(p, mx, u32(t.panel, 0.96f), 0.0f); dl->AddLine({p.x, p.y}, {mx.x, p.y}, u32(t.vurgu, 0.5f), 1.0f); // üst neon çizgi ImFont* f = ImGui::GetFont(); const float fs = 12.0f, cy = p.y + (yk - fs) * 0.5f; float x = p.x + 10.0f; // koordinat (eksen renkli) static const char* AD[3] = {"X", "Y", "Z"}; for (int i = 0; i < 3; ++i) { char b[32]; std::snprintf(b, sizeof(b), "%s %.3f", AD[i], imlec[i]); dl->AddText(f, fs, {x, cy}, u32(karisim(t.metin, EKSEN[i], 0.35f)), b); x += f->CalcTextSizeA(fs, FLT_MAX, 0.0f, b).x + 14.0f; } dl->AddLine({x - 7.0f, p.y + 5.0f}, {x - 7.0f, mx.y - 5.0f}, u32(t.kenar), 1.0f); // birim + seçim sayısı if (birim) { dl->AddText(f, fs, {x, cy}, u32(t.metinSoluk), birim); x += f->CalcTextSizeA(fs, FLT_MAX, 0.0f, birim).x + 14.0f; } char sb[40]; std::snprintf(sb, sizeof(sb), "%d seçili", secimSayisi); dl->AddText(f, fs, {x, cy}, u32(secimSayisi > 0 ? t.vurgu : t.metinSoluk), sb); // sağda ipucu if (ipucu) { const float iw = f->CalcTextSizeA(fs, FLT_MAX, 0.0f, ipucu).x; dl->AddText(f, fs, {mx.x - iw - 10.0f, cy}, u32(t.metinSoluk), ipucu); } } } // namespace fiko::ui