# Topolojik Görsel Özellikler — Dalga 1 (Temel) Uygulama Planı

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Her yüz/kenar/nokta'nın görsel özelliklerini (`OgeOzellik`) tutan veri modeli + çözüm API'si + undo/redo kalıcılığı + STEP renk köprüsü — böylece undo/redo'da renk kaybı biter ve tüm sistemin (render/UI/dosya/topo-naming) temeli atılır. **Bu dalga görsel çıktı DEĞİŞTİRMEZ; undo/redo renk-korumasını ve altyapıyı ekler.**

**Architecture:** `OgeOzellik` POD struct + öğe-tipi başına seyrek `unordered_map<u32,OgeOzellik>` (yalnız override edilenler) `Dugum` içinde + gövde-seviyesi varsayılan. Çözüm: `override varsa onu, yoksa gövde varsayılanı`. `DugumPusula` (undo snapshot) bu haritaları taşır. STEP `yuzRenkleri` açılışta `yuzOz[i].renk`'e köprülenir.

**Tech Stack:** C++23, mevcut `motor/sahne` ECS (Dunya/Dugum), `fiko_test.hpp` test çatısı, ctest.

## Global Constraints

- İsimlendirme Türkçe (teknik terimler hariç) — proje kuralı.
- Yeni sistem doğuştan makro+plugin+olay erişilebilir olmalı — bu dalgada VERİ modeli; olay/Lua Dalga 6.
- `Vertex`/render/shader'a bu dalgada DOKUNULMAZ (Dalga 2).
- Test exe: `fiko_sahne_test`; yeni test dosyası `motor/sahne/CMakeLists.txt` add_executable listesine eklenir; çalıştırma `ctest -C Debug -R sahne` (build dizini: `build/` VS ağacı derleme-doğrulama; kullanıcı `insa/Release` çalıştırır — bkz. proje hafızası).
- Commit mesajı sonu: `Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`. Commit YALNIZ kullanıcı onayıyla — plan adımlarında `git add` hazırla, commit'i kullanıcı tetikler (proje kuralı: otomatik commit yok). *(Executor: commit adımlarını çalıştırmadan önce kullanıcı onayı iste.)*

---

## Dosya Yapısı

- **Create** `motor/sahne/include/fiko/sahne/oge_ozellik.hpp` — `OgeOzellik` struct + enum'lar + `ImzaVeri` + saf çözüm yardımcıları. Vulkan/OCCT bağımsız (kolay test).
- **Modify** `motor/sahne/include/fiko/sahne/sahne.hpp` — `Dugum`'a 3 harita + 3 varsayılan + çözüm API (`yuzOzellik`/`kenarOzellik`/`noktaOzellik`); `DugumPusula`'ya aynı alanlar.
- **Modify** `motor/sahne/src/sahne.cpp` — `pusula()` (Dugum→DugumPusula) ve `diril()` (DugumPusula→Dugum) haritaları kopyalar.
- **Modify** `motor/geometri/src/brep_io.cpp` veya STEP import yolu — `yuzRenkleri` → `yuzOz[i].renk` köprüsü (import edilen düğüme uygulanır). *(Executor: STEP renk uygulama noktasını `HazirDugum`/`sahne_kur` akışında bul; `yuzRenkleri` `brep_ic.hpp`'de.)*
- **Create** `motor/sahne/test/test_oge_ozellik.cpp` — çözüm + undo round-trip testleri.
- **Modify** `motor/sahne/CMakeLists.txt` — test dosyasını ekle.

---

### Task 1: `OgeOzellik` veri modeli + saf çözüm

**Files:**
- Create: `motor/sahne/include/fiko/sahne/oge_ozellik.hpp`
- Create: `motor/sahne/test/test_oge_ozellik.cpp`
- Modify: `motor/sahne/CMakeLists.txt` (add_executable listesine `test/test_oge_ozellik.cpp`)

**Interfaces:**
- Produces: `struct OgeOzellik`, `enum class KenarStil`, `enum class NoktaSekil`, `struct ImzaVeri`, `enum class OgeTip { Yuz, Kenar, Nokta }`, ve `OgeOzellik ogeVarsayilan(OgeTip)`.

- [ ] **Step 1: Başarısız test yaz** (`test_oge_ozellik.cpp`)

```cpp
#include "fiko/sahne/oge_ozellik.hpp"
#include "fiko_test.hpp"
using namespace fiko;

FIKO_TEST(oge_varsayilan_tip_bazli) {
  const OgeOzellik yuz = ogeVarsayilan(OgeTip::Yuz);
  const OgeOzellik kenar = ogeVarsayilan(OgeTip::Kenar);
  const OgeOzellik nokta = ogeVarsayilan(OgeTip::Nokta);
  FIKO_ESIT(yuz.alfa, 1.0f);
  FIKO_DOGRU(yuz.gorunur);
  FIKO_ESIT(kenar.stil, KenarStil::Duz);
  FIKO_DOGRU(kenar.kalinlik > 0.0f);
  FIKO_ESIT(nokta.sekil, NoktaSekil::Nokta);
  FIKO_DOGRU(nokta.noktaBoyut > 0.0f);
  // Kenar varsayılanı yüzden koyu (görsel ayrım).
  FIKO_DOGRU(kenar.renk.x < yuz.renk.x || kenar.renk.y < yuz.renk.y);
}
```
*(Executor: `fiko_test.hpp`'deki gerçek makro adlarını kullan — `FIKO_TEST`/assert makroları; `FIKO_ESIT`/`FIKO_DOGRU` yoksa dosyadaki muadilini kopyala.)*

- [ ] **Step 2: Testi çalıştır, başarısız olduğunu gör**

Run: `cmake --build insa/Debug --target fiko_sahne_test` (veya `build/` VS) → derleme HATASI: `oge_ozellik.hpp` yok.
Expected: FAIL (dosya/tip yok).

- [ ] **Step 3: `oge_ozellik.hpp` yaz (minimal)**

```cpp
#pragma once
#include "fiko/core/mat/vec.hpp"
#include "fiko/core/temel.hpp"

namespace fiko {

enum class OgeTip : u8 { Yuz, Kenar, Nokta };
enum class KenarStil : u8 { Duz, Dash, Dot, DashDot };
enum class NoktaSekil : u8 { Nokta, Kare, Arti };

// Proje 2 (topo-naming) eşleme anahtarı — öğe tipine göre anlamlı alanlar.
struct ImzaVeri {
  Vec3f konum{};   // yüz merkez / kenar orta / nokta konum (yerel uzay)
  Vec3f yon{};     // yüz normal / kenar yön (nokta: 0)
  f32   olcu = 0;  // yüz alan / kenar uzunluk (nokta: 0)
  u8    altTip = 0;// yüzey/eğri tipi (düzlem/silindir/doğru/çember...) — opsiyonel
};

struct OgeOzellik {
  Vec3f renk{0.72f, 0.74f, 0.78f};
  f32   alfa = 1.0f;
  bool  gorunur = true;
  // Kenar
  KenarStil stil = KenarStil::Duz;
  f32   kalinlik = 1.6f;
  // Nokta
  f32   noktaBoyut = 7.0f;
  NoktaSekil sekil = NoktaSekil::Nokta;
  // Yüz basit malzeme
  f32   metalik = 0.0f;
  f32   puruz = 0.6f;
  // Topo-naming kancası (Proje 2)
  ImzaVeri imza{};
};

// Öğe tipine göre görsel varsayılan (kenar koyu, nokta belirgin).
inline OgeOzellik ogeVarsayilan(OgeTip tip) {
  OgeOzellik o;
  switch (tip) {
    case OgeTip::Kenar: o.renk = {0.05f, 0.06f, 0.09f}; o.kalinlik = 1.6f; break;
    case OgeTip::Nokta: o.renk = {0.95f, 0.85f, 0.20f}; o.noktaBoyut = 7.0f; break;
    case OgeTip::Yuz:   o.renk = {0.72f, 0.74f, 0.78f}; break;
  }
  return o;
}

}  // namespace fiko
```

- [ ] **Step 4: `CMakeLists.txt`'e test ekle + çalıştır → geçer**

`motor/sahne/CMakeLists.txt` add_executable(fiko_sahne_test ...) listesine `test/test_oge_ozellik.cpp` satırını ekle.
Run: `cmake --build build --target fiko_sahne_test --config Debug && ctest --test-dir build -C Debug -R sahne -V`
Expected: PASS (`oge_varsayilan_tip_bazli`).

- [ ] **Step 5: Commit (kullanıcı onayıyla)**

```bash
git add motor/sahne/include/fiko/sahne/oge_ozellik.hpp motor/sahne/test/test_oge_ozellik.cpp motor/sahne/CMakeLists.txt
git commit -m "feat(ozellik): OgeOzellik veri modeli + tip-bazlı varsayılan"
```

---

### Task 2: `Dugum` özellik deposu + çözüm API

**Files:**
- Modify: `motor/sahne/include/fiko/sahne/sahne.hpp` (Dugum'a alanlar + metodlar)
- Modify: `motor/sahne/test/test_oge_ozellik.cpp` (yeni test)

**Interfaces:**
- Consumes: `OgeOzellik`, `OgeTip`, `ogeVarsayilan` (Task 1).
- Produces: `Dugum` üyeleri `std::unordered_map<u32,OgeOzellik> yuzOz, kenarOz, noktaOz;` + `OgeOzellik yuzVars, kenarVars, noktaVars;` ve metodlar:
  - `OgeOzellik& yuzOzellikYaz(u32 ord)` — override oluştur/al (yoksa yuzVars'tan kopya).
  - `OgeOzellik yuzOzellik(u32 ord) const` — çözüm (override → yuzVars).
  - Aynısı `kenar*` / `nokta*`.

- [ ] **Step 1: Başarısız test yaz** (test_oge_ozellik.cpp'e ekle)

```cpp
#include "fiko/sahne/sahne.hpp"

FIKO_TEST(dugum_ozellik_cozum) {
  Dugum d;
  // Override yok → gövde varsayılanı (yüz).
  const OgeOzellik c0 = d.yuzOzellik(3);
  FIKO_ESIT(c0.renk.x, ogeVarsayilan(OgeTip::Yuz).renk.x);
  // Yüz 3'e kırmızı ata → çözümde kırmızı döner, yüz 5 hâlâ varsayılan.
  d.yuzOzellikYaz(3).renk = {1.0f, 0.0f, 0.0f};
  FIKO_ESIT(d.yuzOzellik(3).renk.x, 1.0f);
  FIKO_ESIT(d.yuzOzellik(5).renk.x, ogeVarsayilan(OgeTip::Yuz).renk.x);
  // Gövde varsayılanı değişince override'sız öğeler etkilenir.
  d.yuzVars.alfa = 0.5f;
  FIKO_ESIT(d.yuzOzellik(5).alfa, 0.5f);
  FIKO_ESIT(d.yuzOzellik(3).alfa, 1.0f);  // override alfa'sı korunur
}
```

- [ ] **Step 2: Çalıştır → FAIL** (`yuzOzellik`/`yuzOzellikYaz` yok).

Run: `cmake --build build --target fiko_sahne_test --config Debug`
Expected: FAIL (derleme: metod yok).

- [ ] **Step 3: `sahne.hpp` Dugum'a ekle**

`Dugum` struct'ına (mevcut `cpuKenar`/`yerelSinir` yakınına), `#include "fiko/sahne/oge_ozellik.hpp"` sahne.hpp başına:

```cpp
  // ---- Öğe görsel özellikleri (yüz/kenar/nokta) — seyrek override + gövde varsayılanı ----
  std::unordered_map<u32, OgeOzellik> yuzOz, kenarOz, noktaOz;
  OgeOzellik yuzVars = ogeVarsayilan(OgeTip::Yuz);
  OgeOzellik kenarVars = ogeVarsayilan(OgeTip::Kenar);
  OgeOzellik noktaVars = ogeVarsayilan(OgeTip::Nokta);

  OgeOzellik& yuzOzellikYaz(u32 ord) {
    auto it = yuzOz.find(ord);
    if (it == yuzOz.end()) it = yuzOz.emplace(ord, yuzVars).first;
    return it->second;
  }
  OgeOzellik yuzOzellik(u32 ord) const {
    const auto it = yuzOz.find(ord);
    return it != yuzOz.end() ? it->second : yuzVars;
  }
  OgeOzellik& kenarOzellikYaz(u32 ord) {
    auto it = kenarOz.find(ord);
    if (it == kenarOz.end()) it = kenarOz.emplace(ord, kenarVars).first;
    return it->second;
  }
  OgeOzellik kenarOzellik(u32 ord) const {
    const auto it = kenarOz.find(ord);
    return it != kenarOz.end() ? it->second : kenarVars;
  }
  OgeOzellik& noktaOzellikYaz(u32 ord) {
    auto it = noktaOz.find(ord);
    if (it == noktaOz.end()) it = noktaOz.emplace(ord, noktaVars).first;
    return it->second;
  }
  OgeOzellik noktaOzellik(u32 ord) const {
    const auto it = noktaOz.find(ord);
    return it != noktaOz.end() ? it->second : noktaVars;
  }
```
*(Executor: `<unordered_map>` sahne.hpp'de var mı kontrol et; yoksa ekle.)*

- [ ] **Step 4: Çalıştır → PASS**

Run: `cmake --build build --target fiko_sahne_test --config Debug && ctest --test-dir build -C Debug -R sahne -V`
Expected: PASS (`dugum_ozellik_cozum`).

- [ ] **Step 5: Commit (onayla)**

```bash
git add motor/sahne/include/fiko/sahne/sahne.hpp motor/sahne/test/test_oge_ozellik.cpp
git commit -m "feat(ozellik): Dugum per-oge ozellik deposu + cozum API"
```

---

### Task 3: Undo/redo kalıcılığı (`DugumPusula`)

**Files:**
- Modify: `motor/sahne/include/fiko/sahne/sahne.hpp` (`DugumPusula` alanları)
- Modify: `motor/sahne/src/sahne.cpp` (`pusula()` + `diril()` kopyalama)
- Modify: `motor/sahne/test/test_oge_ozellik.cpp` (round-trip testi)

**Interfaces:**
- Consumes: Task 2 Dugum alanları; mevcut `Sahne::pusula(kimlik)->DugumPusula` ve `Sahne::diril(const DugumPusula&)` (isimleri koddan doğrula — `sahne.cpp`).
- Produces: `DugumPusula` içine `yuzOz/kenarOz/noktaOz/yuzVars/kenarVars/noktaVars` alanları; pusula/diril bunları taşır.

- [ ] **Step 1: Başarısız test yaz**

```cpp
FIKO_TEST(ozellik_undo_roundtrip) {
  Dunya dunya;
  Sahne sahne(dunya /*, gerekli ctor argümanları — koddan doğrula*/);
  const Varlik k = /* sahneye bir Dugum ekle — test_agac_zengin dugumEkle kalıbı */;
  Dugum* d = sahne.bul(k);
  d->yuzOzellikYaz(2).renk = {0.1f, 0.9f, 0.2f};
  // Pusula al (undo snapshot) → özelliği değiştir → dirilt → geri gelir.
  const DugumPusula p = sahne.pusula(k);
  d->yuzOz.clear();  // "başka işlem" simülasyonu (renk kaybı)
  FIKO_ESIT(d->yuzOzellik(2).renk.y, ogeVarsayilan(OgeTip::Yuz).renk.y);  // kayıp
  sahne.diril(p);    // undo
  FIKO_ESIT(sahne.bul(k)->yuzOzellik(2).renk.y, 0.9f);  // geri geldi
}
```
*(Executor: `Sahne` ctor + `pusula`/`diril` gerçek imzalarını `sahne.hpp`/`sahne.cpp`'den al; test_agac_zengin.cpp Dunya/Dugum kurulum kalıbını kopyala. Vulkan gerektiren yol varsa mesh'siz düğüm kullan.)*

- [ ] **Step 2: Çalıştır → FAIL** (DugumPusula özellik taşımıyor → diril sonrası renk kayıp).

- [ ] **Step 3: `DugumPusula` + pusula/diril genişlet**

`sahne.hpp` `DugumPusula` struct'ına ekle:
```cpp
  std::unordered_map<u32, OgeOzellik> yuzOz, kenarOz, noktaOz;
  OgeOzellik yuzVars, kenarVars, noktaVars;
```
`sahne.cpp` `pusula()` içinde (Dugum→DugumPusula): `p.yuzOz = d.yuzOz; p.kenarOz = d.kenarOz; p.noktaOz = d.noktaOz; p.yuzVars = d.yuzVars; ...`
`diril()` içinde (DugumPusula→Dugum): tersi. *(Executor: pusula/diril'in Dugum alanlarını kopyaladığı yeri bul, bu 6 alanı ekle.)*

- [ ] **Step 4: Çalıştır → PASS**

Expected: PASS (`ozellik_undo_roundtrip`).

- [ ] **Step 5: Commit (onayla)**

```bash
git add motor/sahne/include/fiko/sahne/sahne.hpp motor/sahne/src/sahne.cpp motor/sahne/test/test_oge_ozellik.cpp
git commit -m "feat(ozellik): undo/redo kaliciligi — DugumPusula oge ozellikleri"
```

---

### Task 4: STEP renk köprüsü (`yuzRenkleri` → `yuzOz`)

**Files:**
- Modify: STEP import → sahne düğüm kurulum yolu (`motor/io/src/sahne_kur.cpp` veya import'un `Dugum` doldurduğu yer)
- Modify: `motor/sahne/test/test_oge_ozellik.cpp` (köprü testi)

**Interfaces:**
- Consumes: mevcut `yuzRenkleri` (BrepGovde `Icerik`, `brep_ic.hpp`) + Task 2 `yuzOzellikYaz`.
- Produces: import edilen düğümün `yuzOz[i].renk` = `yuzRenkleri[i-1]` (1-tabanlı ordinal).

- [ ] **Step 1: Başarısız test yaz** — bir BrepGovde'ye yüz renkleri ata, düğüme köprüle, `yuzOzellik(i)` renk döner.

```cpp
FIKO_TEST(step_yuz_renk_kopru) {
  Dugum d;
  // brep + yuzRenkleri kur (test_brep kalıbı) → köprü fonksiyonunu çağır.
  // ogeOzellikBrepYuzRenkUygula(d, brep);  // Task 4 ürünü
  // FIKO_ESIT(d.yuzOzellik(1).renk.x, atanan.x);
}
```
*(Executor: köprüyü ya serbest fonksiyon `void ogeOzellikBrepYuzRenkUygula(Dugum&, const geometri::BrepGovde&)` yap ya import akışında inline. `yuzRenkleri` erişimi için brep API'sini kullan — `brep_ic.hpp` private ise brep.hpp'ye getter ekle.)*

- [ ] **Step 2: Çalıştır → FAIL.**

- [ ] **Step 3: Köprüyü yaz** — import'ta (veya serbest fonksiyon), her yüz için `if renk varsa d.yuzOzellikYaz(i).renk = yuzRenkleri[i-1];`. Böylece STEP renkleri artık `yuzOz`'da (undo + dosya'da korunur).

- [ ] **Step 4: Çalıştır → PASS.**

- [ ] **Step 5: Commit (onayla)**

```bash
git add -A
git commit -m "feat(ozellik): STEP yuz renkleri -> yuzOz kopru (kalici)"
```

---

## Self-Review Notları

- **Spec kapsamı (Dalga 1):** veri modeli (Task 1-2) ✓, undo (Task 3) ✓, STEP köprü (Task 4) ✓. Render/UI/dosya/olay → sonraki dalgalar (ayrı plan).
- **Placeholder:** Test iskeletlerinde `*(Executor: ...)*` notları gerçek imza-doğrulama gerektirir (Sahne ctor, pusula/diril, yuzRenkleri erişimi kod-bağımlı) — literal kod yerine yönlendirme, çünkü bu imzalar koddan okunmalı. Executor ilk adımda bunları doğrular.
- **Tip tutarlılığı:** `yuzOzellik`/`yuzOzellikYaz`/`OgeOzellik`/`OgeTip`/`ogeVarsayilan` tüm task'larda aynı.
- **Risk:** `Sahne` ctor Vulkan gerektiriyorsa test mesh'siz düğüm + minimal Sahne kullanmalı (test_agac_zengin Dunya-only kalıbına bak — Sahne yerine doğrudan Dunya/Dugum ile test daha güvenli; pusula/diril Dunya seviyesindeyse oradan test et).

## Sonraki dalgalar (ayrı planlar)
Dalga 2 (yüz render: Vertex alpha + renk/görünürlük pişirme), Dalga 3 (kenar: renk + dash shader + kalınlık kova), Dalga 4 (nokta shader), Dalga 5 (Özellikler paneli UI), Dalga 6 (.fikocad serileştirme + `OgeOzellikDegisti` olay + `fiko.ozellik` Lua).
