#include "cam_paneli.hpp" #include #include #include #include #include #include #include "cam_simulasyon_penceresi.hpp" #include "cam_takim_penceresi.hpp" #include "fiko/cam/cam_islemleri.hpp" #include "fiko/cam/cam_sistemi.hpp" #include "fiko/cekirdek/cekirdek.hpp" #include "fiko/sahne/sahne.hpp" #include "fiko/ui/bilesen.hpp" #include "fiko/ui/form.hpp" #include "fiko/ui/pencere_cerceve.hpp" #include "fiko/ui/tema.hpp" #include "pencere_util.hpp" namespace fiko { namespace { using cam::CamIslem; using cam::CamIslemTip; using cam::CamSistemi; using cam::Takim; // f64 için DragScalar sarımı; degisti bayrağını toplar. bool surukleF64(const char* etiket, f64& deger, f32 hiz = 0.1, const char* fmt = "%.3f") { return ImGui::DragScalar(etiket, ImGuiDataType_Double, °er, hiz, nullptr, nullptr, fmt); } void geometriSekmesi(Sahne& sahne, CamSistemi& cam, CamIslem& op) { const ImVec4 SOLUK = ui::tema().metinSoluk; ImGui::TextColored(SOLUK, "Hedef geometri (sahneden yüz kipiyle seçin)"); ImGui::Spacing(); if (op.govde) { const Dugum* d = sahne.bul(op.govde); ImGui::Text("Gövde: %s", d ? d->ad.c_str() : "(silinmiş)"); if (op.tip == CamIslemTip::Delik) ImGui::Text("Delik yüzü: %d adet", (int)op.delikYuzleri.size()); else if (op.yuz) ImGui::Text("Yüz: #%u", op.yuz); else if (op.tip == CamIslemTip::SweepFinis || op.tip == CamIslemTip::KonturGudumlu) ImGui::Text("Kaynak: tüm gövde + %d sürüş kenarı", (int)op.surusKenarlari.size()); else if (cam::ucBoyutluMu(op.tip)) ImGui::TextUnformatted("Kaynak: tüm gövde mesh'i"); } else { ImGui::TextColored(SOLUK, "Henüz geometri atanmadı"); } ImGui::Spacing(); if (ImGui::Button("◉ Seçimden Al", {-1, 0})) cam.geometridenAta(op); ImGui::SetItemTooltip("Aktif 3D seçimi bu operasyona bağlar ve Z değerlerini önerir"); } void takimSekmesi(CamSistemi& cam, CamIslem& op, bool& degisti) { const ImVec4 SOLUK = ui::tema().metinSoluk; const Takim* aktif = cam.takimBul(op.takimNo); ui::alan("Takım"); if (ImGui::BeginCombo("##Takım", aktif ? aktif->ad.c_str() : "—")) { for (const Takim& t : cam.takimlar()) { char etiket[96]; std::snprintf(etiket, sizeof(etiket), "T%d %s", t.numara, t.ad.c_str()); if (ImGui::Selectable(etiket, t.numara == op.takimNo)) { op.takimNo = t.numara; degisti = true; } } ImGui::EndCombo(); } if (aktif) { ImGui::TextColored(SOLUK, "%s — Ø%.2f, %d ağız", cam::takimTipAdi(aktif->tip), aktif->cap, aktif->agizSayisi); } ImGui::SeparatorText("Feeds && Speeds"); const auto& malz = cam::malzemeler(); ui::alan("Malzeme"); if (ImGui::BeginCombo("##Malzeme", malz[(size_t)cam.malzemeIndeks].ad)) { for (int i = 0; i < (int)malz.size(); ++i) if (ImGui::Selectable(malz[(size_t)i].ad, i == cam.malzemeIndeks)) cam.malzemeIndeks = i; ImGui::EndCombo(); } if (ImGui::Button("⚡ Hesapla (Vc/fz)", {-1, 0}) && aktif) { const cam::FeedsSpeeds fs = cam::feedsSpeeds(malz[(size_t)cam.malzemeIndeks], aktif->cap, aktif->agizSayisi); op.devir = fs.devir; op.ilerleme = fs.ilerleme; op.dalmaIlerleme = fs.ilerleme * 0.3; degisti = true; } ui::alan("Devir (rpm)"); degisti |= surukleF64("##Devir", op.devir, 10.0f, "%.0f"); ui::alan("İlerleme (mm/dk)"); degisti |= surukleF64("##İlerleme", op.ilerleme, 10.0f, "%.0f"); ui::alan("Dalma (mm/dk)"); degisti |= surukleF64("##Dalma", op.dalmaIlerleme, 5.0f, "%.0f"); } void yukseklikSekmesi(CamIslem& op, bool& degisti) { const ImVec4 SOLUK = ui::tema().metinSoluk; ImGui::TextColored(SOLUK, "Mutlak Z (mm) — CATIA/Fusion yükseklik modeli"); ui::alan("Güvenli Z"); degisti |= surukleF64("##Güvenli Z", op.guvenliZ); ImGui::SetItemTooltip("Hızlı hareket düzlemi (clearance)"); ui::alan("Geri Çekme Z"); degisti |= surukleF64("##Geri Çekme Z", op.geriCekmeZ); ImGui::SetItemTooltip("Pasolar arası geri çekilme (retract)"); ui::alan("Üst Z"); degisti |= surukleF64("##Üst Z", op.ustZ); ImGui::SetItemTooltip("Malzeme üstü (top of stock)"); ui::alan("Alt Z"); degisti |= surukleF64("##Alt Z", op.altZ); ImGui::SetItemTooltip("Kesim tabanı (bottom)"); } void gecislerSekmesi(CamIslem& op, bool& degisti) { const ImVec4 SOLUK = ui::tema().metinSoluk; if (op.tip != CamIslemTip::Delik) { ui::alan("Z Hatvesi (mm)"); degisti |= surukleF64("##Z Hatvesi", op.zHatve, 0.05f); f32 oran = (f32)(op.yanalHatveOran * 100.0); ui::alan("Yanal Hatve (%)"); if (ImGui::SliderFloat("##Yanal Hatve", &oran, 5.0f, 90.0f, "%.0f%%")) { op.yanalHatveOran = oran / 100.0; degisti = true; } ui::alan("Yüzey Payı (mm)"); degisti |= surukleF64("##Yüzey Payı", op.yuzeyPayi, 0.02f); } switch (op.tip) { case CamIslemTip::Profil: { const char* yonlar[] = {"Dışından (Sol)", "İçinden (Sağ)", "Üzerinde"}; int y = (int)op.ofsetYon; ui::alan("Ofset Yönü"); if (ImGui::Combo("##Ofset Yönü", &y, yonlar, 3)) { op.ofsetYon = (cam::OfsetYonu)y; degisti = true; } break; } case CamIslemTip::Delik: { int d = (int)op.dongu; const char* donguler[] = {"Punta (G81)", "Delme (G81)", "Kademeli (G83)", "Kılavuz (G84)", "Rayba (G85)", "Havşa (G82)"}; ui::alan("Döngü"); if (ImGui::Combo("##Döngü", &d, donguler, 6)) { op.dongu = (cam::DelikDongu)d; degisti = true; } if (op.dongu == cam::DelikDongu::PeckDelme) { ui::alan("Peck Derinliği (mm)"); degisti |= surukleF64("##Peck Derinliği", op.peckDerinlik, 0.1f); } if (op.dongu == cam::DelikDongu::Havsa) { ui::alan("Bekleme (s)"); degisti |= surukleF64("##Bekleme", op.bekleme, 0.05f); } if (op.dongu == cam::DelikDongu::Kilavuz) { ui::alan("Diş Adımı (mm)"); degisti |= surukleF64("##Diş Adımı", op.disAdimi, 0.05f); } break; } case CamIslemTip::Kaba3D: case CamIslemTip::Finis3D: case CamIslemTip::RestKaba: case CamIslemTip::SweepFinis: case CamIslemTip::AdvancedFinis: case CamIslemTip::KonturGudumlu: case CamIslemTip::ReworkFinis: { ImGui::SeparatorText("OpenCAMLib"); ui::alan("Örnekleme (mm)"); degisti |= surukleF64("##Örnekleme", op.ornekleme, 0.02f); ImGui::SetItemTooltip("Küçük değer = hassas + yavaş (kaba: 0.5, finiş: 0.1)"); ui::alan("Min. Örnekleme (mm)"); degisti |= surukleF64("##Min. Örnekleme", op.minOrnekleme, 0.005f); if (op.tip == CamIslemTip::Kaba3D) if (ui::anahtarSatiri("Cep-içi doldur (waterline + boşaltma)", &op.cepDoldur)) degisti = true; const bool finis = op.tip == CamIslemTip::Finis3D || op.tip == CamIslemTip::SweepFinis || op.tip == CamIslemTip::AdvancedFinis || op.tip == CamIslemTip::KonturGudumlu; if (op.tip == CamIslemTip::Finis3D || op.tip == CamIslemTip::AdvancedFinis) { ui::alan("Tarama Açısı (°)"); degisti |= surukleF64("##Tarama Açısı", op.finisAciDerece, 1.0f, "%.0f"); } if (finis) { ui::alan("Scallop (mm, 0=oransal)"); degisti |= surukleF64("##Scallop", op.scallop, 0.005f, "%.3f"); ImGui::SetItemTooltip("Kalıntı tarak yüksekliği → stepover otomatik hesaplanır"); } if (op.tip == CamIslemTip::RestKaba || op.tip == CamIslemTip::ReworkFinis) { ui::alan("Önceki Takım Çapı (mm)"); degisti |= surukleF64("##Önceki Takım Çapı", op.oncekiTakimCap, 0.1f, "%.2f"); ImGui::SetItemTooltip("Bu işlemden önce kullanılan büyük takımın çapı"); } if (op.tip == CamIslemTip::AdvancedFinis) { ui::alan("Dik Eşiği (°)"); degisti |= surukleF64("##Dik Eşiği", op.dikEsikDerece, 1.0f, "%.0f"); ImGui::SetItemTooltip("Bu eğimin üstü → waterline (dik), altı → paralel (sığ)"); } if (op.tip == CamIslemTip::KonturGudumlu) { int paso = op.konturPaso; ui::alan("Ofset Paso"); if (ImGui::SliderInt("##Ofset Paso", &paso, 1, 40)) { op.konturPaso = paso; degisti = true; } } if (op.tip == CamIslemTip::SweepFinis || op.tip == CamIslemTip::KonturGudumlu) ImGui::TextColored(SOLUK, "Sürüş kenarı: %d adet (Geometri → Seçimden Al)", (int)op.surusKenarlari.size()); break; } default: break; } } void baglantiSekmesi(CamIslem& op, bool& degisti) { const ImVec4 SOLUK = ui::tema().metinSoluk; if (op.tip == CamIslemTip::Delik) { ImGui::TextColored(SOLUK, "Delik döngüsü giriş/çıkışı sabit döngü içindedir"); return; } int g = (int)op.giris; const char* girisler[] = {"Dikey Dalma", "Rampa", "Helisel"}; ui::alan("Giriş"); if (ImGui::Combo("##Giriş", &g, girisler, 3)) { op.giris = (cam::GirisTip)g; degisti = true; } if (op.giris != cam::GirisTip::Dalma) { ui::alan("Rampa Açısı (°)"); degisti |= surukleF64("##Rampa Açısı", op.rampaAci, 0.1f, "%.1f"); } if (op.giris == cam::GirisTip::Helis) { ui::alan("Helis Çapı (×D)"); degisti |= surukleF64("##Helis Çapı", op.helisCapOran, 0.02f, "%.2f"); } if (op.tip == CamIslemTip::Profil) { ImGui::SeparatorText("Tab / Köprü"); if (ui::anahtarSatiri("Tab Etkin", &op.tabEtkin)) degisti = true; if (op.tabEtkin) { int say = op.tabSayi; ui::alan("Tab Sayısı"); if (ImGui::SliderInt("##Tab Sayısı", &say, 1, 12)) { op.tabSayi = say; degisti = true; } ui::alan("Tab Genişliği (mm)"); degisti |= surukleF64("##Tab Genişliği", op.tabGenislik, 0.1f); ui::alan("Tab Yüksekliği (mm)"); degisti |= surukleF64("##Tab Yüksekliği", op.tabYukseklik, 0.1f); } } } // Op-basina pencere pin ("ustte tut") durumu — UI-only, kalici degil. std::unordered_map g_pinDurum; // Tek operasyonun kendi yuzen/pinlenebilir penceresi (5 sekme + alt eylemler). // Ayni anda birden fazla acik olabilir (###op_ benzersiz). Kapaninca // cam.acikPencereler'den cikar. Web fiko-cam-dialog.ts eslenigi. void operasyonPenceresiCiz(Cekirdek& cekirdek, Sahne& sahne, CamSistemi& cam, CamIslem& op) { using namespace fiko::ui; using u32 = fiko::u32; // ui::u32(ImVec4) ile tip cakismasini onler const ImVec4 SOLUK = ui::tema().metinSoluk; bool& ustte = g_pinDurum[op.kimlik]; char baslik[176]; std::snprintf(baslik, sizeof(baslik), "%s %s###op_%u", cam::islemTipSimge(op.tip), op.ad.c_str(), op.kimlik); bool acik = true; { Pencere p{baslik, &acik, {.boyut = {300, 560}, .pinDurum = &ustte}}; if (p) { // ---- Ad (inline duzenlenebilir) + durum ---- { char buf[96]; std::snprintf(buf, sizeof(buf), "%s", op.ad.c_str()); ImGui::SetNextItemWidth(-1); if (ImGui::InputText("##ad", buf, sizeof(buf))) op.ad = buf; } if (!op.hata.empty()) ui::bilgiSeridi(3, op.hata.c_str()); bool degisti = false; if (sekmeBaslat("camSekmeler")) { if (sekme("Geometri", "◉")) { geometriSekmesi(sahne, cam, op); sekmeBitir(); } if (sekme("Takım", "🔧")) { takimSekmesi(cam, op, degisti); sekmeBitir(); } if (sekme("Yükseklik", "↕")) { yukseklikSekmesi(op, degisti); sekmeBitir(); } if (sekme("Geçişler", "⇄")) { gecislerSekmesi(op, degisti); sekmeBitir(); } if (sekme("Bağlantı", "🔗")) { baglantiSekmesi(op, degisti); sekmeBitir(); } sekmeKapat(); } if (degisti) op.kirli = true; // ---- Alt eylem cubugu: Hesapla / Replay / Sil ---- ImGui::Separator(); if (!op.yol.bosMu()) ImGui::TextColored(SOLUK, "Yol: %.0f mm kesme, %.1f dk", op.yol.kesmeUzunluk, op.yol.sureDk); ImGui::BeginDisabled(op.hesaplaniyor); if (ImGui::Button(op.hesaplaniyor ? "Hesaplanıyor..." : "⚙ Hesapla", {-150, 0})) cam.hesapla(op.kimlik); ImGui::EndDisabled(); ImGui::SameLine(); ImGui::BeginDisabled(op.yol.bosMu()); if (ImGui::Button("▶ Replay", {-70, 0})) camSimPencereAc(op.kimlik); ImGui::EndDisabled(); ImGui::SetItemTooltip(op.yol.bosMu() ? "Önce yolu hesaplayın" : "Simülasyon penceresini aç"); ImGui::SameLine(); if (ikonButon("🗑", "Operasyonu sil")) cekirdek.uygula(std::make_unique(cam, op.kimlik)); } } if (!acik) cam.pencereKapat(op.kimlik); } } // namespace void camPaneliCiz(Cekirdek& cekirdek, Sahne& sahne, cam::CamSistemi& cam, bool& ustte, void* hwnd) { (void)ustte; // "Üretim Programı" penceresi kaldırıldı → CAM ağacı ANA ürün ağacında (void)hwnd; // (camAgacTopla). Bu fonksiyon artık yalnız op-başına pencereleri çizer. // ---- Op-başına ayrı yüzen pencereler (geçersiz kimlikleri ayıkla) ---- for (size_t i = cam.acikPencereler.size(); i-- > 0;) { CamIslem* op = cam.bul(cam.acikPencereler[i]); if (!op) { cam.acikPencereler.erase(cam.acikPencereler.begin() + (std::ptrdiff_t)i); continue; } operasyonPenceresiCiz(cekirdek, sahne, cam, *op); } } } // namespace fiko