Once you have put out all the objects you intend to animate with Clockworks, the rest of the work is done by custom control scripts you write or buy from others.

Getting started

To get started, you should download the following sample script:

Download sample script

In most simple cases, the only part you need to edit is the .ConfigureMachines() method:


private void ConfigureMachines() {

    // Give the controller and units a chance to initialize
    Wait(TimeSpan.FromMilliseconds(WaitSecondsBeforeInit * 1000));

    ProgramMsg(SetName, "Attach", "B", "A");

    ProgramMsg(SetName, "Arm", "A", FromVector(BasePosition), FromVector(BaseOrientation));
    ProgramMsg(SetName, "Arm", "B", "1,0,0", "0,0,0");

    ProgramMsg(SetName, "Prog", "A", "", "S:1/2 | S:-1/2");
    ProgramMsg(SetName, "Prog", "B", "", "S:1");

    ProgramMsg(SetName, "Start", "");

}
 

Configuration is done by sending messages out to the "Clockworks - Controller" script, which in turn talks to the individual units. You do this by calling the .ProgramMsg() method.

Be sure to read the Assembling a machine before writing a custom script. You will also need to learn about unit programming.

Messages sent to the controller (using the ScenePrivate.Chat.MessageScript() method) look like so:

Cw|X|Attach|B|A

Which is reflected in the equivalent Live programming command:

/cw x attach b a

And the custom script call:

ProgramMsg("X", "Attach", "B", "A");

Ignoring the "CW" message prefix, the first argument in the message is always the set name to apply the operation to (e.g., "X"). The second argument is always the operation name (e.g., "Attach"). The third argument is usually (but not always) the name of the unit to apply it to (e.g., "B"). And the remaining arguments are specific to the operation (e.g., "A").

Note that the set name can either be literally the name you gave it or asterisk (*) to address all sets.

Although you should have read about this by now, it bears repeating that you must perform all attachment of segments before configuring other aspects of them like their arms or programs. This is because any given unit will need to know not only about its own configuration, but also the configuration of its parent segment, that one's parent segment, and on all the way up the chain for that machine. If you do not do this in the proper order, your machine will not function properly.

That said, you can sometimes get away with not doing all attachment first. Let's say you had a spider, for instance. You could attach one leg to its body and then set up the arms/axes for that one leg before attaching the second leg and configuring it. But this is flirting with danger. You could not, for instance, set any of the body's configuration before you attached all the legs without breaking your machine. Use this tactic sparingly.

Addressing units by name

Most operations influence individual units. However, if you have ten identical units, you don't need to have ten copies of the same configuration operation to update them all. If you named them well, you can address your units in groups.

For starters, you can use the asterisk (*) character as a wildcard character. If, for instance, you had units named "Car.Wheel.LeftFront", "Car.Wheel.RightFront", and so on, you could address all wheels via "Car.Wheel.*". If you also had a "Truck" machine with part names like "Truck.Wheel.LeftFront", etc., you could address all wheels for all vehicles using "*.Wheel.*".

Second, you can take advantage of the special "$" variable in unit names that represents the machine name. If you have a unit named "Lamp.$.Base" and had ten copies of the lamp with machine names like "1", "2", "3", etc., you would be referring to all of them using "Lamp.$.Base". If you wanted to refer to one specific one, as when placing the lamp's base (and everything attached to it) in the scene, you would replace the "$" with the machine's name. For example, "Lamp.3.Base".

You can only directly refer to units by their set names and unit names. You never refer directly to the flavor variants. And you only refer indirectly to specific machines through the "$" variable in a unit name.

Separate scripts

You are not required to lump all of your Clockworks configuration into one single script. It can be useful to create separate scripts to configure different classes of machines or sets. This is especially true if you plan to sell your own animated machine creations.

A good strategy is to separate scripts when you think you might reuse machines you create for one scene in other scenes. Remember that these scripts consume resources and have to be set out and configured, so don't go overboard.

If you create a script oriented toward setting up a single machine, as you might with a commercial product, be sure to add settings. These are a good start:


public float WaitSecondsBeforeInit;

public string SetName;

public string MachineName;

public Vector BasePosition;

public Vector BaseOrientation;

public int UpdateRate;
 

With these, you enable your users to properly sequence the setup and add more than one copy of your machine, via unique naming and positioning in the scene.

Let's say you had 20 different machines out there and one script for each. One upshot of this approach is that all 20 of those configuration scripts could start running at the same time (WaitSecondsBeforeInit) and send out their messages to their respective machines. The way this all works, no wires should get crossed and everything will happen (virtually) in parallel.

Thus, a good rule of thumb is to give the Clockworks controller and unit scripts at least a second to get themselves initialized before having other scripts throw configuration messages at them. And then give all those configuration messages enough time to be processed — at least another second — before you start sending other signals to get them all started to sync up with your music or whatever. There is a virtue in waiting a little longer than that, though, to make sure the first user (probably you) gets logged in and thus can see any error messages that might be thrown by your scripts or others, at least while you are creating your experience. But all this is why you want to make your separate machine configuration scripts have a WaitSecondsBeforeInit type setting, especially if you are selling these scripts and not giving buyers the ability to edit your scripts. Don't hard-code that in.