Coming off of my post last week about starting to think about projects as systems instead of linear timelines, it’s time to dive deeper and talk about the signals side of things. If you start thinking about your projects and installations as complex systems and lay out all the dependencies and interlinked elements, you may end up naturally thinking about it as a kind of state machine, where you have many different states (or moments or loops) in the system that move between each other based on some kind of trigger or signal or input. So that’s what today’s post is about, the follow up to Systems Thinking in TouchDesigner is Signals Thinking.
Full Disclosure: unlike systems thinking, which is a real thing you can learn about and get good at, signals thinking is something I just made up (and really it’s more of just a simple idea and workflow than anything else), so don’t go doing web searches to find resources for signals thinking…
What is Signals Thinking?
Similar to how systems thinking was about envisioning your whole environment as a complex mesh of components and their connections, signals thinking is almost a secondary deeper stage of thinking about your system that isolates all the signals/drivers/triggers of a complex system. You probably won’t find signals thinking useful at all if you don’t think in systems first, but if you are thinking in systems it’s what allows you to take real control of your system.
By real control, what I mean is that you can actually control almost any part of the system independently like a puppeteer would control a puppet. A puppeteer may choose not to randomly move random body parts without moving complimentary parts, but it is within their capability to do so. The harsh reality about installation work and a lot of logic programming I see is that most installations don’t even have this basic capability. They can only go forward in one direction on very narrow conditions and if even the smallest change is needed to be made to either one of the inputs or signals or the run of show needs to be updated, it becomes a complete disaster. It becomes a surgical operation the developer needs to perform and the patient is on life support holding on by a thread. That probably sounds like a familiar situation, or the example I made in the last post was about how you finished a complex run of show programming and the client is now asking for a reset button that can go from any state to the beginning of the experience cleanly.
How to start thinking in signals?
The first step is seeing things differently. Let’s look at some examples of keyframe/timeline animations and talk about how I would approach them mentally as signals, which would naturally take me away from any notion of timeline.
Easy example – Stepping animation
So the above is some really simple keyframe data. Every 2 frames, the value of the animation steps to something else. If you’re coming from a discipline that does a lot of keyframing or is hooked on timelines, you may see this as one “unit” or one layer of keyframe data, something very simple and a small building block in something bigger. When I look at this, I already see something “compounded” and complex because I’m thinking about this data as one or many signals and how they change over time and what patterns I’m seeing. This is the key of signals thinking, breaking down things like keyframe/timeline-based data or any type of control values, inputs, or signals, into the most basic elements that build it up.
When I look at the above, I see 5 “states” the signal has and it changes at a regular “interval”. It’s important to not get too tied into either the states or the interval, because if you set this up correctly in TouchDesigner, it’s arbitrary what those values are and what the interval is. So even a quick look at this I could imagine at least 3 different ways of doing this in TouchDesigner:
- Having one Button COMP per state, passing the output of each button to a Math CHOP so that each output could be scaled from 0-1 to be 0-X, where X is the difference between the next state value and the current state value. Then all those individual signals would go to another Math CHOP that would add them all together, so as you click each next button you would increment the number to the next state.
- Make a bunch of Constant CHOPs, each one with the value of a single state, and connect all of those to a Switch CHOP, which can then have the index updated easily to switch between the states/values.
- Have one Constant CHOP that represents the final value you want and then a handful of Python scripts that update the op().par.value0 of that Constant CHOP.
Why is this really important? You might be thinking “wow that sounds way more complicated than regular keyframes!” It is and it isn’t. It is, in that you had to think about your problem a little bit different, which might be a bit uncomfortable in the ol’ coconut, but it’s actually freeing and easier in the long run because you now have 3 different ways to approach the same problem, all of which are very easy (a few operators or a few lines of the simplest Python), all of which have completely different integration methods, and all of which have different strengths.
If your project is already Python heavy the 3rd option would be really easy to integrate seamlessly into existing scripts. If your project has some kind of UI display, the first button easy integrates into that to show you logic pre-viz in your UI. If you’re going to the most optimized system possible, the 2nd method would have the lowest overall cook time because switches are so fast.
And we haven’t even begun to talk about the sheer flexibility of it all. It’d be easy to make any of those 3 examples dynamic in terms of changing the values of the states or the intervals of change. You aren’t locked into a sequence of events. You can time the steps between the actions however you like, it could even be random! You can override them manually very easily even within the network editor. You could even hotwire new steps in between the existing states or have other signals triggered off of different steps. All of these things would be trickier if not down right annoying/time-consuming to do if you were locked to some kind of keyframe or timeline.
What you should probably still keyframe
I’ll talk about this more in my next post about getting off the timeline along with more complex examples and some TouchDesigner projects you can look at, but if you encounter something that looks like the below, it may be more trouble than it’s worth to actually control as a bunch of signals. It can be done, but you might just be spending a lot of time recreating that data set, when you could just export it in some way that could be read into an Animation COMP or similar.
I hope you’re starting to see the light here. If you start thinking about your projects as complex interconnected systems of events and loops, and then you take it even further and start being thoughtful about your signals, not only will you never want to touch the timeline again, your projects will be cleaner, you’ll feel more powerful and flexible, you’ll be able to respond to client changes faster, and more.
I can’t stress how many benefits there are to mentally ditching the timeline and keyframe animations. In the next post of this series, I’ll talk through a few more complex examples and give you some TouchDesigner project files you can use as templates for how you can create complex signals instead of relying on timelines and keyframe data.