2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TouchDesignerで作った絵をTouchDesignerから印刷する

Last updated at Posted at 2022-12-17

この記事はTouchDesigner Advent Calendar 2022 17日目の記事です。

今年は、TouchDesigner使いの人間が抱く3大欲求の一つである、
TouchDesignerで作った絵をTouchDesignerから印刷するやり方をご紹介したいと思います。
※Window用です。

今回のプロジェクトファイルは下記にアップしています。

システム構成

まずはシステム構成を考えます。
スクリーンショット 2022-12-16 122221.png

本来であれば venv作って必要なライブラリインストールしてTouchDesignerの中から印刷命令! と行きたいところなのですが、印刷に使うPythonライブラリである pywin32」が仮想環境から使えないらしい ということがわかりました。

ということでsubprocessで外部pythonを実行しています。
※pythonはグローバルのpythonを使います。

それと出力ファイル名をバリデートしている箇所がありますが、フォルダ監視で間違って変なファイルを検出して印刷してしまわないようなシステム構成にしています。

プログラム

そして実際のプログラムです。
TouchDesignerのオペレーターはそれほど多くありませんね。
スクリーンショット 2022-12-16 154701.png

以下流れ

  1. 画像出力先のフォルダ(今回はimagesフォルダ)を外部のPythonで監視開始(後述)
  2. Button 押下でnull1のCookが走る
  3. CHOP EXECUTE DAT(createFileName) でファイル名を生成してText DAT(fileName) にタイムスタンプのファイル名を出力し、moviefileout1のrecordを実行
  4. 監視プログラムが画像ファイルを検出しそのファイル名をOSCで通知、udpin1に検出したファイル名を送信
  5. 4のタイミングでudpin1_callbacksが走り、受信したファイル名と、3で生成したファイル名を比較
  6. 5のバリデーションで問題なければprintを実行。※本当はここでプリント処理を記述したかったのですが、subprocessで外部pythonを実行しています。(後述)
  7. 外部の印刷用pythonが走り、印刷が完了するとudpin2に成功の通知が来る
    ※今回はエラーハンドリングは行わず成功が返るだけになっています。

フォルダ監視プログラム

これはpythonの Watchdog をpipでグローバルにインストールして使っています。
コマンドプロンプトで実行してシステムに常駐させます。

import os
import time
import sys
import socket
from argparse import ArgumentParser

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

class MyWatchHandler(FileSystemEventHandler):
    def __init__(self):
        super().__init__()

    def on_any_event(self, event):
        pass

    def on_created(self, event):
        #ファイルが生成されたときにUDPでファイル名を送信
        sendUDP(os.path.basename(event.src_path))

def msg_to_bytes(msg):
    return str(msg).encode('utf-8')

def sendUDP(basename):
    upd_ip = "127.0.0.1" #TouchDesigner側(udpin1)と合わせる
    udp_port = int(7000) #TouchDesigner側(udpin1)と合わせる
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(msg_to_bytes(basename), (upd_ip, udp_port))

def monitor():
    event_handler = MyWatchHandler()
    observer = Observer()
    observer.schedule(event_handler, '../images/', recursive=True)#監視するフォルダを指定する
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()


def main():
    monitor()


if __name__ == "__main__":
    main()

subprocess部分

ここは去年のアドカレでも少し記述しました。同じように記述します。

import os
import subprocess

#オペレーターの名前は適宜変更
port = str(op('udpin2').par.port.val) 
file = '{}/images/'.format(project.folder) + str(op('fileName').text)

#自分の環境のPythonを指定
cmd_python = 'C:/Users/[user]/AppData/Local/Programs/Python/Python39/python.exe'

#実行するpythonファイルを指定
cmd_python_script = '{}/scripts/print.py'.format(project.folder)
python_args = [cmd_python, cmd_python_script]

#OSCに使うポート番号と、印刷するためのファイルパスを引数で渡す指定
script_args = ['-p', port, '-f', file]
cmd_args = python_args + script_args
op('udpin2').par.clear.pulse()

#ここでプロンプトのウィンドウを非表示にする設定
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW

#コマンド実行
subprocess.Popen(cmd_args, startupinfo=si)

印刷のプログラム

下記の記事等を参考にpythonから印刷するコードを書いて実行するだけです。
その際にport番号やOSCの送受信の記述も入れています。

実行するとwindowsのシステムで既定になっているプリンターのキューに入るようになっています。

以上で終わりです。
よいお年をー😀

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?