Checkpoint on fixing the positioning mess.
authordsc <david.schoonover@gmail.com>
Thu, 9 Dec 2010 22:09:26 +0000 (14:09 -0800)
committerdsc <david.schoonover@gmail.com>
Thu, 9 Dec 2010 22:09:26 +0000 (14:09 -0800)
29 files changed:
src/Y/class.cjs
src/Y/core.cjs
src/Y/delegate.cjs
src/Y/modules/metaclass.js
src/Y/op.cjs
src/Y/types/array.cjs
src/evt.cjs
src/ezl/layer.cjs
src/ezl/loc/boundingbox.cjs
src/ezl/math/rect.cjs
src/ezl/shape/circle.cjs
src/ezl/shape/line.cjs
src/ezl/shape/polygon.cjs
src/ezl/shape/rect.cjs
src/ezl/shape/shape.cjs
src/tanks/map/pathmap.cjs
src/tanks/map/trajectory.cjs
src/tanks/thing/player.cjs
src/tanks/thing/tank.cjs
www/commonjs.php [new file with mode: 0644]
www/index.php
www/scripts.php [new file with mode: 0644]
www/test [deleted symlink]
www/test/math/index.php [copied from test/math/index.php with 94% similarity]
www/test/math/test-math.js [moved from test/math/math.test.js with 100% similarity]
www/test/shapes/index.php [moved from test/math/index.php with 76% similarity]
www/test/shapes/test-shapes.js [new file with mode: 0644]
www/test/uki/index.php [moved from test/uki/index.php with 100% similarity]
www/test/uki/test-uki.js [moved from test/uki/test-uki.js with 100% similarity]

index 0aa02c8..2fc6520 100644 (file)
@@ -14,8 +14,11 @@ var type       = require('Y/type')
 ,   _String   = globals.String
 ,   _Number   = globals.Number
 
-,   hasOwn   = _Object.prototype.hasOwnProperty
+,   P        = 'prototype'
+,   hasOwn   = _Object[P].hasOwnProperty
 ,   getProto = _Object.getPrototypeOf
+,   getDesc  = _Object.getOwnPropertyDescriptor
+,   setDesc  = _Object.defineProperty
 
 ,   KNOWN_CLASSES = type.type.KNOWN_CLASSES
 ,   classToString = function toString(){ return this.className+"()"; }
@@ -56,7 +59,7 @@ function _Class() {
  * @param {Object} [members] Instance members to add to the new class's prototype; a class
  * constructor can be supplied as `init`.
  * 
- * @returns {Class} A new Class.
+ * @return {Class} A new Class.
  */
 function Class(className, Parent, members) {
     var ClassFactory  = arguments.callee
@@ -81,7 +84,7 @@ function Class(className, Parent, members) {
         prototype = Parent;
         
     // Parent is a constructor: check ClassFactory
-    } else if (Parent.prototype instanceof ClassFactory) {
+    } else if (Parent[P] instanceof ClassFactory) {
         SuperClass = Parent;
         prototype  = Parent.fabricate();
         
@@ -90,7 +93,7 @@ function Class(className, Parent, members) {
         return new ClassFactory(className, Parent, members);
     
     } else {
-        parentMembers = Parent.prototype || {};
+        parentMembers = Parent[P] || {};
     }
     
     // Creates a new function with the appropriate name
@@ -109,13 +112,16 @@ function Class(className, Parent, members) {
     
     // Copy parent methods, then add new instance methods
     for (var k in parentMembers)
-        prototype[k] = parentMembers[k];
+        if ( hasOwn.call(parentMembers,k) )
+            setDesc(prototype, k, getDesc(parentMembers,k));
+        else
+            prototype[k] = parentMembers[k];
     
     if ( prototype.toString === toString )
         prototype.toString = classToString;
     
     // Fix Constructors, prototypes
-    NewClass.prototype = NewClass.fn = prototype;
+    NewClass[P] = NewClass.fn = prototype;
     prototype.constructor = prototype.__class__ = NewClass;
     NewClass.__super__ = SuperClass; // don't override NewClass.constructor -- it should be Function
     NewClass.className = prototype.className = className;
@@ -127,7 +133,7 @@ function Class(className, Parent, members) {
     // Or add new instance methods
     } else for (var k in members) {
         if ( hasOwn.call(members, k) )
-            prototype[k] = members[k];
+            setDesc(prototype, k, getDesc(members,k));
     }
     
     if (prototype.init) NewClass.init = YFunction(prototype.init);
@@ -139,7 +145,7 @@ function Class(className, Parent, members) {
 
 // Add metaprogramming data to Class object
 Class.__super__ = Object;
-Class.fn = Class.prototype;
+Class.fn = Class[P];
 Class.fn.__class__ = Class;
 Class.className = Class.fn.className = "Class";
 
index 620723c..ded75cc 100644 (file)
@@ -1,10 +1,19 @@
 // Generic Collection Functions
 
 var undefined
+
 ,   globals   = (function(){ return this; })()
+,   _Object   = globals.Object
 ,   _Function = globals.Function
 ,   _Array    = globals.Array
-,   slice     = _Array.prototype.slice
+
+,   getProto = _Object.getPrototypeOf
+,   getDesc  = _Object.getOwnPropertyDescriptor
+,   setDesc  = _Object.defineProperty
+
+,   P        = 'prototype'
+,   hasOwn   = _Object[P].hasOwnProperty
+,   slice    = _Array[P].slice
 
 ,   type      = require('Y/type')
 ;
@@ -97,14 +106,41 @@ function extend( A, B ){
 function extendall(A, donor){ return reduce(donor, attrvk, A); }
 function attrvk(o, v, k){     return attr(o, k, v, o[k]); }
 
+/**
+ * Fetches the descriptor for each property that is an accessor (getter/setter).
+ * @param {Object} o Object for inspection.
+ * @return {Object} A map of property to descriptor.
+ * nb. An Array is safer, but:
+ *  1) Object.defineProperties takes an Object
+ *  2) That'd be much worse to work with
+ */
+function accessors(o){
+    if ( !(o && typeof o === "object") )
+        return {};
+    return reduce(o, function(acc, v, k, obj){
+        
+        // Ignore inherited properties
+        if ( !hasOwn.call(obj,k) )
+            return acc;
+        
+        // Only yield accessors
+        var desc = getDesc(obj,k);
+        if ( !hasOwn.call(desc,'value') )
+            acc[k] = desc;
+        
+        return acc;
+    }, {});
+}
+
 
-exports['reduce']  = reduce;
-exports['map']     = map;
-exports['forEach'] = forEach;
-exports['filter']  = filter;
+exports['reduce']    = reduce;
+exports['map']       = map;
+exports['forEach']   = forEach;
+exports['filter']    = filter;
 
-exports['set']     = set;
-exports['attr']    = attr;
-exports['extend']  = extend;
+exports['set']       = set;
+exports['attr']      = attr;
+exports['extend']    = extend;
 
-exports['slice']   = slice;
+exports['accessors'] = accessors;
+exports['slice']     = slice;
index 8bc9e64..469a1e0 100644 (file)
@@ -108,6 +108,15 @@ function extend( A, B ){
 function extendall(A, donor){ return reduce(donor, attrvk, A); }
 function attrvk(o, v, k){     return attr(o, k, v, o[k]); }
 
+function accessors(o){
+    if ( !(o && typeof o === "object") )
+        return {};
+    
+    if ( notWrapped(o.accessors) )
+        return o.accessors.apply(o, slice.call(arguments,1));
+    
+    return core.accessors(o);
+}
 
 exports['reduce']  = reduce;
 exports['map']     = map;
@@ -117,3 +126,6 @@ exports['filter']  = filter;
 exports['set']     = set;
 exports['attr']    = attr;
 exports['extend']  = extend;
+
+exports['accessors'] = accessors;
+
index 3aebbbd..d4fdc85 100644 (file)
@@ -112,7 +112,7 @@ function _Class() {
  * @param {Object} [members] Instance members to add to the new class's prototype; a class
  * constructor can be supplied as `init`.
  * 
- * @returns {Class} A new Class.
+ * @return {Class} A new Class.
  */
 function Class(className, Parent, members){
     var ClassFactory  = arguments.callee
index 3b2971c..769cab3 100644 (file)
@@ -65,7 +65,9 @@ var core = require('Y/core')
             else
                 return obj;
         };
-    }
+    },
+    
+    end : function end(o){ return ((o && o.__y__) ? o.end() : o); }
     
 };
 
index c9f11e8..0bd0b4f 100644 (file)
@@ -1,6 +1,7 @@
 var Y           = require('Y/y').Y  // I *think* this is safe
 ,   del         = require('Y/delegate')
 ,   type        = require('Y/type')
+,   op          = require('Y/op')
 ,   mixin       = require('Y/utils').mixin
 ,   YCollection = require('Y/types/collection').YCollection
 
@@ -58,9 +59,6 @@ YCollection.subclass('YArray', function(YArray){
     function concat( donor ){
         var A = this._o;
         return new YArray(A.concat.apply( A, slice.call(arguments,0).map(unwrapY) ));
-        // return new YArray( slice.call(arguments).reduce(function(A, donor ){
-        //     return A.concat(donor instanceof YArray ? donor.end() : donor);
-        // }, this._o) );
     };
     
     this['extend'] =
@@ -90,22 +88,18 @@ YCollection.subclass('YArray', function(YArray){
                     acc.push(v);
                 return acc;
             }, new YArray(), this );
-        
-        // return this.filter(function(v, i){
-        //     // Executes in the context of the new array, so
-        //     // `this.indexOf` is checking what we've already
-        //     // collected.
-        //     return (this.indexOf(v) === -1);
-        // });
     };
     
-    // this.zip =
-    // function zip(){
-    //     var sequences = new YArray(slice.call(arguments)).map( Y.limit(1) ).unshift(this);
-    //     return this.map(function(_, k){
-    //         return sequences.invoke('attr', k);
-    //     }).invoke('end');
-    // };
+    this['zip'] =
+    function zip(){
+        var sequences = new YArray(slice.call(arguments)).unshift(this._o)
+        ,   kget = op.curried.kget ;
+        return this.map(function(_, k){
+            return sequences.map(function(seq){
+                return del.attr(seq,k);
+            });
+        }); //.invoke('end');
+    };
     
     /**
      * Like map, but produces a YObject:
index 14b0090..345db7a 100644 (file)
@@ -29,9 +29,14 @@ var Y       = require('Y').Y
 
 ,   isFunction      = Y.isFunction
 ,   KNOWN_CLASSES   = Class.KNOWN_CLASSES = exports['KNOWN_CLASSES'] = {}
-,   getProto        = Object.getPrototypeOf
-,   hasOwn          = Object.prototype.hasOwnProperty
-,   objToString     = Object.prototype.toString
+
+,   P        = 'prototype'
+,   _Object  = Object
+,   hasOwn   = _Object[P].hasOwnProperty
+,   getProto = _Object.getPrototypeOf
+,   getDesc  = _Object.getOwnPropertyDescriptor
+,   setDesc  = _Object.defineProperty
+
 ,   classToString   = function toString(){ return this.className+"()"; }
 ;
 
@@ -77,7 +82,7 @@ function ConstructorTemplate() {
  * @param {Object} [members] Instance members to add to the new class's prototype; a class
  * constructor can be supplied as `init`.
  * 
- * @returns {Class} A new Class.
+ * @return {Class} A new Class.
  */
 function Class(className, Parent, members){
     var ClassFactory  = arguments.callee
@@ -133,9 +138,12 @@ function Class(className, Parent, members){
             NewClass[k] = v;
     }
     
-    // Copy parent methods
+    // Copy parent methods, then add new instance methods
     for (var k in parentMembers)
-        prototype[k] = parentMembers[k];
+        if ( hasOwn.call(parentMembers,k) )
+            setDesc(prototype, k, getDesc(parentMembers,k));
+        else
+            prototype[k] = parentMembers[k];
     
     if ( prototype.toString === objToString )
         prototype.toString = classToString;
@@ -149,7 +157,7 @@ function Class(className, Parent, members){
     
     NewClass.init = // XXX: This means subclasses will fire events.
     prototype.initialise =
-        function initialise(){
+        Y(function initialise(){
             var instance = this
             ,   init     = NewClass.prototype.init
             ;
@@ -168,7 +176,7 @@ function Class(className, Parent, members){
             });
             
             return instance;
-        };
+        });
     
     // Add class emitter
     var ParentEmitter = (Parent.__emitter__ ? Parent : ClassFactory)
@@ -182,7 +190,7 @@ function Class(className, Parent, members){
     // Or add new instance methods
     } else for (var k in members) {
         if ( hasOwn.call(members, k) )
-            prototype[k] = members[k];
+            setDesc(prototype, k, getDesc(members,k));
     }
     
     // Record for metaprogramming
@@ -215,8 +223,8 @@ Class.className = Class.fn.className = "Class";
  * Create a new instance and run delegate constructor if it exists.
  * Unlike the keyword `new`, instantiate can be applied.
  */
-function instantiate(){
-    var instance = this.fabricate();
+function instantiate(cls){
+    var instance = cls.fabricate();
     if ( instance.initialise )
         instance.initialise.apply(instance, arguments);
     return instance;
index 53f0f54..1111c0d 100644 (file)
@@ -28,8 +28,9 @@ Y.subclass('Layer', {
     ctx      : null,
     dirty    : true,
     
-    canvasWidth : 0,    layerWidth  : 0,
-    canvasHeight : 0,   layerHeight : 0,
+    
+    layerWidth  : 0,  canvasWidth : 0,
+    layerHeight : 0,  canvasHeight : 0,
     
     x: 0, y: 0, loc : null, // Position relative to parent
     
@@ -38,6 +39,7 @@ Y.subclass('Layer', {
     posBleed : null, // Loc
     
     // Transforms
+    _origin : null, // rotational origin
     transform : null, // Object
     useCanvasScaling : false, // default to CSS3 scaling
     
@@ -53,8 +55,8 @@ Y.subclass('Layer', {
         
         this.boundingBox = new BoundingBox(0,0, 0,0);
         
+        this._origin = new Loc('50%','50%');
         this.transform = {
-            origin    : new Loc('50%','50%'), // rotational origin
             rotate    : 0,
             scale     : new Loc(1.0,1.0),
             translate : new Loc(0,0) // translates canvas
@@ -120,7 +122,7 @@ Y.subclass('Layer', {
     },
     
     /**
-     * @returns The root of the scene graph.
+     * @return The root of the scene graph.
      */
     root : function root(){
         if (this.parent)
@@ -135,17 +137,7 @@ Y.subclass('Layer', {
     
     /// Attributes ///
     
-    
-    attr : function attr(key, value, def){
-        if (!key) return this;
-        
-        if ( Y.isPlainObject(key) ) {
-            for (var k in key)
-                this.attr(k, key[k]);
-            return this;
-        } else
-            return Y.op.attr(this, key, value, def);
-    },
+    attr : Y.attr.methodize(),
     
     /**
      * Changes the layer's width and then updates the canvas.
@@ -155,16 +147,19 @@ Y.subclass('Layer', {
             return this.layerWidth;
         
         this.layerWidth = w;
+        
+        var origin = this._origin
+        ,   nb = this.negBleed
+        ,   v  = this.canvasWidth = Math.ceil(w + nb.x + this.posBleed.x); // HTMLCanvas.width is a long
+        
         this.boundingBox = this.boundingBox.resize(w, this.layerHeight);
+        this.layer.width(w).css('margin-left', (-nb.x)+'px')
         
-        var nb = this.negBleed.x
-        ,   v  = this.canvasWidth = Math.ceil(w + nb + this.posBleed.x);
-        this.layer.width(w).css('margin-left', (-nb)+'px')
-        this.canvas.width(v);
-        // this.canvas.css({
-        //     'width' : v+'px',
-        //     'margin-left' : (-nb)+'px'
-        // });
+        // this.canvas.width(v);
+        this.canvas.css({
+            'width' : v+'px',
+            'margin-left' : (-nb)+'px'
+        });
         this.canvas[0].width = v;
         
         
@@ -176,10 +171,10 @@ Y.subclass('Layer', {
             return this.layerHeight;
         
         this.layerHeight = h;
-        this.boundingBox = this.boundingBox.resize(this.layerWidth, h);
+        this.boundingBox =  this.boundingBox.resize(this.layerWidth, h);
         
         var nb = this.negBleed.y
-        ,   v  = this.canvasHeight = Math.ceil(h + nb + this.posBleed.y);
+        ,   v  = this.canvasHeight = Math.ceil(h + nb + this.posBleed.y); // HTMLCanvas.height is a long
         this.layer.height(h).css('margin-top', (-nb)+'px')
         this.canvas.height(v);
         // this.canvas.css({
@@ -192,35 +187,45 @@ Y.subclass('Layer', {
     },
     
     /**
-     * position() -> object 
+     * position() -> {Loc}
      * Gets position of the layer relative to the parent.
+     * @return {Loc}
      */
     /**
-     * position(top, left) -> this
+     * position(x,y) -> {this}
      * Sets the position of this node, and then returns it.
-     * @param {Number|String|undefined} top If omitted, this method must be invoked with `undefined` as the first argument.
-     * @param {Number|String|undefined} left
+     * @param {Number|String|undefined} x
+     * @param {Number|String|undefined} y If omitted, this method must be invoked with `undefined` as the first argument.
+     * @return {this}
      */
     /**
-     * position(pos) -> this
+     * position(pos) -> {this}
      * Sets the position of this node, and then returns it.
-     * @param {Object} pos An object with "top" and/or "left" properties as in `position(top, left)`.
+     * @param {Object} pos An object with "x" and/or "y" properties as in `position(x,y)`.
+     * @return {this}
      */
-    position : function position(left, top){
-        if (top === undefined && left === undefined)
+    position : function position(x,y){
+        if (x === undefined && y === undefined)
             return this.layer.position();
         
-        if (top && Y.isPlainObject(top))
-            var pos = top;
-        else
-            var pos = { 'top': top, 'left':left };
+        if ( Y.isPlainObject(x) ){
+            y = x.y;
+            x = x.x;
+        }
+        
+        // if (pos.x !== undefined)  pos.x -= this.offsetX;
+        // if (pos.y !== undefined)  pos.y -= this.offsetY;
         
-        // if (pos.left !== undefined)  pos.left -= this.offsetX;
-        // if (pos.top  !== undefined)  pos.top  -= this.offsetY;
+        this.boundingBox = this.boundingBox.relocate(x,y);
+        this.loc = this.boundingBox.midpoint();
         
-        this.boundingBox = this.boundingBox.add(pos.left,pos.top);
-        this.loc = this.boundingBox.p1;
-        this.css(pos);
+        var origin = this.origin();
+        this.css({ 
+            'left'        : x,
+            'top'         : y,
+            'margin-left' : -origin.x,
+            'margin-top'  : -origin.y
+        });
         return this;
     },
     
@@ -259,10 +264,11 @@ Y.subclass('Layer', {
     /// Transformations ///
     
     /**
-     * Gets and sets the transformation origin.
+     * Gets and sets the origin-location for this shape, used for 
+     * position and rotation. Defaults to the midpoint.
      */
     origin : function origin(x,y){
-        var o = this.transform.origin;
+        var o = this._origin;
         if (arguments.length === 0)
             return o.absolute(this.layerWidth, this.layerHeight);
         
@@ -323,15 +329,16 @@ Y.subclass('Layer', {
             tfns.push('scale('+t.scale.x+','+t.scale.y+')');
         
         var trans = (tfns.length ? tfns.join(' ') : 'none')
-        ,   o = t.origin.toUnits()
+        ,   o = this._origin.toUnits('px')
         ,   origin = o.x+' '+o.y ;
-        this.layer.css(
-            ['', '-moz-', '-webkit-'].reduce(
+        this.layer.css(['', '-moz-', '-webkit-']
+            .reduce(
                 function(values, prefix){
                     values[prefix+'transform'] = trans;
                     values[prefix+'transform-origin'] = origin;
                     return values;
-                }, {}) );
+                },
+                {}) );
         return this;
     },
     
@@ -482,8 +489,8 @@ Y.subclass('Layer', {
     
     /// Misc ///
     toString : function toString(){
-        var pos = (this.layer ? this.position() : {top:NaN, left:NaN});
-        return this.className+'['+pos.left+','+pos.top+']( children='+this.children.size()+' )';
+        var pos = (this.layer ? this.position() : {y:NaN, x:NaN});
+        return this.className+'['+pos.x+','+pos.y+']( children='+this.children.size()+' )';
     }
 });
 
index f7ae7d5..7e17ea2 100644 (file)
@@ -8,67 +8,20 @@ var Y = require('Y').Y
 BoundingBox =
 exports['BoundingBox'] =
 Rect.subclass('BoundingBox', {
-    init : function initBoundingBox(x1,y1, x2,y2){
-        Rect.init.call(this, x1,y1, x2,y2);
-        
-        this.sides = {
-            top    : new Line(x1,y1, x2,y1),
-            bottom : new Line(x1,y2, x2,y2),
-            left   : new Line(x1,y1, x1,y2),
-            right  : new Line(x2,y1, x2,y2)
-        };
-    },
-    
-    set : function set(k, v, def){
-        v = (v !== undefined ? v : def);
-        
-        switch (k) {
-            case 'x1': case 0: case 'x':    this.x1 = this[0] = this.x = v;     break;
-            case 'y1': case 1: case 'y':    this.y1 = this[1] = this.y = v;     break;
-            case 'x2': case 2:              this.x2 = this[2] = v;              break;
-            case 'y1': case 3:              this.y2 = this[3] = v;              break;
-            
-            default: this[k] = v;
-        }
-        
-        this.width  = this.x2 - this.x1;
-        this.height = this.y2 - this.y1;
-        
-        return this._updateSides();
-    },
-    
-    _updateSides : function _updateSides(){
-        var s = this.sides
-        ,   x1 = this.x1,           y1 = this.y1
-        ,   x2 = this.x2,           y2 = this.y2
-        ,   dx1 = x1 !== s.top.x1,  dy1 = y1 !== s.top.y1
-        ,   dx2 = x2 !== s.top.x2,  dy2 = y2 !== s.left.y2
-        ;
-        
-        if ( dx1 || dy1 ) this.p1 = new Vec(x1,y1);
-        if ( dx2 || dy2 ) this.p2 = new Vec(x2,y2);
-        
-        if ( dx1 || dy1 || dx2 ) s.top    = new Line(x1,y1, x2,y1);
-        if ( dx1 || dx2 || dy2 ) s.bottom = new Line(x1,y2, x2,y2);
-        if ( dx1 || dy1 || dy2 ) s.left   = new Line(x1,y1, x1,y2);
-        if ( dy1 || dy2 || dx2 ) s.right  = new Line(x2,y1, x2,y2);
-        
-        return this;
-    },
     
     attr : Y.attr.methodize(),
     
-    add : function add(x,y){
+    re