virtual-world-framework/vwf — pull request #160 by rchadwic (2014-03-12 15:08:20+00:00)
Title: Branch/watchable

So, this patch will allow authors to set properties of complex objects naturally, just as if the complex object was a sub node. This is how we accomplish `this.material.color.r = 0` in the Sandbox. I prefer this because it makes the job of the drivers much much easier. Instead of creating a child node for material and a child node for color, the driver can just operate on the simple JSON object that is the property value. You can also imagine this might make it simpler to do things like `this.animations[0].cycles.run.speed = 1.2`.

I'm making heavy use of caching here, because building a watchable is very expensive. Note that when you set a value which is itself an object or array, we have to uncache the Watchables for all child properties.

Also, this has effects on many of the libraries in `/support/www.example.com`. When you send the watchable into the goog.vec functions, you're generating many many kernel entries, because every operation that the goog.vec library does (even intermediate steps) cause a set property for the while object. This can even do some nasty stuff to the engine, as some of the intermediate steps in the calculations might not produce proper matrices or vectors. The solution is to fetch the .internal_val property from the watchable, which will return the raw value without all the get/set goo attached.

Another issue to be aware of: any test that uses `instanceOf` on a property will return `Watchable`. You should call `instanceOf` on the .internal_val. Also, be careful not to store a reference to the watchable in another property that is not a Watchable. For instance.

```
this.notaproperty = this.transform;
//this actually causes a set on 'transform' !
this.notaproperty[12] = 0;
```

Note: Strings are treated as primitives - since `typeof 'asdf'[0] === String` we can hit infinite loops here. Indexing into strings and setting will not trigger a set.

Note: I do implement most of the Array class functions like `push` , `pop`, `length`,`indexOf`, and others, but not every possible function. This is pretty easy to extend.

Finally, adding a property will not trigger a set. We probably add a function to the object to fix that. You must manually trigger a set in the following way:
```
this.prop = {name:'hi',val:[0,1,2]};
//this does not trigger the set!
this.prop.name2 = 'hello';
//fix it like this
this.prop = this.prop
```