# Kreator skryptu generowania projektu graficznego Tworzysz nowy skrypt Python do generowania projektow graficznych z szablonu PSD. Skrypt bedzie uzywal Photoshop API (photoshop-python-api) do podmiany tekstow w Smart Objects z zachowaniem pozycji warstw. ## Wymagania - Photoshop musi byc uruchomiony — sprawdz: `tasklist //FI "IMAGENAME eq Photoshop.exe" 2>/dev/null | grep -i photoshop` - Python z pakietem `photoshop-python-api` musi byc zainstalowany ## Przepływ ### 1. Pobierz sciezke do PSD Uzytkownik poda sciezke do pliku PSD szablonu. Zweryfikuj ze plik istnieje. ### 2. Eksploruj strukture warstw Otworz PSD w Photoshopie przez Python i rekurencyjnie przejdz wszystkie warstwy: ```python import photoshop.api as ps app = ps.Application() doc = app.open(PSD_PATH) def explore(container, indent=0): try: for al in container.artLayers: extra = '' try: extra = f' text="{al.textItem.contents}"' except: pass print(f'{" "*indent}art: "{al.name}" kind={al.kind}{extra}') except: pass try: for ls in container.layerSets: print(f'{" "*indent}set: "{ls.name}"') explore(ls, indent+1) except: pass explore(doc) ``` Jezeli warstwa jest Smart Objectem (kind=5 lub 7) — wejdz do niego: ```python app.activeDocument.activeLayer = smart_layer desc = ps.ActionDescriptor() ref = ps.ActionReference() ref.putEnumerated(app.stringIDToTypeID('layer'), app.stringIDToTypeID('ordinal'), app.stringIDToTypeID('targetEnum')) desc.putReference(app.stringIDToTypeID('null'), ref) app.executeAction(app.stringIDToTypeID('placedLayerEditContents'), desc) ``` Eksploruj zawartosc Smart Object rekurencyjnie (moze byc wiele poziomow zagniezdzenia). ### 3. Wyswietl drzewo warstw Pokaz uzytkownikowi pelna strukture warstw w czytelnym formacie drzewa, np.: ``` Projekt (Smart Object) └── Dekoracje (set) └── Tekst (set) └── Dane (set) ├── "imie" kind=2 text="Jan" ├── "data" kind=2 text="01.01.2026" └── "zyczenia" kind=2 text="Wszystkiego najlepszego" ``` kind=2 to warstwy tekstowe — te sa kandydatami na zmienne. ### 4. Ustal zmienne Zapytaj uzytkownika: - Ktore warstwy tekstowe maja byc parametrami skryptu? - Jakie nazwy parametrow CLI? (np. --imie, --data, --zyczenia) - Ktore parametry sa wymagane, ktore opcjonalne (opcjonalne = zostaw domyslny tekst z szablonu)? ### 5. Uproszczenie warstw (opcjonalnie) Zaproponuj uproszczenie nazw warstw w PSD: - Przemianuj warstwy na czytelne nazwy (np. "Warstwa 5" -> "Tekst", "Kasia" -> "imie_zenskie") - Przemianuj grupy (np. "Warstwa 4" -> "Dane") - Zapytaj uzytkownika o akceptacje Jezeli uzytkownik zaakceptuje — wykonaj rename warstw w PSD i zapisz szablon. ### 6. Ustal sciezki Zapytaj uzytkownika: - Nazwa skryptu (np. `kubki_wzor1.py`) - Katalog wyjsciowy `_gotowe/` — domyslnie podfolder `_gotowe` w katalogu szablonu PSD - Nazwa Smart Object glownego (jezeli PSD ma wiele — ktory jest szablonem) ### 7. Wygeneruj skrypt Uzyj wzorca z `tools/generowanie/buteleczki_wzor1.py` jako referencji. Kluczowe elementy: ```python import argparse import os import photoshop.api as ps # Sciezki SZABLON_PATH = r"..." GOTOWE_DIR = r"..." SMART_OBJECT_LAYER = "Projekt" def open_smart_object(app): desc = ps.ActionDescriptor() ref = ps.ActionReference() ref.putEnumerated(app.stringIDToTypeID('layer'), app.stringIDToTypeID('ordinal'), app.stringIDToTypeID('targetEnum')) desc.putReference(app.stringIDToTypeID('null'), ref) app.executeAction(app.stringIDToTypeID('placedLayerEditContents'), desc) def change_text_preserve_position(layer, new_text): """Zmienia tekst warstwy z zachowaniem oryginalnej pozycji.""" bounds_before = [float(b) for b in layer.bounds] layer.textItem.contents = new_text bounds_after = [float(b) for b in layer.bounds] dx = bounds_before[0] - bounds_after[0] dy = bounds_before[1] - bounds_after[1] if dx != 0 or dy != 0: layer.translate(dx, dy) def generate(**kwargs): # ... otworz PSD, wejdz do SO, podmien teksty, zapisz kopie pass def main(): parser = argparse.ArgumentParser(...) # ... argumenty na podstawie ustalonych zmiennych args = parser.parse_args() generate(...) if __name__ == "__main__": main() ``` Wazne: - **Zawsze** uzywaj `change_text_preserve_position()` zamiast bezposredniego `textItem.contents` - Nawigacja do warstw przez `layerSets['nazwa'].artLayers['nazwa']` - Po edycji Smart Object: `so_doc.save()` + `so_doc.close()` - Zapisz jako kopie: `app.activeDocument.saveAs(output_path, psd_opts, True)` - Zamknij oryginal bez zapisu: `app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges)` - Parametr `--klient` zawsze wymagany (nazwa pliku wyjsciowego) ### 8. Przetestuj Po wygenerowaniu skryptu: 1. Uruchom go z przykladowymi danymi 2. Sprawdz czy PSD zostal wygenerowany 3. Popros uzytkownika o weryfikacje wizualna ### 9. Dodaj mapowanie Zaproponuj uzytkownikowi dodanie mapowania w panelu (Ustawienia > Mapowanie projektow) — wzorzec nazwy produktu -> nowy skrypt. ## Wazne zasady - Zamykaj PSD po zakonczeniu (nie zostawiaj otwartych dokumentow) - Przy bledzie — zamknij wszystkie otwarte dokumenty bez zapisu - Skrypty zapisuj w `tools/generowanie/` w katalogu projektu orderPRO - Testuj z realnymi danymi przed zakonczeniem