Introduction: Using the Tweak Processing Library

About: Background in Electrical Engineering, Computer Science, Robotics, and Tangible Interfaces from MIT. Other projects I've worked on can be found at http://projects.kumpf.cc

A few weeks ago, I worked with Teague Labs to create a library for Processing that allows you to easily tweak variables while your Processing sketch is running. Tweak is pretty straight-forward, but I though an instructable might help to overcome the hurdles of setting it up and getting started.

Tweak is intended for rapid prototyping and fast-paced software development.  Beginning programmers often "hard code" values into their sketches as they tinker with how things are drawn on screen or handled behind the scenes, while expert developers usually build numerous classes, data types, and specifications to allow for scale and robustness.  Tweak is a friendly middle ground where beginners and experts alike can enable programs to be modified on-the-fly without having to worry about the details behind the scenes.


Step 1: Running Tweak for the First Time

Tweak is easy to setup.  To get started, just download one of the examples, open it with Processing, and hit Run.  We'll go over how it works (and how you can add Tweak to your own projects) next.

There are two examples you can start from:
Tweak Simple Demo
Tweak Complex Demo

To change variable values, just click and drag your mouse over the variable's name in the Tweak Panel.


Step 2: Adding Tweak to Your Own Sketches

Tweak can be added to your own sketches by copying the Tweak.pde file to your sketch's folder and adding a few lines of code to initialize it.  The Tweak.pde file can be found in either of the example sketches.

Once you have added the Tweak.pde file to your sketch's folder, you can use Tweak variables for the things you want to be able to change while your program is running.  If your sketch isn't finding the Tweak.pde file, just close and reopen your sketch (Processing looks for other .pde files in your sketch's folder when it is opened).

There are currently four basic Tweak variables: TweakFloat, TweakInt, TweakBool, and TweakPoint.  These can each be used as standard Float, Int, Boolean, and Point types; just use the "new" operator to create them and get their value via the "val" property. 

Perhaps an example will help at this point.  Here we create a number (of type TweakInt) in the setup method and then get its value in the draw loop.  The number's initial value is 100 and its description is "My changeable number".   We then use that number to set the amount of red in the sketch's background.

----------------------------
TweakInt myNumber;

void setup(){
  myNumber = new TweakInt("My changeable number", 100);
}

void draw(){
  background(myNumber.val, 0, 0);
}
----------------------------


You can also set bounds on your Tweak variables.  The example above works fine, but colors should normally stay between 0 and 255.  In some cases, letting a variable go out of bounds may do unexpected things, so let's add in some limits to the example.  The "1" in the TweakInt's instantiation specifies the step size (in other words, how quickly the number changes when you are adjusting the variable).

----------------------------
TweakInt myNumber;

void setup(){
  myNumber = new TweakInt("My changeable number", 100, 1, 0, 255);
}

void draw(){
  background(myNumber.val, 0, 0);
}
----------------------------



Finally, let's add all three color channels to our example.

----------------------------
TweakInt myNumberR;
TweakInt myNumberG;
TweakInt myNumberB;

void setup(){
  myNumberR = new TweakInt("Background Red",   100, 1, 0, 255);
  myNumberG = new TweakInt("Background Green", 100, 1, 0, 255);
  myNumberB = new TweakInt("Background Blue",  100, 1, 0, 255);
}

void draw(){
  background(myNumberR.val,
myNumberG.val, myNumberB.val);
}
----------------------------


Step 3: How Tweak Works

For those curious about what's going on behind the scenes, here's a bit about how Tweak works.  You can, of course, view all of the Tweak code directly (and modify, extend, etc.) by viewing the source in the Tweak.pde file.

Conceptually, Tweak is composed of two parts: the Tweak Panel (which displays variables and allows users to interact and change them), and a class structure that allows for common (or combined/complex) variable types to share a set of methods for display, manipulation, and bounds checking.

The Tweak Panel extends a JFrame and allows for a new window to be created where variables are displayed.  There a handful on interaction code that handles mouse clicks, drags, and scrolling (in case you have lots of variables!).

Now let's take a look at how a Tweak type (such as TweakInt, TweakFloat, TweakBool, and TweakPoint) works.

All Tweak types extend and abstract class, TweakParameter.  This ensures that all Tweak types will be able to work with the Tweak Panel.  A TweakParameter has a description, a way to increment/decrement a variable, bounds checking, and a value string.  Each Tweak type takes a bit of code, but everything is pretty straight forward.

Here is what the TweakInt looks like:

------------------------------

class TweakInt extends TweakParameter{
  int origVal;
  int val;
  int maxVal;
  int minVal;
  int step;
  public TweakInt(String desc, int val, int step, int minVal, int maxVal){
    this.val     = val;
    this.origVal = val;
    this.minVal  = minVal;
    this.maxVal  = maxVal;
    this.step    = step;
    this.desc    = desc;
    tweakParamList.add(this);
    tweak_initParamManagerIfNeeded();
  }
  public TweakInt(String desc, int val, int step){
    this(desc, val, step, -Integer.MAX_VALUE, Integer.MAX_VALUE);
  }
  public TweakInt(String desc, int val){
    this(desc, val, 1);
  }
  boolean supportsX(){
    return true;
  }
  boolean supportsY(){
    return false;
  }
  void incX(){
    val += step;
  }
  void decX(){
    val -= step;
  }
  void incY(){
  }
  void decY(){
  }
  int equalToOriginalValue(){
    if(val < origVal){
      return -1;
    }
    else{
      if(val > origVal){
        return +1;
      }
      else{
        return 0;
      }
    }
  }
  String valString(){
    return ""+val;
  }
  void keepInBounds(){
    if(val > maxVal){
      val = maxVal;
    }
    if(val < minVal){
      val = minVal;
    }
  }
}

------------------------------

Using this same structure, you can create your own Tweak types.  Basic types (such as Double, Long, Char, etc.) can be built very similar to the TweakInt, but there's no need to stop there.  More complex types can also be created that work with multiple variables and have internal state or communicate with other Tweak variables. 

If you're interested in building your own Tweak types, see the Tweak.pde file (some of the other types might also help, such as the TweakPoint which controls two variables, X and Y, at the same time).

Step 4: Tweaks to Tweak

Since Tweak is open source, you can view all of the code and hack it to do whatever you want.

After you've had your fun tweaking, there's a good chance you want to disable the additional window so that it doesn't show up when presenting your sketch.  You may notice that Tweak first checks for "tweak_hasBeenInitialized" before displaying the Tweak Panel.  You can fool tweak into thinking that it has already created the window and keep it from showing up by setting tweak_hasBeenInitialized to true before you instantiate and Tweak type variables.

Here, we modify the example from step 2 to disable the Tweak Panel window.

--------------------------------
TweakInt myNumberR;
TweakInt myNumberG;
TweakInt myNumberB;

void setup(){
   // a hack to hide the Tweak Control Panel:
   // (placed before any variables are constructed).
  tweak_hasBeenInitialized = true;

  myNumberR = new TweakInt("Background Red", 100, 1, 0, 255);
  myNumberG = new TweakInt("Background Green", 100, 1, 0, 255);
  myNumberB = new TweakInt("Background Blue", 100, 1, 0, 255);
}

void draw(){
  background(myNumberR.val, myNumberG.val, myNumberB.val);
}
--------------------------------

There's a lot more you can do.  Have fun and let us know what cool stuff you do with it.  Happy Tweaking!