11 KiB
PSD Grup Katmanı Düzeltme Planı
Commit aşaması tamamlandı (commit
5f62c84). Bu plan sadece PSD grup katmanı fix’ini 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 validation’da 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-204aralığında,Tool::allowed_layer_type() == Some(Raster)olduğunda aktif katman farklı tipte ise yeni bir layer otomatik oluşturuluyor.- PSD’den gelen grup katmanı
LayerType::Groupolarak işaretlenmiş olmasına rağmen, bu kod yine deadd_layer("Layer")çağrısı yapıyor ve normal bir raster layer oluşturuyor.
Doğru Davranış
- Aktif katman
LayerType::Groupise:- 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 Crate’ler
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 |
LayerInfo’ya 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-apiaçılmalı. - Tüm GUI değişiklikleri zaten açık olan
hcie-egui-app/crates/hcie-gui-eguiiç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.rsiçine ekle,lib.rs’den public olarak re-export et.- Veya doğrudan
hcie-engine-api/src/lib.rsiçine ekle.
Tavsiye: Yeni fonksiyonları
layer_property_ops.rsiçine ekle velib.rs’depub useveya doğrudanimpl Enginebloğ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 branch’lerinde ek kontrol
Tool::Pen | Tool::Brush | Tool::Eraser | Tool::Spray ve Tool::FloodFill branch’lerinin 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 enum’una ş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
HcieAppstruct’ınastatus_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
- Derleme:
cargo check -p hcie-engine-api cargo check -p hcie-gui-egui - Golden regression:
cargo test -p hcie-engine-api --test visual_regression - 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 bar’da "Layer not editable" görünüyor.
6. Riskler ve Dikkat Edilecekler
- Kilitli crate: Sadece
hcie-engine-apiaçılacak.unlock.sh hcie-engine-apiile aç, değişiklikten sonralock.sh hcie-engine-apiile 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ğigui_audit.rstestini 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
lockedveMaskkatmanları için de kullanılabilir. İlk aşamadaGroupodaklı tutulması önerilir.
7. Kısa Özet
- Commit tamam; şimdi sadece PSD grup katmanı fix’i yapılacak.
hcie-engine-apikilidini aç,is_layer_editableveactive_layer_is_editableekle.hcie-egui-app/crates/hcie-gui-eguiiç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 bar’da 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.