# TDPyMovieplayer
A movie player whose network is built by Python, not by hand: it reads a folder
of video files, measures them, and plays them in a random order — each clip
starting at a random point and running at a random speed, cut to the next after
a fixed dwell time.
`TDPyMovieplayer.toe` holds no project code. It carries one Execute DAT that reads its
source from `DAT/StartupExec.py`, puts this folder on `sys.path`, and hands off
to `tdpy/startup.py` a frame later. The network itself is created by
`tdpy/build.py` — that is the file to edit.
Generated by [touchdesigner-python](https://github.com/wtkns/touchdesigner-python).
## Setup
1. Create the Python environment with tdPyEnvManager, named `TDPyMovieplayer_vEnv`, so the
interpreter matches TouchDesigner's own.
2. Run `open-project.bat`. It opens VS Code on this folder and TouchDesigner on
`TDPyMovieplayer.toe`, discovering both installs rather than hardcoding them.
Requires TouchDesigner **2025.32050 or newer** — `.toe` files are
forward-compatible only.
## Media
Put video files in `media/`. Nothing in there is committed — the files are large,
binary, and particular to whoever is running the project — so the folder arrives
empty on a fresh clone and stays tracked via its own `.gitignore`.
## The development loop
Edit `tdpy/build.py`, then in TouchDesigner's textport:
```python
import tdpy.startup; tdpy.startup.reload()
```
TouchDesigner keeps modules loaded for the life of the process, so a saved file
changes nothing until the old module objects are discarded — that is what
`reload()` does before rebuilding. It cannot reload `startup.py` itself; edits
to that file need TouchDesigner restarted.
Builds are clear-and-rebuild: each run destroys the previous `generated`
container and makes a new one. Anything outside it is left alone.
You do not save the `.toe`. Your work is not in it.
## Errors
Exceptions raised inside a DAT callback are easy to lose. The build is wrapped,
and failures are printed to the textport and appended to `logs/startup.log`.
## Two constraints worth knowing
TouchDesigner's globals — `op()`, `project`, the operator classes — are injected
into DAT scripts, expressions and the textport only. A module imported from disk
gets none of them and must go through the `td` module, imported inside the
function that needs it.
The bootstrap imports only the standard library, and `td` and any third-party
package are imported inside `build()`. TDPyEnvManager sets up its environment
during startup, and code running earlier cannot assume it exists yet.