SubstanceDesignerからPhotoshopにテクスチャを送る


この記事はTakumi Akashiro ひとり Advent Calendar 2020の11日目の記事です。

昨日 (PythonからCOMオブジェクトを扱う - Qiita) に引き続き、
今日はSubstance DesignerからPhotoshopへ出力したテクスチャを送ります。

昨日と同じネタを擦るな!と灰皿が飛んでくるかもですが、
便利そうで、出来そうなことはなるべくやるのが私のモットー(?)なのでやります。

それに、今後の仕事で必要な瞬間が来る予感がしますし。

とりあえず作る

テクスチャをtempフォルダに書き出して、
Photoshopで開き、開いているドキュメントのレイヤーにコピーして、閉じるだけです。

特にそれ以外は技術的に解説することはないので、とりあえず作ります。

import gc
import pathlib
import tempfile

import sd
from PySide2 import QtWidgets

# 拡張モジュール。詳細は昨日の記事参照。
import comtypes.client

def get_photoshop_client():
    client = comtypes.client.GetActiveObject("Photoshop.Application")
    if client:
        return client
    else:
        return comtypes.client.CreateObject("Photoshop.Application")

def is_exist_document(client):
    return bool(len(list(client.documents)))

# def get_output_size():
#     出力するテクスチャ解像度を取得する
#     NOTE:
#           当初はテクスチャ解像度を取得して、ドキュメントがなければ生成、
#           既に開かれていれば、Photoshopの開いているドキュメントのサイズと比較、
#           違ったらconfirmDialogを出すとかやりたかった。倍解像度で送ってリサイズ…とかする人もいるので不要かもだが。
#           だが、テクスチャ解像度をピクセル単位で取得するすべが分からない……ので断念。
#           Relativeの元の値はどこに格納されてンだよ…
#     pass

def export_texture_to_temp_folder(sd_graph):
    export_path = tempfile.gettempdir()
    sd.tools.export.exportSDGraphOutputs(sd_graph, export_path, 'png')
    path = str(pathlib.Path(export_path) / (sd_graph.getIdentifier() + "_output_0.png"))
    return path

def send_texture_to_photoshop(ps_client, path):
    document = ps_client.activeDocument
    ps_client.open(path)
    ps_client.activeDocument.artLayers[0].duplicate(document)
    ps_client.activeDocument.close()

def main():
    ps_client = get_photoshop_client()

    sd_app = sd.getContext().getSDApplication()
    sd_uimgr = sd_app.getQtForPythonUIMgr()
    sd_graph = sd_uimgr.getCurrentGraph()

    # sd_size = get_output_size()

    if is_exist_document(ps_client) is False:
        print(is_exist_document(ps_client))
        sd_mainwindow = sd_uimgr.getMainWindow()
        message = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, "TextureSender", "Photoshopでドキュメントを開いてから実行してください", parent=sd_mainwindow)
        message.show()
        return

    texture_path = export_texture_to_temp_folder(sd_graph)
    send_texture_to_photoshop(ps_client, texture_path)

    del ps_client
    gc.collect()


main()

結構いい感じですね!

締め

SubstanceDesingerのPythonモジュールは叩いて2日ぐらい1でしたが、どうにかそれっぽくはなりましたね!

……Outputノードが複数あるときの挙動とか、OutputNodeの名前を直書きしてるとか、
前に送った奴はレイヤー名とかロック状態とか参照して消したいとか、いろいろ思うところはありますが、
時間が全く足りないので今回はここまでで!

では!

参考

【SubstanceDesigner】Pythonでテクスチャを出力|三味松ブログ


  1. 正味6時間ぐらい?先人のおかげで10分ぐらいでテクスチャは出力出来て、内4時間ぐらいはテクスチャサイズの取得に使ってた。
    SDPropertyが理解できたのは収穫だった。