163 lines
5.3 KiB
Markdown
163 lines
5.3 KiB
Markdown
# 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
|