OSC messages to trigger Python?

I am trying to use OSC messages from Max to control the cooking of individual processes in TouchDesigner. I have the following TOE that contains working Python code excerpt from the larger patch. I can trigger the code with buttons, but everything I have tried to connect to OSC messages fails. The messages are formatted like this, with 1/0 being on/off:

/td/kief/active 1
/td/roth/active 1
/td/fish/active 1
/td/meba/active 1

The Python code only seems to work in this “Panel Execute DAT” but not in any of the other Execute OPs. Any advice on what I might be missing?

OSCtoPython.toe (4.9 KB)

1 Like

Welcome to the forum @nathanwolek!

First things I’d check - are you getting the messages in TouchDesigner?

You could do this either with an OSC in DAT or OSC in CHOP. Using a DAT you’d parse by address, and then choose which code block to run. Using a CHOP you’d probably want to use a CHOP execute and watch for which channel has changed in order to determine which code block to execute.

More generally, Touch is a pull based system, so turning cooking on and off isn’t always the most efficient approach to these kinds of problems. Often building more of an AB deck with some simple switching is a little easier to wrangle than updating pars every frame and bypassing / unbypassing ops.

If it’s too late for you to refactor your work, consider this example file. In here all of the yellow ops are used to simulate messages being sent from Max:

The elements doing any work are on the right:

Here you could block each action as it’s own text DAT - you can treat these as their own functions that run with arguments you’ll pass to them with the run() method. The OSC DAT parses the messages, finds which target DAT to run, and then passes the active value to the target DAT.

Hope this helps!
oscDAT-example.tox (2.0 KB)

3 Likes

Matthew:

Thanks for the detailed reply! First, I want to also thank you for all the material on your website. The documentation there has been a big help as I dove into TouchDesigner for a project this past year.

Good point about the pull based system. After 20+ years in Max, it’s hard to fight my instinct to think about pushing messages.

I am not sure a switch will work in this case, because the project calls for blending each of these looks. Instead of switching between the looks, we want the ability to layer them at specific moments. Switching the cooking between true/false seemed like the best way to save CPU when a layer is inactive.

Thinking about it again, I suppose I could refactor to switch each look with a blank frame. However, wouldn’t Touch still be pulling the frames from my layer and multiplying the pixels by zero? Is there an object that stops pulling frames when a layer is not being factored into the output?

Hope that makes sense.
-Nathan

Hi @nathanwolek - I’m always glad to hear the pieces I’ve made help. If only there were more hours in the day :slight_smile:

So given your description of a more layer based system you could think of a few different approaches here that might help.

TouchDesigner Centric Op Approach

A more op based approach would be to use something like the switch TOP set to “blend between inputs”. This only cooks the current index and the next index. For example, an index value of 0 cooks the 0 and 1 inputs. 0 and 1 will continue to cook until we get to an index value of 1, then inputs 1 and 2 will cook. So You could do something like this:

Here a button simulates the active value, and a filter CHOP is used for your easing / transition between switch inputs. Setting the null’s cook type to be selective will prevent the null from updating the value of the index par every frame. This effectively stops the first input to the switch from cooking.

base_switch_top_approach.tox (1.3 KB)

That might be enough, but if that’s not totally enough rails for your process, you might think about locking a top.

Scripting the Lock Attribute

This other approach is a little more pythonic, and uses two scripts to make this work. The trick here is that you can “lock” any operator. This creates a cached “frozen” state of the data in an operator. This is more efficient than bypassing un-bypassing because it preserves the memory of your chain of operators - bypassing and un-bypassing or turning cooking on / off can sometimes cause your ops to re-cook or re-initialize. This usually ends up in looking like frame drops and performance stutters - which is why I only use that approach if there are no other viable alternatives.

In this example we use one script to turn off the lock property of our level TOP… anytime our active value changes we’ll want to unlock the TOP so changes can push. Another script locks the TOP only when the state of active goes from 1 to 0 - or when the opacity is turned all the way off. We similarly use a filter CHOP for the easing, and our script to lock the level TOP happens based on values after filtering.

base_script_gate.tox (1.6 KB)

This is kind of gating in TouchDesigner that is a little more flexible, but also means you need a few more handles manage the state of your ops.

Hopefully one of these approaches should help do the trick. I think either of these should be fairly straight forward to integrate for a refactor - though you can always hold off on making that decision if your frame rates still look good.

Hope this helps!

1 Like

Circling back this post to say thanks for all the valuable tips last year, Matthew! The concert for this project was live streamed last weekend, so I thought you and others might like an update about the results.

You can see the 15-minute piece that resulted from this work at the link below (takes you directly to the piece in a two hour concert). All visuals are produced by Touch Designer and controlled using OSC messages from Max. There are 5 different “looks” that can be turned on and off (and even layered!) using the Python control scheme that is outlined in this post.

Thanks again for the clear and specific help that set me off on the right path. Take care.

-Nathan

1 Like