""" Generator PSD - Magnes podziekowanie na chrzest UV - Stopki serce. Makieta A3 z 15 kopiami magnesu linkowanymi do Smart Object "projekt". Edycja warstw wewnatrz SO "projekt" propaguje zmiany na wszystkie kopie. Struktura wewnatrz Smart Object "projekt" -> "Warstwa 2": - podziekowanie (text, domyslnie "Dziękuję za przybycie.") - data (DD.MM.RRRR) - tytul (2 linie: "Chrzest Święty\r{imie}") Wymaga: uruchomiony Adobe Photoshop, photoshop-python-api. """ import argparse import os import photoshop.api as ps PROJEKT_DIR = os.path.join( r"d:\pomysloweprezenty.pl\projekty\chrzest - magnesy", "Magnes podziękowanie dla gości na chrzest UV - Stopki serce", ) SZABLON_PATH = os.path.join(PROJEKT_DIR, "magnesy serduszka makieta A3 CMYK.psd") GOTOWE_DIR = os.path.join(PROJEKT_DIR, "_gotowe") SMART_OBJECT_NAME = "projekt" INNER_SET_NAME = "Warstwa 2" def set_text(layer, new_text): """Zmienia tekst warstwy zachowujac srodek bounding boxa.""" b = [float(x) for x in layer.bounds] cx, cy = (b[0] + b[2]) / 2, (b[1] + b[3]) / 2 layer.textItem.contents = new_text b2 = [float(x) for x in layer.bounds] cx2, cy2 = (b2[0] + b2[2]) / 2, (b2[1] + b2[3]) / 2 dx, dy = cx - cx2, cy - cy2 if dx or dy: layer.translate(dx, dy) def set_layer_text(container, layer_name, new_text): if new_text is None: return layer = container.artLayers[layer_name] old = layer.textItem.contents set_text(layer, new_text) print(f' {layer_name}: "{old[:30]}..." -> "{new_text[:40]}..."') def enter_smart_object(app, layer): app.activeDocument.activeLayer = 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) def hide_excess_copies(doc, liczba): """Ukrywa nadmiarowe kopie magnesu (szablon ma 15 slotow).""" slot_layers = [] for al in doc.artLayers: if al.name == SMART_OBJECT_NAME or al.name.startswith("main kopia"): slot_layers.append(al) total = len(slot_layers) if liczba >= total: return for layer in slot_layers[liczba:]: layer.visible = False print(f" Ukryto {total - liczba}/{total} slotow (zamowienie: {liczba})") def generate(klient, imie, data, liczba, podziekowanie=None): os.makedirs(GOTOWE_DIR, exist_ok=True) output_path = os.path.join(GOTOWE_DIR, f"{klient}.psd") app = ps.Application() doc = app.open(SZABLON_PATH) print(f"Otwarto szablon: {doc.name}") try: projekt_layer = None for al in doc.artLayers: if al.name == SMART_OBJECT_NAME: projekt_layer = al break if projekt_layer is None: raise RuntimeError(f'Nie znaleziono warstwy Smart Object "{SMART_OBJECT_NAME}"') enter_smart_object(app, projekt_layer) inner = app.activeDocument print(f" Wewnatrz SO: {inner.name}") w2 = inner.layerSets[INNER_SET_NAME] set_layer_text(w2, "tytul", f"Chrzest Święty\r{imie}") set_layer_text(w2, "data", data) set_layer_text(w2, "podziekowanie", podziekowanie) inner.close(ps.SaveOptions.SaveChanges) hide_excess_copies(doc, liczba) psd_opts = ps.PhotoshopSaveOptions() doc.saveAs(output_path, psd_opts, True) print(f"Zapisano: {output_path}") finally: app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges) print("Gotowe!") return output_path def main(): parser = argparse.ArgumentParser(description="Generator PSD - Magnes chrzest, Stopki serce") parser.add_argument("--klient", required=True, help="Nazwa pliku wyjsciowego") parser.add_argument("--imie", required=True, help="Imie dziecka (dopelniacz, np. Rozalii, Szymona)") parser.add_argument("--data", required=True, help='Data chrztu, format "DD.MM.RRRR" (np. 19.04.2026)') parser.add_argument("--liczba", type=int, default=15, help="Liczba zamowionych magnesow (1-15, nadmiar slotow ukrywany; domyslnie 15)") parser.add_argument("--podziekowanie", default=None, help='Tresc podziekowania (opcjonalnie, domyslnie "Dziękuję za przybycie.")') args = parser.parse_args() generate( klient=args.klient, imie=args.imie, data=args.data, liczba=args.liczba, podziekowanie=args.podziekowanie, ) if __name__ == "__main__": main()