#include "cam_operasyon_penceresi.hpp" #include #include #include #include "cam_makro_onizleme.hpp" #include "cam_simulasyon_penceresi.hpp" #include "cam_strateji_semasi.hpp" #include "cam_takim_ekseni_penceresi.hpp" #include "fiko/cam/cam_secim.hpp" #include "fiko/cam/cam_sistemi.hpp" #include "fiko/cam/takim.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 "imgui.h" #include "pencere_util.hpp" namespace fiko { namespace { using cam::CamGeometri; using cam::CamHizlar; using cam::CamMakro; using cam::CamOperasyon; using cam::CamStrateji; using cam::MakroAdim; using cam::CamSecimKip; using cam::CamSistemi; using cam::Takim; // Bir seçim modu butonu: aktifse "basılı" (cyan) görünür, tekrar tık = bitir. // baglı=true → yeşil ✓ etiket; değilse kırmızı. camSecim.aktifMi ile durum. bool secimButonu(CamSistemi& cam, CamOperasyon& op, CamSecimKip kip, const char* etiket, std::function gc) { const bool aktif = cam.secim().aktifMi(op.kimlik, kip); if (aktif) ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.08f, 0.42f, 0.55f, 1.0f}); const bool basildi = ImGui::Button(etiket, {-1, 0}); if (aktif) ImGui::PopStyleColor(); if (basildi) cam.secim().baslat(op, kip, std::move(gc)); return basildi; } // Op-basina acik pencere + pin durumu (UI-only, kalici degil). cam_paneli.cpp // g_pinDurum kalibi. acikPencereler CamSistemi'de ESKI CamIslem'e ait — kullanma. std::unordered_map g_opAcik; std::unordered_map g_opPin; // f64 icin DragScalar sarimi; degisti bayragini toplar (cam_paneli.cpp ile ayni). 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); } // Enum combo yardimcisi: (int) cast + geri (T) cast, degisti toplar. template bool enumCombo(const char* etiket, T& deger, const char* const* etiketler, int adet, bool& degisti) { int v = (int)deger; if (ImGui::Combo(etiket, &v, etiketler, adet)) { deger = (T)v; degisti = true; return true; } return false; } // Bir yüz Z alanı yanında "🎯 yüzden-seç" düğmesi. Aktifken cyan; tık → düzlem // modu başlat (associatif faceId). Elle DragScalar değişince ref kopar (çağıran). void duzlemSecDugmesi(CamSistemi& cam, CamOperasyon& op, CamSecimKip kip, const char* id, f64& hedef, u32& ref, bool& degisti) { const ImVec4 YESIL = ui::tema().basari; ImGui::SameLine(); const bool aktif = cam.secim().aktifMi(op.kimlik, kip); ImGui::PushID(id); if (aktif) ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.08f, 0.42f, 0.55f, 1.0f}); if (ImGui::SmallButton("🎯")) { cam.secim().duzlemBaslat(op, kip, [&hedef, &ref](f64 z, u32 faceId) { hedef = z; ref = faceId; }, [] {}); } if (aktif) ImGui::PopStyleColor(); ImGui::PopID(); ImGui::SetItemTooltip(ref ? "Yüzden alınmış (associatif) — çift-tık için sahnede yüze tıkla" : "Yüzeyden seç: sahnede bir yüze tıkla → Z bu yüze bağlanır"); if (ref) { ImGui::SameLine(); ImGui::TextColored(YESIL, "⛓#%u", ref); } (void)degisti; } // ============================ SEKME A — GEOMETRİ ============================= void geometriSekmesi(CamSistemi& cam, CamOperasyon& op, bool& degisti) { const ImVec4 SOLUK = ui::tema().metinSoluk; const ImVec4 YESIL = ui::tema().basari; const ImVec4 KIRMIZI = ui::tema().hata; CamGeometri& g = op.geometri; const bool axial = cam::axialMi(op.tip); auto gc = [] {}; // pencere yenilemesi ImGui her kare zaten çizer // İnteraktif izometrik şema (Web Facing penceresi gibi) — rol tıklaması gerçek // sahneden-seçim modu başlatır, offset çift-tık düzenler. stratejiSemasiCiz(cam, op, {ImGui::GetContentRegionAvail().x, 200.0f}, degisti); ImGui::Spacing(); ImGui::SeparatorText("Geometri Seçimi (sahneden)"); if (axial) { // Zorunlu: en az 1 delik noktası. const bool var = !g.noktalar.empty(); ImGui::TextColored(var ? YESIL : KIRMIZI, var ? "● Nokta: %d seçili" : "● Nokta: seçilmedi", (int)g.noktalar.size()); secimButonu(cam, op, CamSecimKip::Nokta, "🎯 Delik Merkezi (sahneden)", gc); ImGui::SetItemTooltip("Sahnede yüze tıkla → delik ağzı noktası eklenir (ESC=bitir)"); if (var && ImGui::SmallButton("✕ Noktaları Temizle")) { g.noktalar.clear(); degisti = true; } } else { const bool konturVar = !g.konturlar.empty(); if (konturVar) ImGui::TextColored(YESIL, "● Profil: %d kontur", (int)g.konturlar.size()); else ImGui::TextColored(KIRMIZI, "● Profil: seçilmedi"); secimButonu(cam, op, CamSecimKip::Kontur, "⬚ Profil/Kontur (yüzden)", gc); ImGui::SetItemTooltip("Sahnede düz bir yüze tıkla → kontur OCCT'den çıkarılır"); secimButonu(cam, op, CamSecimKip::Kenar, "╱ Kenar Zinciri", gc); ImGui::SetItemTooltip("Kenarlara tıkla (toggle) → uç-uca kontur zincirlenir (ESC=bitir)"); if (konturVar && ImGui::SmallButton("✕ Konturu Temizle")) { g.konturlar.clear(); g.ustZRef = 0; degisti = true; } if (op.tip == cam::CamIslemTipCatia::Pocketing) { const bool adaVar = !g.adalar.empty(); ImGui::TextColored(adaVar ? YESIL : SOLUK, adaVar ? "● Ada: %d (opsiyonel)" : "○ Ada: yok (opsiyonel)", (int)g.adalar.size()); secimButonu(cam, op, CamSecimKip::Ada, "🏝 Ada Ekle", gc); ImGui::SetItemTooltip("Cep içinde işlenmeyecek ada yüzü seç (ESC=bitir)"); if (adaVar && ImGui::SmallButton("✕ Adaları Temizle")) { g.adalar.clear(); degisti = true; } } } ImGui::SeparatorText("Yükseklikler (mm)"); if (axial) { if (surukleF64("Üst Z", g.ustZ)) { g.ustZRef = 0; degisti = true; } // elle → ref kopar duzlemSecDugmesi(cam, op, CamSecimKip::DuzlemUst, "axUstZ", g.ustZ, g.ustZRef, degisti); ui::alan("Derinlik"); degisti |= surukleF64("##Derinlik", g.derinlik, 0.1f, "%.2f"); const bool capliTip = op.tip == cam::CamIslemTipCatia::ThreadMilling || op.tip == cam::CamIslemTipCatia::ThreadNoTap || op.tip == cam::CamIslemTipCatia::TSlotting; if (capliTip) { ui::alan("Hedef Çap"); degisti |= surukleF64("##Hedef Çap", g.cap, 0.1f, "%.2f"); } } else { if (surukleF64("Üst Z (yüzey)", g.ustZ)) { g.ustZRef = 0; degisti = true; } duzlemSecDugmesi(cam, op, CamSecimKip::DuzlemUst, "ustZ", g.ustZ, g.ustZRef, degisti); if (surukleF64("Alt Z (taban)", g.altZ)) { g.altZRef = 0; degisti = true; } duzlemSecDugmesi(cam, op, CamSecimKip::DuzlemAlt, "altZ", g.altZ, g.altZRef, degisti); const char* tabanlar[] = {"Kör (Kapalı)", "Açık (Breakthrough)"}; int taban = g.tabanAcik ? 1 : 0; ui::alan("Taban"); if (ImGui::Combo("##Taban", &taban, tabanlar, 2)) { g.tabanAcik = (taban == 1); degisti = true; } if (g.tabanAcik) { ui::alan("Geçiş Payı (mm)"); degisti |= surukleF64("##Geçiş Payı", g.breakthrough, 0.05f, "%.2f"); } if (op.tip == cam::CamIslemTipCatia::Pocketing) ImGui::TextColored(SOLUK, "Açık Kenarlar: %d adet (Open Pocket)", (int)g.acikKenarlar.size()); } ImGui::SeparatorText("Takım Ekseni"); { const bool yuzey = op.takimYonu.kaynak == cam::TakimYonu::Kaynak::Yuzey; ImGui::TextColored(yuzey ? YESIL : SOLUK, "%s ⊥ (%.2f, %.2f, %.2f)", cam::takimYonuKaynakAdi(op.takimYonu.kaynak), op.takimYonu.yon.x, op.takimYonu.yon.y, op.takimYonu.yon.z); secimButonu(cam, op, CamSecimKip::ToolAxis, "🎯 Yüzeyden Takım Ekseni", gc); ImGui::SetItemTooltip("Sahnede yüze tıkla → takım ekseni yüz normaline hizalanır"); if (ImGui::Button("🧭 Takım Ekseni Penceresi (Triad)", {-1, 0})) camTakimEkseniPencereAc(op.kimlik); ImGui::SetItemTooltip("İnteraktif triad: eksene sabitle / ters çevir / IJK / sabit düzlem"); } ImGui::SeparatorText("Offsets (mm)"); ui::alan("Ofset Üst"); degisti |= surukleF64("##Ofset Üst", g.ofsetUst, 0.02f, "%.2f"); ui::alan("Ofset Kontur"); degisti |= surukleF64("##Ofset Kontur", g.ofsetKontur, 0.02f, "%.2f"); ui::alan("Ofset Taban"); degisti |= surukleF64("##Ofset Taban", g.ofsetTaban, 0.02f, "%.2f"); ui::alan("Ofset Check"); degisti |= surukleF64("##Ofset Check", g.ofsetCheck, 0.02f, "%.2f"); } // Geometri sekmesinde zorunlu seçim eksik mi (sekme durum ışığı için). bool geometriEksik(const CamOperasyon& op) { if (cam::axialMi(op.tip)) return op.geometri.noktalar.empty(); return op.geometri.konturlar.empty(); } // ============================ SEKME B — STRATEJİ ============================ void stretejiFreze(CamOperasyon& op, bool& degisti) { CamStrateji& s = op.strateji; const auto tip = op.tip; ImGui::SeparatorText("Modlar"); const char* yolStilleri[] = {"Helisel", "Zigzag", "Tek Yön"}; ui::alan("Yol Stili"); enumCombo("##Yol Stili", s.yolStili, yolStilleri, 3, degisti); const char* frezYonu[] = {"Eş (Climb)", "Zıt (Conv)"}; ui::alan("Frez Yönü"); enumCombo("##Frez Yönü", s.yon, frezYonu, 2, degisti); const char* koseTipleri[] = {"Dairesel", "Keskin", "Optimize", "Zorunlu"}; ui::alan("Köşe Tipi"); enumCombo("##Köşe Tipi", s.koseTip, koseTipleri, 4, degisti); const char* radyalModlar[] = {"Çap %", "Maks", "Yollar"}; ui::alan("Radyal Mod"); enumCombo("##Radyal Mod", s.radialMod, radyalModlar, 3, degisti); const char* eksenelModlar[] = {"Maks Derinlik", "Seviye"}; ui::alan("Eksenel Mod"); enumCombo("##Eksenel Mod", s.axialMod, eksenelModlar, 2, degisti); const char* finisModlar[] = {"Yok", "Tabanda"}; ui::alan("Finiş Mod"); enumCombo("##Finiş Mod", s.finisMod, finisModlar, 2, degisti); ImGui::SeparatorText("Genel"); if (s.koseTip == cam::KoseTip::Dairesel || s.koseTip == cam::KoseTip::Zorunlu) { ui::alan("Köşe Yarıçap (mm)"); degisti |= surukleF64("##Köşe Yarıçap", s.koseR, 0.05f, "%.2f"); } ui::alan("Makine Toleransı (mm)"); degisti |= surukleF64("##Makine Toleransı", s.makineToleransi, 0.005f, "%.3f"); if (tip == cam::CamIslemTipCatia::Contouring || tip == cam::CamIslemTipCatia::CurveFollow) { ImGui::SeparatorText("Kontur / Kompanzasyon"); const char* taraflar[] = {"İçeride", "Dışarıda", "Üzerinde"}; ui::alan("Takım Tarafı"); enumCombo("##Takım Tarafı", s.taraf, taraflar, 3, degisti); if (ui::anahtarSatiri("Cutter Comp (G41/G42)", &s.kompanzasyonAktif)) degisti = true; if (s.kompanzasyonAktif) { const char* kompler[] = {"Yok", "G41 (Sol)", "G42 (Sağ)"}; ui::alan("Kompanzasyon"); enumCombo("##Kompanzasyon", s.kompanzasyon, kompler, 3, degisti); } ImGui::SeparatorText("Tab / Köprü"); if (ui::anahtarSatiri("Tab Etkin", &s.tabAktif)) degisti = true; if (s.tabAktif) { ui::alan("Tab Adet"); if (ImGui::SliderInt("##Tab Adet", &s.tabAdet, 1, 12)) degisti = true; ui::alan("Tab Genişliği (mm)"); degisti |= surukleF64("##Tab Genişliği", s.tabGenislik, 0.1f, "%.2f"); ui::alan("Tab Yüksekliği (mm)"); degisti |= surukleF64("##Tab Yüksekliği", s.tabYukseklik, 0.1f, "%.2f"); } } if (tip == cam::CamIslemTipCatia::CircularMill) { ImGui::SeparatorText("Dairesel Frezeleme"); ui::alan("Radyal Pas"); if (ImGui::SliderInt("##Radyal Pas", &s.daireYolSayisi, 1, 20)) degisti = true; ui::alan("Pas Mesafe (mm)"); degisti |= surukleF64("##Pas Mesafe", s.daireYolMesafe, 0.1f, "%.2f"); } ImGui::SeparatorText("Radyal · Eksenel"); if (s.radialMod == cam::RadyalMod::CapYuzde) { f32 y = (f32)s.yanalHatveYuzde; ui::alan("Yanal · Çap %"); if (ImGui::SliderFloat("##Yanal · Çap %", &y, 5.0f, 90.0f, "%.0f%%")) { s.yanalHatveYuzde = y; degisti = true; } } else { ui::alan("Yanal Hatve (mm)"); degisti |= surukleF64("##Yanal Hatve", s.yanalHatve, 0.1f, "%.2f"); } if (s.axialMod == cam::EksenelMod::Seviye) { ui::alan("Seviye Sayısı"); if (ImGui::SliderInt("##Seviye Sayısı", &s.seviyeSayisi, 1, 50)) degisti = true; } else { ui::alan("Kesim Derinliği (mm)"); degisti |= surukleF64("##Kesim Derinliği", s.eksenelHatve, 0.1f, "%.2f"); } ImGui::SeparatorText("Finiş"); ui::alan("Yan Pay (mm)"); degisti |= surukleF64("##Yan Pay", s.finisPayi, 0.02f, "%.2f"); if (s.finisMod == cam::FinisMod::Tabanda) { ui::alan("Taban Payı (mm)"); degisti |= surukleF64("##Taban Payı", s.tabanPayi, 0.02f, "%.2f"); } if (tip == cam::CamIslemTipCatia::Pocketing) if (ui::anahtarSatiri("Tam Finiş", &s.finisTam)) degisti = true; if (ui::anahtarSatiri("Scallop Önle", &s.avoidScallops)) degisti = true; if (tip == cam::CamIslemTipCatia::Facing) { ImGui::SeparatorText("Facing"); ui::alan("Raster Açısı (°)"); degisti |= surukleF64("##Raster Açısı", s.rasterAci, 1.0f, "%.0f"); } ImGui::SeparatorText("Trochoidal"); if (ui::anahtarSatiri("Trochoidal Aktif", &s.trochoidalAktif)) degisti = true; if (s.trochoidalAktif) { ui::alan("Adım (mm)"); degisti |= surukleF64("##Adım", s.trochoidalAdim, 0.1f, "%.2f"); ui::alan("Genişlik (mm)"); degisti |= surukleF64("##Genişlik", s.trochoidalGenislik, 0.1f, "%.2f"); } } void stratejiAxial(CamStrateji& s, bool& degisti) { ImGui::SeparatorText("Döngü"); const char* donguler[] = {"Standart", "Gagalı", "Talaş Kır", "Beklemeli"}; ui::alan("Döngü"); enumCombo("##Döngü", s.dongu, donguler, 4, degisti); const char* dwellModlar[] = {"Kapalı", "Devir", "Süre"}; ui::alan("Dwell Modu"); enumCombo("##Dwell Modu", s.dwellMod, dwellModlar, 3, degisti); const char* siralar[] = {"Seçim", "En Yakın"}; ui::alan("Nokta Sırası"); enumCombo("##Nokta Sırası", s.noktaSirala, siralar, 2, degisti); ImGui::SeparatorText("Peck / Dwell"); ui::alan("Peck Derinlik (mm)"); degisti |= surukleF64("##Peck Derinlik", s.peckDerinlik, 0.1f, "%.2f"); ui::alan("Geri Çekme (mm)"); degisti |= surukleF64("##Geri Çekme", s.geriCekme, 0.05f, "%.2f"); if (s.dwellMod != cam::DwellMod::Kapali) { ui::alan("Dwell Değer"); degisti |= surukleF64("##Dwell Değer", s.dwellDeger, 0.05f, "%.2f"); } ui::alan("Peck Azaltma (mm)"); degisti |= surukleF64("##Peck Azaltma", s.decrement, 0.05f, "%.2f"); ui::alan("Min. Peck (mm)"); degisti |= surukleF64("##Min. Peck", s.decrementLimit, 0.05f, "%.2f"); } void stratejiSekmesi(CamOperasyon& op, bool& degisti) { if (cam::axialMi(op.tip)) stratejiAxial(op.strateji, degisti); else stretejiFreze(op, degisti); } // ============================= SEKME C — TAKIM ============================= void takimSekmesi(CamSistemi& cam, CamOperasyon& op, bool& degisti) { const ImVec4 SOLUK = ui::tema().metinSoluk; Takim* aktif = cam.takimBul(op.takimId); char aktifEtiket[128] = "—"; if (aktif) std::snprintf(aktifEtiket, sizeof(aktifEtiket), "T%d %s (Ø%.2f)", aktif->numara, aktif->ad.c_str(), aktif->cap); ui::alan("Takım"); if (ImGui::BeginCombo("##Takım", aktifEtiket)) { for (const Takim& t : cam.takimlar()) { char etiket[128]; std::snprintf(etiket, sizeof(etiket), "T%d %s (Ø%.2f)", t.numara, t.ad.c_str(), t.cap); if (ImGui::Selectable(etiket, t.numara == op.takimId)) { op.takimId = t.numara; degisti = true; } } ImGui::EndCombo(); } if (aktif) { ImGui::SeparatorText("Özet"); ui::istatistikSatiri("Tip", cam::takimTipAdi(aktif->tip)); ui::istatistikSatiri("Çap", (f32)aktif->cap, "mm", "Ø%.2f"); ui::istatistikSatiri("Ağız", (f32)aktif->agizSayisi, nullptr, "%.0f"); ui::istatistikSatiri("T-No", (f32)aktif->numara, nullptr, "%.0f"); } else { ImGui::TextColored(SOLUK, "Takım seçilmedi"); } ImGui::Spacing(); if (ImGui::Button("✏ Takımı Düzenle (Grafiksel)", {-1, 0})) {} ImGui::SetItemTooltip("Takım penceresi — ayrı ajan/yakında"); if (ImGui::Button("+ Yeni Takım Ekle", {-1, 0})) {} ImGui::SetItemTooltip("Takım penceresi — ayrı ajan/yakında"); } // ============================== SEKME D — HIZ ============================== void hizSekmesi(CamSistemi& cam, CamOperasyon& op, bool& degisti) { const ImVec4 SOLUK = ui::tema().metinSoluk; CamHizlar& h = op.hizlar; const Takim* aktif = cam.takimBul(op.takimId); 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("⚡ Otomatik Hesapla (Vc/fz)", {-1, 0}) && aktif) { const cam::Malzeme& m = malz[(size_t)cam.malzemeIndeks]; const cam::FeedsSpeeds fs = cam::feedsSpeeds(m, aktif->cap, aktif->agizSayisi); h.kesimHiz = m.vc; h.disBasinaIlerleme = m.fz; h.devir = fs.devir; h.ilerleme = fs.ilerleme; h.dalmaIlerleme = fs.ilerleme * 0.3; degisti = true; } if (!aktif) ImGui::TextColored(SOLUK, "Hesap için önce takım seçin"); ImGui::SeparatorText("Kesim"); ui::alan("Kesme Hızı Vc (m/dk)"); degisti |= surukleF64("##Kesme Hızı Vc", h.kesimHiz, 1.0f, "%.0f"); ui::alan("Diş Başına fz (mm)"); degisti |= surukleF64("##Diş Başına fz", h.disBasinaIlerleme, 0.005f, "%.3f"); ImGui::SeparatorText("Hesaplanan"); ui::alan("Devir (rpm)"); degisti |= surukleF64("##Devir", h.devir, 10.0f, "%.0f"); ui::alan("İlerleme (mm/dk)"); degisti |= surukleF64("##İlerleme", h.ilerleme, 10.0f, "%.0f"); ui::alan("Dalma (mm/dk)"); degisti |= surukleF64("##Dalma", h.dalmaIlerleme, 5.0f, "%.0f"); ui::alan("Yaklaşma (mm/dk)"); degisti |= surukleF64("##Yaklaşma", h.yaklasmaIlerleme, 5.0f, "%.0f"); ui::alan("Geri Çekme (mm/dk)"); degisti |= surukleF64("##Geri Çekme", h.geriCekmeIlerleme, 10.0f, "%.0f"); ui::alan("Finiş (mm/dk)"); degisti |= surukleF64("##Finiş", h.finisIlerleme, 10.0f, "%.0f"); } // ============================= SEKME E — MAKRO ============================= void makroAdimlari(CamMakro& m, bool& degisti) { const char* adimTipler[] = {"Eksenel", "Teget", "Rampa", "Helis", "Düzleme"}; int silinecek = -1, tasiYukari = -1, tasiAsagi = -1; for (int i = 0; i < (int)m.adimlar.size(); ++i) { MakroAdim& a = m.adimlar[(size_t)i]; ImGui::PushID(i); ImGui::SetNextItemWidth(120); enumCombo("##adimTip", a.tip, adimTipler, 5, degisti); ImGui::SameLine(); if (ImGui::SmallButton("↑")) tasiYukari = i; ImGui::SameLine(); if (ImGui::SmallButton("↓")) tasiAsagi = i; ImGui::SameLine(); if (ImGui::SmallButton("✕")) silinecek = i; switch (a.tip) { case cam::MakroAdimTip::Eksenel: case cam::MakroAdimTip::Teget: ui::alan("Mesafe (mm)"); degisti |= surukleF64("##Mesafe", a.mesafe, 0.1f, "%.2f"); break; case cam::MakroAdimTip::Rampa: ui::alan("Açı (°)"); degisti |= surukleF64("##Açı", a.aci, 0.5f, "%.1f"); ui::alan("Mesafe (mm)"); degisti |= surukleF64("##Mesafe", a.mesafe, 0.1f, "%.2f"); break; case cam::MakroAdimTip::Helis: ui::alan("Açı (°)"); degisti |= surukleF64("##Açı", a.aci, 0.5f, "%.1f"); ui::alan("Yarıçap (mm)"); degisti |= surukleF64("##Yarıçap", a.yaricap, 0.1f, "%.2f"); break; case cam::MakroAdimTip::Duzleme: ui::alan("Hedef Z (mm)"); degisti |= surukleF64("##Hedef Z", a.hedefZ); break; } ImGui::Separator(); ImGui::PopID(); } if (ImGui::Button("+ Adım", {-1, 0})) { m.adimlar.push_back({}); degisti = true; } if (silinecek >= 0) { m.adimlar.erase(m.adimlar.begin() + silinecek); degisti = true; } else if (tasiYukari > 0) { std::swap(m.adimlar[(size_t)tasiYukari], m.adimlar[(size_t)tasiYukari - 1]); degisti = true; } else if (tasiAsagi >= 0 && tasiAsagi < (int)m.adimlar.size() - 1) { std::swap(m.adimlar[(size_t)tasiAsagi], m.adimlar[(size_t)tasiAsagi + 1]); degisti = true; } } void makroDetay(CamMakro& m, bool& degisti) { if (ui::anahtarSatiri("Aktif", &m.aktif)) degisti = true; switch (m.tip) { case cam::MakroTip::Clearance: ui::alan("Güvenlik Z (mm)"); degisti |= surukleF64("##Güvenlik Z", m.guvenlikZ); ui::alan("Yaklaşma Z (mm)"); degisti |= surukleF64("##Yaklaşma Z", m.yaklasmaZ); break; case cam::MakroTip::ReturnLevel: case cam::MakroTip::ReturnBetween: ui::alan("Sıçrama (mm)"); degisti |= surukleF64("##Sıçrama", m.jumpYuksek, 0.1f, "%.2f"); break; default: { // Approach / Retract / LinkApproach / LinkRetract // Geri çekme mi (retract görsel yönü yukarı): Retract / LinkRetract. const bool ret = m.tip == cam::MakroTip::Retract || m.tip == cam::MakroTip::LinkRetract; makroOnizlemeCiz(m, ret, {ImGui::GetContentRegionAvail().x, 130.0f}, degisti); ImGui::Spacing(); const char* modlar[] = {"Hazır", "Custom (Build by user)"}; ui::alan("Mod"); enumCombo("##Mod", m.mod, modlar, 2, degisti); if (m.mod == cam::MakroMod::Hazir) { const char* hareketler[] = {"Dikine", "Rampa", "Helis", "Yay", "Teğet Çizgi", "Ön Delik"}; ui::alan("Hareket"); enumCombo("##Hareket", m.hareketTip, hareketler, 6, degisti); ui::alan("Açı (°)"); degisti |= surukleF64("##Açı", m.aci, 0.5f, "%.1f"); ui::alan("Yarıçap (mm)"); degisti |= surukleF64("##Yarıçap", m.yaricap, 0.1f, "%.2f"); ui::alan("Mesafe (mm)"); degisti |= surukleF64("##Mesafe", m.mesafe, 0.1f, "%.2f"); } else { makroAdimlari(m, degisti); } break; } } } void makroSekmesi(CamOperasyon& op, bool& degisti) { const ImVec4 SOLUK = ui::tema().metinSoluk; static int seciliIdx = 0; if (seciliIdx >= (int)op.makrolar.size()) seciliIdx = 0; ImGui::TextColored(SOLUK, "Giriş/çıkış/bağlantı makroları"); for (int i = 0; i < (int)op.makrolar.size(); ++i) { CamMakro& m = op.makrolar[(size_t)i]; ImGui::PushID(i); char etiket[64]; std::snprintf(etiket, sizeof(etiket), "%s%s", cam::makroTipAdi(m.tip), m.aktif ? "" : " (pasif)"); if (ImGui::Selectable(etiket, i == seciliIdx)) seciliIdx = i; ImGui::PopID(); } ImGui::Separator(); if (!op.makrolar.empty()) { ImGui::PushID(seciliIdx); makroDetay(op.makrolar[(size_t)seciliIdx], degisti); ImGui::PopID(); ImGui::Spacing(); if (ImGui::SmallButton("✕ Seçili Makroyu Sil")) { op.makrolar.erase(op.makrolar.begin() + seciliIdx); degisti = true; } } else { ImGui::TextColored(SOLUK, "Makro yok"); } ImGui::SeparatorText("Yeni Makro"); static int yeniTip = 0; const char* tipler[] = {"Approach", "Retract", "LinkApproach", "LinkRetract", "ReturnLevel", "ReturnBetween", "Clearance"}; ImGui::SetNextItemWidth(-90); ImGui::Combo("##yeniTip", ¥iTip, tipler, 7); ImGui::SameLine(); if (ImGui::Button("+ Makro Ekle", {-1, 0})) { CamMakro m; m.tip = (cam::MakroTip)yeniTip; op.makrolar.push_back(m); seciliIdx = (int)op.makrolar.size() - 1; degisti = true; } } // ========================= TEK OPERASYON PENCERESİ ========================= void operasyonPenceresiCiz(Cekirdek& cekirdek, Sahne& sahne, CamSistemi& cam, CamOperasyon& op) { (void)cekirdek; (void)sahne; using namespace fiko::ui; using u32 = fiko::u32; // ui::u32(ImVec4) ile tip cakismasini onler const ImVec4 CYAN = ui::tema().vurgu; const ImVec4 SOLUK = ui::tema().metinSoluk; const ImVec4 YESIL = ui::tema().basari; const ImVec4 KIRMIZI = ui::tema().hata; const ImVec4 HATA_RENK = ui::tema().hata; bool& ustte = g_opPin[op.kimlik]; char baslik[192]; std::snprintf(baslik, sizeof(baslik), "%s %s###catop_%u", cam::islemTipCatiaSimge(op.tip), op.ad.c_str(), op.kimlik); bool acik = true; bool silindi = false; { Pencere p{baslik, &acik, {.boyut = {300, 560}, .pinDurum = &ustte}}; if (p) { // ---- Ad (inline düzenlenebilir) ---- { 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; } ImGui::TextColored(SOLUK, "%s", cam::islemTipCatiaAdi(op.tip)); bool degisti = false; // Geometri sekmesi durum ışığı: zorunlu seçim eksikse kırmızı, tamsa yeşil. const bool geoEksik = geometriEksik(op); char geoEtiket[48]; std::snprintf(geoEtiket, sizeof(geoEtiket), "%s Geometri###geoSekme", geoEksik ? "⚠" : "✓"); if (sekmeBaslat("catopSekmeler")) { // Geometri sekmesi renkli durum ışığı için ham BeginTabItem (sekme() renk almaz). ImGui::PushStyleColor(ImGuiCol_Text, geoEksik ? KIRMIZI : YESIL); const bool geoAcik = ImGui::BeginTabItem(geoEtiket); ImGui::PopStyleColor(); if (geoAcik) { geometriSekmesi(cam, op, degisti); ImGui::EndTabItem(); } if (sekme("Strateji", "🎯")) { stratejiSekmesi(op, degisti); sekmeBitir(); } if (sekme("Takım", "🔧")) { takimSekmesi(cam, op, degisti); sekmeBitir(); } if (sekme("Hız", "⚡")) { hizSekmesi(cam, op, degisti); sekmeBitir(); } if (sekme("Makro", "🔀")) { makroSekmesi(op, degisti); sekmeBitir(); } sekmeKapat(); } if (degisti) op.bayat = true; // ---- Alt eylem çubuğu: Hesapla / Replay / Sil ---- ImGui::Separator(); const bool mesgul = op.hesaplaniyor; if (mesgul) ImGui::BeginDisabled(); if (ImGui::Button("⚙ Hesapla", {-150, 0}) && !geoEksik) cam.opHesapla(op.kimlik); if (mesgul) ImGui::EndDisabled(); ImGui::SetItemTooltip(geoEksik ? "Önce zorunlu geometriyi seçin" : "Takım yolunu hesapla (arka planda)"); ImGui::SameLine(); if (geoEksik) { ImGui::TextColored(KIRMIZI, "⚠ zorunlu geometri eksik"); } else if (mesgul) { ImGui::TextColored(CYAN, "⟳ hesaplanıyor…"); } else if (!op.hata.empty()) { ImGui::TextColored(HATA_RENK, "%s", op.hata.c_str()); } else if (op.hesaplandi && !op.yol.bosMu()) { ImGui::TextColored(op.bayat ? SOLUK : YESIL, "✓ %.0f mm · %.1f dk", op.yol.kesmeUzunluk, op.yol.sureDk); } else { ImGui::TextColored(SOLUK, "yol hesaplanmadı"); } ImGui::SameLine(); if (ImGui::Button("▶ Replay", {-40, 0})) camSimPencereAc(op.kimlik); ImGui::SetItemTooltip("Simülasyon penceresini aç"); ImGui::SameLine(); if (ikonButon("🗑", "Operasyonu sil")) { // CamOperasyon icin Islem sinifi yok — undo'suz dogrudan sil (bu dalga). const u32 kimlik = op.kimlik; if (cam.secim().opKimlik() == kimlik) cam.secim().bitir(); // aktif seçimi kapat cam.opSil(kimlik); g_opAcik[kimlik] = false; silindi = true; } } } if (silindi) return; if (!acik) g_opAcik[op.kimlik] = false; } } // namespace void camOperasyonPencereAc(u32 kimlik) { g_opAcik[kimlik] = true; } void camOperasyonPencereleriCiz(Cekirdek& cekirdek, Sahne& sahne, cam::CamSistemi& cam) { for (auto it = g_opAcik.begin(); it != g_opAcik.end();) { if (!it->second) { it = g_opAcik.erase(it); continue; } CamOperasyon* op = cam.opBul(it->first); if (!op) { // op silinmis → pencereyi de kapat it = g_opAcik.erase(it); continue; } operasyonPenceresiCiz(cekirdek, sahne, cam, *op); ++it; } } } // namespace fiko