杰瑞科技汇

touchdesigner python

Of course! This is a fantastic question. Using Python in TouchDesigner is a powerful way to extend its capabilities, automate tasks, and create complex, custom logic that would be difficult or impossible with the built-in nodes alone.

touchdesigner python-图1
(图片来源网络,侵删)

Here’s a comprehensive guide to Python in TouchDesigner, broken down into key concepts, where to use it, and practical examples.


Why Use Python in TouchDesigner?

TouchDesigner's node-based paradigm is incredibly visual and fast for prototyping and many common tasks. However, Python excels where you need:

  • Complex Logic: Handling intricate state machines, complex mathematical calculations, or parsing data structures.
  • External Communication: Easily integrating with web APIs (like OpenAI, weather services), databases, or other software over TCP/UDP or serial ports.
  • Text Processing: Manipulating strings, parsing JSON/XML, or reading/writing files.
  • Automation: Creating custom tools, managing large networks, or automating repetitive tasks.
  • Object-Oriented Programming: Organizing complex logic into reusable classes and objects.
  • Leveraging Libraries: Using the vast ecosystem of Python libraries like requests, numpy, Pillow, or opencv-python.

Where to Run Python in TouchDesigner

TouchDesigner provides several places to run Python, each with its own use case.

Component Where to Find It Best For... Execution Context
python TOP In the network editor. Real-time, per-frame execution. Manipulating pixel data, running a loop for each pixel. Runs on the GPU (if available) or CPU. Very fast for pixel operations.
script CHOP In the network editor. Channel-based data. Reading/writing channels, analyzing or generating audio/MIDI data. Runs on the CPU.
text DAT In the network editor. General-purpose scripting. Good for organizing code, constants, or helper functions. Runs on the CPU.
panel Execute Right-click a panel > Run Script. UI-specific interactions. Customizing buttons, sliders, and other widgets in a panel. Runs on the CPU.
op Execute Right-click any operator > Run Script. Quick, one-off scripts to modify that specific operator or its parameters. Runs on the CPU.
Python Editor Ctrl+Shift+P or Window > Python Editor. Debugging, testing code snippets, and running longer scripts without a UI component. Runs on the CPU.
TouchDesigner Python Module From an external Python script or terminal. Batch processing, rendering animations, or building tools outside of the real-time environment. Runs in a standalone Python interpreter.

The Core: The op() and parent() Objects

The most important concept to understand is how your Python script talks to the TouchDesigner network. You do this through two main objects:

touchdesigner python-图2
(图片来源网络,侵删)

op('operator_path')

This is your primary tool. It lets you get a reference to any operator in your network, just like you would type its path into a parameter.

Syntax: op('parent_name/child_name')

Examples:

# Get a reference to a movie player TOP
movie_player = op('movie_in1')
# Get a reference to a null container
my_container = op('my_container')
# Get a reference to a CHOP with the path /project1/audio
audio_chop = op('/project1/audio')

parent()

This is a shortcut for op('.'). It returns the operator that the script is currently living inside.

touchdesigner python-图3
(图片来源网络,侵删)

Example: If you have a script CHOP named my_script inside a container named logic, then inside my_script:

# These two lines are equivalent
my_parent = parent()  # Gets the 'logic' container
my_parent_alt = op('.') # Also gets the 'logic' container
# You can chain them
# If 'logic' contains a null named 'settings', you can get it like this:
settings_null = parent().op('settings')

Common Python Tasks in TouchDesigner

A. Reading and Writing Parameters

This is the most frequent operation. You use the .par attribute.

# Assuming my_script is inside a container named 'logic'
# and 'logic' contains a movie player named 'movie_in1'
# Get a reference to the movie player
movie_player = parent().op('movie_in1')
# --- Reading a parameter ---
current_file = movie_player.par.filename  # Get the value of the 'filename' parameter
print(f"Current movie file: {current_file}")
# --- Writing a parameter ---
# Set the filename to a new movie
movie_player.par.filename = 'C:/path/to/my/new_movie.mp4'
# You can also use the .val shortcut for simple parameters
movie_player.par.play.val = True  # Press play
print(f"Play state is: {movie_player.par.play.val}")

B. Working with TOPs (Pixel Data)

The python TOP is designed for this. It gives you a NumPy array of the pixel data.

# This code would live inside a 'python' TOP
# 'prev' refers to the top connected to the input of the python TOP
# Get the pixel data as a NumPy array
# It will have shape (height, width, channels) for RGBA images
pixels = prev.SliceNumComponents(4) # Get RGBA data
# --- Manipulate the pixels ---
# Example: Invert the colors
pixels[:, :, 0:3] = 255 - pixels[:, :, 0:3] # Invert RGB channels
# --- Set the output ---
# The 'dst' object is the output of the python TOP
# You must assign a NumPy array to it
dst[:] = pixels

C. Working with CHOPs (Channel Data)

The script CHOP is perfect for this. It gives you a list of channels.

# This code would live inside a 'script' CHOP
# 'me' is a reference to the script CHOP itself
# --- Read channel data ---
# Get a list of all channel names in the first input CHOP
chop_names = me.inputs[0].colnames
print(f"Input channels: {chop_names}")
# Get the value of a specific channel at the current sample
x_value = me.inputs[0]['chan1'][0] # [0] gets the current sample
# --- Write channel data ---
# Create a new channel named 'output'
me.appendChan('output')
# Set a value for the current sample on the 'output' channel
me['output'][0] = x_value * 2 # Double the input value

D. External Communication (e.g., a Web API)

This is where Python shines. You can use the requests library.

Setup:

  1. Install the requests library in your Python environment.
    • Go to Edit > Preferences > Python.
    • In the "Packages" section, click and type requests. Click Install.
  2. Create a script DAT to run the code.
# This code lives in a 'script' DAT
import requests
import json
# The op() to our UI panel where we'll display the result
ui_panel = op('ui_text')
def get_weather(api_key, city):
    url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
    try:
        response = requests.get(url)
        response.raise_for_status()  # Raise an exception for bad status codes
        data = response.json()
        temp = data['main']['temp']
        description = data['weather'][0]['description']
        return f"It's {temp}°C and {description} in {city}."
    except requests.exceptions.RequestException as e:
        return f"Error fetching weather: {e}"
    except (KeyError, json.JSONDecodeError):
        return "Error parsing weather data."
# --- Call the function ---
# Replace 'YOUR_API_KEY' and 'London' with real values
api_key = 'YOUR_API_KEY'
city = 'London'
weather_report = get_weather(api_key, city)
# Display the result in a text DAT
ui_panel.text = weather_report

Best Practices and Tips

  1. Organize Code in text DATs: For complex scripts, write your functions in a text DAT and then exec() or import them in your script CHOP or python TOP. This keeps your network clean and your code reusable.

    text DAT (named my_functions):

    def add_numbers(a, b):
        return a + b

    script CHOP:

    # Execute the code from the text DAT
    exec(op('my_functions').text)
    # Now you can use the function
    result = add_numbers(5, 7)
    print(f"The result
分享:
扫描分享到社交APP
上一篇
下一篇