Files
hcie-rust-v3.05/.kilo/plans/commit-and-psd-group-layer-fix.md
T
2026-07-09 02:59:53 +03:00

11 KiB
Raw Blame History

PSD Grup Katmanı Düzeltme Planı

Commit aşaması tamamlandı (commit 5f62c84). Bu plan sadece PSD grup katmanı fixini içerir.

0. Kapanmış Uyarılar / Öğrenilenler (Commit Sonrası)

Aşağıdaki uyarılar commit öncesi değerlendirmede geçerliydi, ancak commit sonrası gerçekleşenlerle artık geçerli değil veya durumu netleşmiştir.

0.1 visual_regression.rs zaten vardı

Planda "visual regression harness henüz yok, oluşturulmalı veya atlanmalı" notu bulunuyordu. Ancak çalışma ağacında hcie-engine-api/tests/visual_regression.rs zaten mevcuttu ve çalışıyordu. Commit öncesi validationda 7 golden testin tamamı geçti. Dolayısıyla o uyarı artık geçerli değil.

0.2 İlk composite süresi ~340 ms — beklenen davranış

4K, 10 katmanlı benchmark testinde ilk composite en kötü ~340 ms ölçüldü. Bu, tasarımın doğal bir yan etkisi:

  • İlk karede alt katmanların tamamı below_cache önbelleğe bir kez dizilir.
  • Sonraki karelerde sadece aktif katman üzerine composite yapılır; süre katman sayısıyla orantılı düşer.
  • Yani ilk vuruş ağır, sürekli boyama hızlanır.

Bu nedenle performans testi "non-gating" olarak tasarlanmıştır; tek seferlik ilk frame süresi regresyon olarak değerlendirilmemeli.

1. Hedefler

  • PSD import sonrası grup katmanlarının doğru şekilde davranmasını sağlamak:
    • Layers panelinde klasör simgesi / farklı görsel ile gösterilmeli.
    • Grup katmanı seçiliyken, fırça/kalem/eraser gibi raster araçlarla çizim yapılmaya çalışıldığında yeni layer oluşturulmamalı.
    • Bunun yerine kullanıcıya "Layer not editable" mesajı gösterilmeli.

2. Mevcut Durum Analizi

Yanlış Davranış

  • hcie-egui-app/crates/hcie-gui-egui/src/canvas/mod.rs:183-204 aralığında, Tool::allowed_layer_type() == Some(Raster) olduğunda aktif katman farklı tipte ise yeni bir layer otomatik oluşturuluyor.
  • PSDden gelen grup katmanı LayerType::Group olarak işaretlenmiş olmasına rağmen, bu kod yine de add_layer("Layer") çağrısı yapıyor ve normal bir raster layer oluşturuyor.

Doğru Davranış

  • Aktif katman LayerType::Group ise:
    • Raster araçlarla (Pen, Brush, Eraser, Spray, FloodFill, vb.) çizim yapılamaz.
    • Yeni layer oluşturulmaz.
    • Kullanıcıya "Layer not editable" mesajı gösterilir.
  • Layers panelinde grup satırı görsel olarak farklılaştırılır (thumbnail yerine klasör ikonu, farklı arka plan rengi, vb.).

3. Kilit Açılması Gereken Crateler

AGENTS.md kurallarına göre aşağıdaki dosyalar locked. Değişiklik yapmadan önce unlock.sh <crate> ile açılmalı, sonra lock.sh <crate> ile kapatılmalı.

Crate / Dosya Neden Açılması Gerekiyor Gerekli mi?
hcie-engine-api/src/lib.rs Yeni public sorgu fonksiyonları (is_layer_editable, active_layer_is_editable) eklemek için. Evet
hcie-engine-api/src/layer_property_ops.rs Aynı sorgu fonksiyonlarını burada da implemente edebiliriz; lib.rs re-export eder. Opsiyonel
hcie-protocol/src/lib.rs LayerInfoya editable veya is_group alanı eklemek istersek. Zaten layer_type var, muhtemelen gerek yok. Hayır (önerilmez)
hcie-document/src/lib.rs LayerInfo oluşturma mantığı. layer_type zaten var, muhtemelen gerek yok. Hayır (önerilmez)
hcie-composite/src/tiled.rs Grup katmanları zaten atlanıyor; değişiklik beklenmiyor. Hayır
hcie-psd/src/psd_import.rs LayerType::Group atanması zaten doğru; inceleme gerekirse açılabilir. Muhtemelen hayır

Minimal kilitli crate seti

  • Sadece hcie-engine-api açılmalı.
  • Tüm GUI değişiklikleri zaten açık olan hcie-egui-app/crates/hcie-gui-egui içinde yapılacak.

4. Uygulama Adımları

Phase 1: Engine API — Editable Sorgu Fonksiyonları

Kilitli crate: hcie-engine-api

Yeni public API ekleyin:

impl Engine {
    /// Returns whether the layer with the given ID can receive pixel edits.
    /// Group and Mask layers are not editable. Locked layers are not editable.
    pub fn is_layer_editable(&self, id: u64) -> bool {
        let Some(layer) = self.document.get_layer_by_id(id) else { return false };
        if layer.locked { return false; }
        !matches!(layer.layer_type, LayerType::Group | LayerType::Mask)
    }

    /// Returns whether the currently active layer can receive pixel edits.
    pub fn active_layer_is_editable(&self) -> bool {
        self.document.active_layer()
            .map(|l| self.is_layer_editable(l.id))
            .unwrap_or(false)
    }
}

Eklenebilecek dosyalar:

  • hcie-engine-api/src/layer_property_ops.rs içine ekle, lib.rsden public olarak re-export et.
  • Veya doğrudan hcie-engine-api/src/lib.rs içine ekle.

Tavsiye: Yeni fonksiyonları layer_property_ops.rs içine ekle ve lib.rsde pub use veya doğrudan impl Engine bloğu içinde re-export yap. Bu, mevcut refactor stiliyle uyumlu olur.

Phase 2: GUI — Canvas Çizim Engeli

Açık crate: hcie-egui-app/crates/hcie-gui-egui

Dosya: hcie-egui-app/crates/hcie-gui-egui/src/canvas/mod.rs

2a. Otomatik layer oluşturma bloğunu düzenle

Mevcut kod (satır ~183-204):

if primary_pressed && !self.state.is_drawing {
    if let Some(req_type) = self.state.active_tool.allowed_layer_type() {
        if let Some(active) = self.doc.engine.active_layer() {
            if active.layer_type != req_type {
                match req_type {
                    hcie_engine_api::LayerType::Vector => { ... }
                    hcie_engine_api::LayerType::Text => { ... }
                    _ => {
                        let id = self.doc.engine.add_layer("Layer");
                        self.doc.engine.set_active_layer(id);
                    }
                }
                self.event_bus.push(AppEvent::RenderRequested);
            }
        }
    }
}

Düzenleme:

if primary_pressed && !self.state.is_drawing {
    if let Some(req_type) = self.state.active_tool.allowed_layer_type() {
        if let Some(active) = self.doc.engine.active_layer() {
            if !self.doc.engine.active_layer_is_editable() {
                self.event_bus.push(AppEvent::ShowStatusMessage(
                    "Layer not editable".to_string()
                ));
                // consume the press so we don't fall through to drawing
                return response;
            }
            if active.layer_type != req_type {
                // Only auto-create a layer when the active layer is editable
                // but of a different type (e.g. vector/text needed).
                match req_type {
                    hcie_engine_api::LayerType::Vector => { ... }
                    hcie_engine_api::LayerType::Text => { ... }
                    _ => {
                        let id = self.doc.engine.add_layer("Layer");
                        self.doc.engine.set_active_layer(id);
                    }
                }
                self.event_bus.push(AppEvent::RenderRequested);
            }
        }
    }
}

2b. Raster çizim branchlerinde ek kontrol

Tool::Pen | Tool::Brush | Tool::Eraser | Tool::Spray ve Tool::FloodFill branchlerinin başına editable kontrolü ekle:

if !self.doc.engine.active_layer_is_editable() {
    self.event_bus.push(AppEvent::ShowStatusMessage(
        "Layer not editable".to_string()
    ));
    return response;
}

Phase 3: GUI — Status Mesajı Event Bus

Açık crate: hcie-egui-app/crates/hcie-gui-egui

Dosya: hcie-egui-app/crates/hcie-gui-egui/src/event_bus.rs

AppEvent enumuna şu variant’ı ekle (eğer yoksa):

pub enum AppEvent {
    // ... existing variants
    ShowStatusMessage(String),
}

Phase 4: GUI — Status Bar Mesaj Gösterimi

Açık crate: hcie-egui-app/crates/hcie-gui-egui

Dosya: hcie-egui-app/crates/hcie-gui-egui/src/app/mod.rs

  • HcieApp struct’ına status_message: Option<(String, Instant)> gibi bir alan ekle.
  • Event loop içinde AppEvent::ShowStatusMessage(text) yakalayıp bu alana yaz.
  • UI çiziminde (örneğin bottom panel / status bar) mesajı göster ve belirli bir süre (örn. 2 saniye) sonra temizle.
  • Eğer zaten bir status bar alanı varsa onu kullan.

Phase 5: GUI — Layers Panelde Grup Görseli

Açık crate: hcie-egui-app/crates/hcie-gui-egui

Dosya: hcie-egui-app/crates/hcie-gui-egui/src/app/panels.rs

show_layers fonksiyonunda:

  • Grup satırının thumbnail alanında klasör ikonu çiz:
    if entry.is_group {
        // Draw a folder icon in the thumbnail rect
        let p = ui.painter();
        p.text(thumb_rect.center(), egui::Align2::CENTER_CENTER, "📁",
               egui::FontId::proportional(16.0), colors.text_primary);
    } else if let Some(tex) = doc.layer_textures.get(&i) {
        // existing texture draw
    }
    
  • (Opsiyonel) Grup satırına hafif farklı arka plan rengi:
    let bg = if is_active {
        colors.accent.gamma_multiply(0.2)
    } else if entry.is_group {
        colors.bg_secondary.gamma_multiply(0.5)
    } else {
        egui::Color32::TRANSPARENT
    };
    

5. Validation Plan

  1. Derleme:
    cargo check -p hcie-engine-api
    cargo check -p hcie-gui-egui
    
  2. Golden regression:
    cargo test -p hcie-engine-api --test visual_regression
    
  3. Manuel senaryo:
    • PSD dosyası içeri aktar.
    • Layers panelinde grup katmanının klasör ikonu ile gösterildiğini doğrula.
    • Grup katmanını seç.
    • Brush/Pen/Eraser ile tuvale tıkla.
    • Beklenen: yeni layer oluşmuyor, status barda "Layer not editable" görünüyor.

6. Riskler ve Dikkat Edilecekler

  • Kilitli crate: Sadece hcie-engine-api açılacak. unlock.sh hcie-engine-api ile aç, değişiklikten sonra lock.sh hcie-engine-api ile kapat.
  • Public API değişikliği minimal: sadece yeni sorgu fonksiyonları ekle, mevcut imzaları değiştirme.
  • Performans korumalarına dokunma: Yeni fonksiyonlar allocation/composite yapmamalı.
  • Tool::allowed_layer_type() değişikliği gui_audit.rs testini etkileyebilir; eğer değiştirirsen testi güncelle. Önerilen: bu fonksiyona dokunmadan canvas/mod.rs içinde ek kontrol yap.
  • Genelleştirme: "Layer not editable" mesajı ileride locked ve Mask katmanları için de kullanılabilir. İlk aşamada Group odaklı tutulması önerilir.

7. Kısa Özet

  • Commit tamam; şimdi sadece PSD grup katmanı fixi yapılacak.
  • hcie-engine-api kilidini aç, is_layer_editable ve active_layer_is_editable ekle.
  • hcie-egui-app/crates/hcie-gui-egui içinde:
    • canvas/mod.rs: grup seçiliyken yeni layer oluşturmayı engelle, status mesajı gönder.
    • event_bus.rs: ShowStatusMessage(String) ekle.
    • app/mod.rs: status barda mesajı göster.
    • app/panels.rs: grup satırına klasör ikonu / farklı arka plan.
  • Validation ile golden testleri ve manuel senaryoyu çalıştır.