#include "fiko/baglam/baglam_motoru.hpp" #include #include "fiko/core/gunluk.hpp" #include "fiko/cekirdek/cekirdek.hpp" #include "fiko/cekirdek/olay.hpp" #include "fiko/geometri/brep.hpp" #include "fiko/sahne/sahne.hpp" namespace fiko::baglam { namespace { // TEŞHİS: hover hedefi değişince koşan bölümlerden hangisi takılıyor (>33 ms → tek satır). struct Olcer { const char* ad; std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now(); ~Olcer() { const f64 ms = std::chrono::duration( std::chrono::steady_clock::now() - t0).count(); if (ms > 33.0) gunluk::uyari("[perf] ADIM YAVAS: baglam/{} — {:.0f} ms", ad, ms); } }; } // namespace BaglamMotoru::BaglamMotoru(Sahne& sahne, Cekirdek& cekirdek) : sahne_(sahne), cekirdek_(cekirdek) { // Varsayılan sağlayıcılar (registri-meta + tip/kategori). Makro/plugin ek sağlayıcıyı // kurallar().ekle ile bunların YANINA kaydeder (anayasa: registry → makro/plugin bedava). varsayilanKurallariKur(kurallar_); } // registry meta + tip/kategori sağlayıcı + FikoNesne köprü → tek liste (dedup). void BaglamMotoru::kurallariTopla() { auto& out = karar_.ogeler; out.clear(); const BaglamHedef& h = karar_.hedef; if (h.kategori == HedefKategori::Bos && h.govdeId == 0) { // Boşluk: tip sağlayıcı (nested Ekle/Çizim) tek kaynak; registry atlanır. } // 1) Kayıtlı sağlayıcılar: registri-meta + tip/kategori + plugin/makro (yalnız EKLER). for (const auto& s : kurallar_.hepsi()) s->oner(h, durum_, cekirdek_, out); // 2) Per-nesne köprü (§3 örnek-seviyesi): düğüm kendi sağ-tık öğelerini bildirir → // tip-sağlayıcının ÜSTÜNE eklenir (web türevin base'i genişletmesi gibi). if (h.govdeId) { if (FikoNesne* n = sahne_.nesneKopru(h.govdeId)) { for (const MenuOge& o : n->sagMenu) { const bool etkin = !o.etkinMi || o.etkinMi(cekirdek_); out.push_back({regKimlik(o.grup, o.ad), o.ad, o.simge, etkin, -1, {}}); } } } // 3) Dedup (aynı komutKimlik iki kez gelmesin; boş kimlik = ara-öğe, korunur). for (std::size_t i = 0; i < out.size(); ++i) { if (out[i].komutKimlik.empty()) continue; for (std::size_t j = out.size(); j-- > i + 1;) if (out[j].komutKimlik == out[i].komutKimlik) out.erase(out.begin() + j); } } const BaglamHedef& BaglamMotoru::guncelle(const girdi::HoverBilgi& hb, const BaglamDurum& durum) { durum_ = durum; BaglamHedef& h = karar_.hedef; h = BaglamHedef{}; // sıfırla (POD; ısı-yol tahsissiz) h.topoloji = hb.tur; h.govdeId = hb.govdeId; h.altId = hb.altId; h.dunyaNokta = hb.dunyaNokta; const Dugum* d = hb.govdeId ? sahne_.bul(hb.govdeId) : nullptr; if (!d) { h.kategori = HedefKategori::Bos; } else { h.dugumTip = d->tip; const void* brepPtr = static_cast(d->brep.get()); // Brep alt-tip sorgusu — YALNIZ hedef anahtarı değişince. yuzBilgi/kenarBilgi = // OCCT ordinal-tarama + GProp integrali (yoğun mesh'te ms mertebesi); hedef sabitken // kare-başı sorgu YOK (tasarım §5, hover-kart önbellek deseni buraya taşındı). const bool yenile = hb.govdeId != obGovde_ || hb.altId != obAlt_ || hb.tur != obTopo_ || brepPtr != obBrep_; if (yenile) { Olcer o{"brep sorgusu (yuzBilgiHizli/kenarBilgi)"}; obGeo_ = GeoOzet{}; obOlcu_ = 0; const auto& brepSp = d->brep; const auto* brep = brepSp.get(); bool sogukKaldi = false; // arka plan hesabı bitmedi → hedef anahtarını KİLİTLEME if (brep && hb.altId) { if (hb.tur == girdi::HedefTur::Yuz) { geometri::YuzBilgi yb; // BLOKLAMAYAN: yalnız önbellek okunur. Soğuksa hesap ARKA PLANA verilir ve bu // kare ölçü/geometri özeti boş kalır (birkaç kare sonra dolar). Bloklayan sürüm // dev B-spline yüzde hover'da 1.1-13 s tek-kare donması yapıyordu. if (!brep->yuzBilgiOnbellekteMi(hb.altId)) { geometri::yuzBilgiArkaPlanIste(brepSp, hb.altId); sogukKaldi = true; } if (brep->yuzBilgiHizli(hb.altId, yb)) { obGeo_.duzlem = yb.duzlemMi; obGeo_.silindir = yb.silindirMi; obGeo_.kure = yb.kureMi; obOlcu_ = yb.alan; } } else if (hb.tur == girdi::HedefTur::Kenar) { geometri::KenarBilgi kb; if (!brep->kenarBilgiOnbellekteMi(hb.altId)) { geometri::kenarBilgiArkaPlanIste(brepSp, hb.altId); sogukKaldi = true; } if (brep->kenarBilgiHizli(hb.altId, kb)) { obGeo_.dogru = kb.dogruMu; obGeo_.cember = kb.cemberMi; obOlcu_ = kb.uzunluk; } } } if (!sogukKaldi) { // soğukken kilitleme → hesap bitince bir sonraki kare tazeler obGovde_ = hb.govdeId; obAlt_ = hb.altId; obTopo_ = hb.tur; obBrep_ = brepPtr; } } h.olcu = obOlcu_; Olcer ok{"kategoriBelirle"}; h.kategori = kategoriBelirle(d->tip, hb.tur, hb.altId, durum.sketchAktif, obGeo_); } // Olay: hedef kategorisi VEYA durum imzası değişince yay (her kare DEĞİL). Zero-alloc. const u32 durumImza = static_cast(durum.arac) ^ (durum.secimSayi * 2654435761u) ^ (static_cast(durum.secimTuru) << 3) ^ (durum.sketchAktif ? 0x8000u : 0u); if (h.kategori != evtKategori_ || h.govdeId != evtGovde_ || durumImza != evtDurumImza_) { evtKategori_ = h.kategori; evtGovde_ = h.govdeId; evtDurumImza_ = durumImza; // Bağlam→komut eşlemesi YALNIZ burada (değişimde) — kare-başı değil (§5). Sunum // kanalları (halka/toolbar/HUD) sonKarar().ogeler'i okur. { Olcer o{"kurallariTopla"}; kurallariTopla(); } Olcer oy{"BaglamCozuldu yayini"}; cekirdek_.olaylar().yayinla( BaglamCozuldu{static_cast(h.kategori), h.govdeId, static_cast(karar_.ogeler.size())}); } return h; } } // namespace fiko::baglam