Generic Controller exposed to JavaScript interface in client

This adds the "Controller" scripting interface to the JS in the client... currently it supports these methods:

```
bool isPrimaryButtonPressed()
glm::vec2 getPrimaryJoystickPosition()

int getNumberOfButtons()
bool isButtonPressed(int buttonIndex)

int getNumberOfTriggers()
float getTriggerValue(int triggerIndex)

int getNumberOfJoysticks();
glm::vec2 getJoystickPosition(int joystickIndex)

int getNumberOfSpatialControls()
glm::vec3 getSpatialControlPosition(int controlIndex)
glm::vec3 getSpatialControlVelocity(int controlIndex)
glm::vec3 getSpatialControlNormal(int controlIndex)
```

Here's some sample script that demonstrates it's use:

```
var currentIteration = 0;
var  MAX_ITERATIONS = 60 * 60 * 3; // about 3 minutes...

function checkController() {
    var joystick = Controller.getPrimaryJoystickPosition();
    var buttonPressed = Controller.isPrimaryButtonPressed();
    print("buttonPressed=" + buttonPressed + " joystick=" + joystick.x + ", " + joystick.y + "\n");
    currentIteration++;

    var numberOfJoysticks = Controller.getNumberOfJoysticks();
    var numberOfButtons = Controller.getNumberOfButtons();
    var numberOfTriggers = Controller.getNumberOfTriggers();
    var numberOfSpatialControls = Controller.getNumberOfSpatialControls();

    print("numberOfJoysticks=" + numberOfJoysticks + " numberOfButtons=" + numberOfButtons + 
            " numberOfTriggers=" + numberOfTriggers + " numberOfSpatialControls=" + numberOfSpatialControls + "\n");

    for (var j = 0; j < numberOfJoysticks; j++) {
        var joystickValue = Controller.getJoystickPosition(j);
        print("joystick[" + j + "]=" + joystickValue.x + "," + joystickValue.y + "\n");
    }

    for (var b = 0; b < numberOfButtons; b++) {
        var buttonValue = Controller.isButtonPressed(b);
        print("button[" + b + "]=" + buttonValue + "\n");
    }

    for (var t = 0; t < numberOfTriggers; t++) {
        var triggerValue = Controller.getTriggerValue(t);
        print("trigger[" + t + "]=" + triggerValue + "\n");
    }
    
    for (var s = 0; s < numberOfSpatialControls; s++) {
        var controlPosition = Controller.getSpatialControlPosition(s);
        var controlVelocity = Controller.getSpatialControlVelocity(s);
        var controlNormal = Controller.getSpatialControlNormal(s);
        print("control[" + s + "]" + "\n"
                + "    position=" + controlPosition.x + "," +  controlPosition.y + "," + controlPosition.z + "\n"
                + "    normal=" + controlNormal.x + "," + controlNormal.y + "," + controlNormal.z + "\n"
                + "    velocity=" + controlVelocity.x + "," + controlVelocity.y + "," + controlVelocity.z + "\n"
                + "\n");
    }
    
    if (currentIteration > MAX_ITERATIONS) {
        print("calling Agent.stop()...\n");
        Agent.stop();
    }
}

 
// register the call back so it fires before each data send
Agent.willSendVisualDataCallback.connect(checkController);
```