# 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.