Browse Source

Fixed a bug in ClassTreeInfo initialization when Abstract classes are involved

CachedGroup/Sprite2DRender synchronization on pos/rot/scl change
https://trello.com/c/khQ9jdhI

Shape2D abstract class
https://trello.com/c/lWa7IsPH

Transparency Support in Primirives
https://trello.com/c/tzrPom9s
nockawa 9 years ago
parent
commit
cc39de049d

+ 12 - 21
src/Canvas2d/babylon.canvas2d.ts

@@ -1,12 +1,4 @@
 module BABYLON {
 module BABYLON {
-    class GroupsCacheMap {
-        constructor() {
-            this.groupSprites = new Array<{ group: Group2D, sprite: Sprite2D }>();
-        }
-        texture: MapTexture;
-        groupSprites: Array<{ group: Group2D, sprite: Sprite2D }>;
-    }
-
     @className("Canvas2D")
     @className("Canvas2D")
     export class Canvas2D extends Group2D {
     export class Canvas2D extends Group2D {
         /**
         /**
@@ -189,7 +181,7 @@
         private _hierarchyLevelZFactor: number;
         private _hierarchyLevelZFactor: number;
         private _hierarchyLevelMaxSiblingCount: number;
         private _hierarchyLevelMaxSiblingCount: number;
         private _hierarchySiblingZDelta: number;
         private _hierarchySiblingZDelta: number;
-        private _groupCacheMaps: GroupsCacheMap[];
+        private _groupCacheMaps: MapTexture[];
         public _renderingSize: Size;
         public _renderingSize: Size;
 
 
         /**
         /**
@@ -219,20 +211,20 @@
          * @param group The group to allocate the cache of.
          * @param group The group to allocate the cache of.
          * @return custom type with the PackedRect instance giving information about the cache location into the texture and also the MapTexture instance that stores the cache.
          * @return custom type with the PackedRect instance giving information about the cache location into the texture and also the MapTexture instance that stores the cache.
          */
          */
-        public _allocateGroupCache(group: Group2D): { node: PackedRect, texture: MapTexture } {
+        public _allocateGroupCache(group: Group2D): { node: PackedRect, texture: MapTexture, sprite: Sprite2D } {
             // Determine size
             // Determine size
             let size = group.actualSize;
             let size = group.actualSize;
             size = new Size(Math.ceil(size.width), Math.ceil(size.height));
             size = new Size(Math.ceil(size.width), Math.ceil(size.height));
             if (!this._groupCacheMaps) {
             if (!this._groupCacheMaps) {
-                this._groupCacheMaps = new Array<GroupsCacheMap>();
+                this._groupCacheMaps = new Array<MapTexture>();
             }
             }
 
 
             // Try to find a spot in one of the cached texture
             // Try to find a spot in one of the cached texture
             let res = null;
             let res = null;
-            for (var g of this._groupCacheMaps) {
-                let node = g.texture.allocateRect(size);
+            for (var map of this._groupCacheMaps) {
+                let node = map.allocateRect(size);
                 if (node) {
                 if (node) {
-                    res = { node: node, texture: g.texture }
+                    res = { node: node, texture: map }
                     break;
                     break;
                 }
                 }
             }
             }
@@ -247,19 +239,18 @@
                     mapSize.height = Math.pow(2, Math.ceil(Math.log(size.height) / Math.log(2)));
                     mapSize.height = Math.pow(2, Math.ceil(Math.log(size.height) / Math.log(2)));
                 }
                 }
 
 
-                g = new GroupsCacheMap();
                 let id = `groupsMapChache${this._mapCounter}forCanvas${this.id}`;
                 let id = `groupsMapChache${this._mapCounter}forCanvas${this.id}`;
-                g.texture = new MapTexture(id, this._scene, mapSize);
-                this._groupCacheMaps.push(g);
+                map = new MapTexture(id, this._scene, mapSize);
+                this._groupCacheMaps.push(map);
 
 
-                let node = g.texture.allocateRect(size);
-                res = { node: node, texture: g.texture }
+                let node = map.allocateRect(size);
+                res = { node: node, texture: map }
             }
             }
 
 
             // Create a Sprite that will be used to render this cache, the "__cachedSpriteOfGroup__" starting id is a hack to bypass exception throwing in case of the Canvas doesn't normally allows direct primitives
             // Create a Sprite that will be used to render this cache, the "__cachedSpriteOfGroup__" starting id is a hack to bypass exception throwing in case of the Canvas doesn't normally allows direct primitives
-            let sprite = Sprite2D.Create(this, `__cachedSpriteOfGroup__${group.id}`, 10, 10, g.texture, res.node.contentSize, res.node.pos, true);
+            let sprite = Sprite2D.Create(this, `__cachedSpriteOfGroup__${group.id}`, group.position.x, group.position.y, map, res.node.contentSize, res.node.pos, true);
             sprite.origin = Vector2.Zero();
             sprite.origin = Vector2.Zero();
-            g.groupSprites.push({ group: group, sprite: sprite });
+            res.sprite = sprite;
             return res;
             return res;
         }
         }
 
 

+ 25 - 8
src/Canvas2d/babylon.group2d.ts

@@ -1,9 +1,12 @@
 module BABYLON {
 module BABYLON {
     @className("Group2D")
     @className("Group2D")
     export class Group2D extends Prim2DBase {
     export class Group2D extends Prim2DBase {
-        static GROUP2D_PROPCOUNT: number = Prim2DBase.PRIM2DBASE_PROPCOUNT + 10;
+        static GROUP2D_PROPCOUNT: number = Prim2DBase.PRIM2DBASE_PROPCOUNT + 5;
 
 
-        /**
+        public static sizeProperty: Prim2DPropInfo;
+        public static actualSizeProperty: Prim2DPropInfo;
+
+      /**
          * Default behavior, the group will use the caching strategy defined at the Canvas Level
          * Default behavior, the group will use the caching strategy defined at the Canvas Level
          */
          */
         public static GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY = 0;
         public static GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY = 0;
@@ -65,10 +68,6 @@
             return this._isCachedGroup;
             return this._isCachedGroup;
         }
         }
 
 
-        public static sizeProperty: Prim2DPropInfo;
-        public static actualSizeProperty: Prim2DPropInfo;
-
-
         @instanceLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, pi => Group2D.sizeProperty = pi, false, true)
         @instanceLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, pi => Group2D.sizeProperty = pi, false, true)
         public get size(): Size {
         public get size(): Size {
             return this._size;
             return this._size;
@@ -99,7 +98,7 @@
             return this._cacheBehavior;
             return this._cacheBehavior;
         }
         }
 
 
-        _addPrimToDirtyList(prim: Prim2DBase) {
+        public _addPrimToDirtyList(prim: Prim2DBase) {
             this._primDirtyList.push(prim);
             this._primDirtyList.push(prim);
         }
         }
 
 
@@ -132,7 +131,6 @@
                 this.updateGlobalTransVisOf(sortedDirtyList, childrenContext, true);
                 this.updateGlobalTransVisOf(sortedDirtyList, childrenContext, true);
             }
             }
 
 
-
             // Setup the size of the rendering viewport
             // Setup the size of the rendering viewport
             // In non cache mode, we're rendering directly to the rendering canvas, in this case we have to detect if the canvas size changed since the previous iteration, if it's the case all primitives must be preprared again because their transformation must be recompute
             // In non cache mode, we're rendering directly to the rendering canvas, in this case we have to detect if the canvas size changed since the previous iteration, if it's the case all primitives must be preprared again because their transformation must be recompute
             if (!this._isCachedGroup) {
             if (!this._isCachedGroup) {
@@ -272,6 +270,7 @@
                 var res = this.owner._allocateGroupCache(this);
                 var res = this.owner._allocateGroupCache(this);
                 this._cacheNode = res.node;
                 this._cacheNode = res.node;
                 this._cacheTexture = res.texture;
                 this._cacheTexture = res.texture;
+                this._cacheRenderSprite = res.sprite;
             }
             }
 
 
             let n = this._cacheNode;
             let n = this._cacheNode;
@@ -284,6 +283,23 @@
             }
             }
         }
         }
 
 
+        protected handleGroupChanged(prop: Prim2DPropInfo) {
+            // This method is only for cachedGroup
+            if (!this.isCachedGroup || !this._cacheRenderSprite) {
+                return;
+            }
+
+            // For now we only support these property changes
+            // TODO: add more! :)
+            if (prop.id === Prim2DBase.positionProperty.id) {
+                this._cacheRenderSprite.position = this.position.clone();
+            } else if (prop.id === Prim2DBase.rotationProperty.id) {
+                this._cacheRenderSprite.rotation = this.rotation;
+            } else if (prop.id === Prim2DBase.scaleProperty.id) {
+                this._cacheRenderSprite.scale = this.scale;
+            }
+        }
+
         private detectGroupStates() {
         private detectGroupStates() {
             var isCanvas = this instanceof Canvas2D;
             var isCanvas = this instanceof Canvas2D;
             var canvasStrat = this.owner.cachingStrategy;
             var canvasStrat = this.owner.cachingStrategy;
@@ -357,6 +373,7 @@
         private _primDirtyList: Array<Prim2DBase>;
         private _primDirtyList: Array<Prim2DBase>;
         private _cacheNode: PackedRect;
         private _cacheNode: PackedRect;
         private _cacheTexture: MapTexture;
         private _cacheTexture: MapTexture;
+        private _cacheRenderSprite: Sprite2D;
         private _viewportPosition: Vector2;
         private _viewportPosition: Vector2;
         private _viewportSize: Size;
         private _viewportSize: Size;
 
 

+ 0 - 8
src/Canvas2d/babylon.prim2dBase.ts

@@ -219,12 +219,6 @@
 
 
         protected onPrimBecomesDirty() {
         protected onPrimBecomesDirty() {
             if (this._renderGroup) {
             if (this._renderGroup) {
-                //if (this instanceof Group2D) {
-                //    var group: any= this;
-                //    if (group.isRenderableGroup) {
-                //        return;
-                //    }
-                //}
                 this._renderGroup._addPrimToDirtyList(this);
                 this._renderGroup._addPrimToDirtyList(this);
             }
             }
         }
         }
@@ -288,7 +282,6 @@
             }
             }
         }
         }
 
 
-
         protected updateGlobalTransVisOf(list: Prim2DBase[], context: Render2DContext, recurse: boolean) {
         protected updateGlobalTransVisOf(list: Prim2DBase[], context: Render2DContext, recurse: boolean) {
             for (let cur of list) {
             for (let cur of list) {
                 cur.updateGlobalTransVis(context, recurse);
                 cur.updateGlobalTransVis(context, recurse);
@@ -296,7 +289,6 @@
         }
         }
 
 
         protected updateGlobalTransVis(context: Render2DContext, recurse: boolean) {
         protected updateGlobalTransVis(context: Render2DContext, recurse: boolean) {
-
             this._globalTransformPreviousStep = this._globalTransformStep;
             this._globalTransformPreviousStep = this._globalTransformStep;
             this.isVisible = context.parentVisibleState && this.levelVisible;
             this.isVisible = context.parentVisibleState && this.levelVisible;
 
 

+ 4 - 4
src/Canvas2d/babylon.rectangle2d.ts

@@ -41,13 +41,13 @@
     }
     }
 
 
     @className("Rectangle2D")
     @className("Rectangle2D")
-    export class Rectangle2D extends RenderablePrim2D<Rectangle2DInstanceData> {
+    export class Rectangle2D extends Shape2D<Rectangle2DInstanceData> {
 
 
         public static sizeProperty: Prim2DPropInfo;
         public static sizeProperty: Prim2DPropInfo;
         public static notRoundedProperty: Prim2DPropInfo;
         public static notRoundedProperty: Prim2DPropInfo;
         public static roundRadiusProperty: Prim2DPropInfo;
         public static roundRadiusProperty: Prim2DPropInfo;
 
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, pi => Rectangle2D.sizeProperty = pi, false, true)
+        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 1, pi => Rectangle2D.sizeProperty = pi, false, true)
         public get size(): Size {
         public get size(): Size {
             return this._size;
             return this._size;
         }
         }
@@ -56,7 +56,7 @@
             this._size = value;
             this._size = value;
         }
         }
 
 
-        @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, pi => Rectangle2D.notRoundedProperty = pi)
+        @modelLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 2, pi => Rectangle2D.notRoundedProperty = pi)
         public get notRounded(): boolean {
         public get notRounded(): boolean {
             return this._notRounded;
             return this._notRounded;
         }
         }
@@ -65,7 +65,7 @@
             this._notRounded = value;
             this._notRounded = value;
         }
         }
 
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Rectangle2D.roundRadiusProperty = pi)
+        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 3, pi => Rectangle2D.roundRadiusProperty = pi)
         public get roundRadius(): number {
         public get roundRadius(): number {
             return this._roundRadius;
             return this._roundRadius;
         }
         }

+ 6 - 33
src/Canvas2d/babylon.renderablePrim2d.ts

@@ -213,42 +213,13 @@
 
 
     @className("RenderablePrim2D")
     @className("RenderablePrim2D")
     export class RenderablePrim2D<TInstData extends InstanceDataBase> extends Prim2DBase {
     export class RenderablePrim2D<TInstData extends InstanceDataBase> extends Prim2DBase {
-        static RENDERABLEPRIM2D_PROPCOUNT: number = Prim2DBase.PRIM2DBASE_PROPCOUNT + 10;
-
-        public static borderProperty: Prim2DPropInfo;
-        public static fillProperty: Prim2DPropInfo;
+        static RENDERABLEPRIM2D_PROPCOUNT: number = Prim2DBase.PRIM2DBASE_PROPCOUNT + 5;
 
 
         setupRenderablePrim2D(owner: Canvas2D, parent: Prim2DBase, id: string, position: Vector2, isVisible: boolean, fill: IFill2D, border: IBorder2D) {
         setupRenderablePrim2D(owner: Canvas2D, parent: Prim2DBase, id: string, position: Vector2, isVisible: boolean, fill: IFill2D, border: IBorder2D) {
             this.setupPrim2DBase(owner, parent, id, position);
             this.setupPrim2DBase(owner, parent, id, position);
             this._isTransparent = false;
             this._isTransparent = false;
         }
         }
 
 
-        @modelLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, pi => RenderablePrim2D.borderProperty = pi, true)
-        public get border(): IBorder2D {
-            return this._border;
-        }
-
-        public set border(value: IBorder2D) {
-            if (value === this._border) {
-                return;
-            }
-
-            this._border = value;
-        }
-
-        @modelLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 2, pi => RenderablePrim2D.fillProperty = pi, true)
-        public get fill(): IFill2D {
-            return this._fill;
-        }
-
-        public set fill(value: IBorder2D) {
-            if (value === this._fill) {
-                return;
-            }
-
-            this._fill = value;
-        }
-
         public _prepareRenderPre(context: Render2DContext) {
         public _prepareRenderPre(context: Render2DContext) {
             super._prepareRenderPre(context);
             super._prepareRenderPre(context);
 
 
@@ -323,6 +294,10 @@
             }
             }
         }
         }
 
 
+        public get isTransparent(): boolean {
+            return this._isTransparent;
+        }
+
         protected createModelRenderCache(): ModelRenderCache<TInstData> {
         protected createModelRenderCache(): ModelRenderCache<TInstData> {
             return null;
             return null;
         }
         }
@@ -367,9 +342,7 @@
         private _modelRenderInstanceID: string;
         private _modelRenderInstanceID: string;
 
 
         protected _instanceData: TInstData;
         protected _instanceData: TInstData;
-        private _border: IBorder2D;
-        private _fill: IFill2D;
-        private _isTransparent: boolean;
+        protected _isTransparent: boolean;
     }
     }
 
 
 
 

+ 39 - 0
src/Canvas2d/babylon.shape2d.ts

@@ -0,0 +1,39 @@
+module BABYLON {
+    @className("Shape2D")
+    export class Shape2D<TInstData extends InstanceDataBase> extends RenderablePrim2D<TInstData> {
+        static SHAPE2D_PROPCOUNT: number = RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5;
+        public static borderProperty: Prim2DPropInfo;
+        public static fillProperty: Prim2DPropInfo;
+
+        @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, pi => Shape2D.borderProperty = pi, true)
+        public get border(): IBorder2D {
+            return this._border;
+        }
+
+        public set border(value: IBorder2D) {
+            if (value === this._border) {
+                return;
+            }
+
+            this._border = value;
+        }
+
+        @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, pi => Shape2D.fillProperty = pi, true)
+        public get fill(): IFill2D {
+            return this._fill;
+        }
+
+        public set fill(value: IBorder2D) {
+            if (value === this._fill) {
+                return;
+            }
+
+            this._fill = value;
+        }
+
+        private _border: IBorder2D;
+        private _fill: IFill2D;
+    }
+
+
+}

+ 20 - 11
src/Canvas2d/babylon.smartPropertyPrim.ts

@@ -72,16 +72,12 @@
             }
             }
 
 
             let baseProto = Object.getPrototypeOf(type);
             let baseProto = Object.getPrototypeOf(type);
-            return this.getOrAddType(baseProto, type);
-
-            //// If type is a class, this will get the base class proto, if type is an instance of a class, this will get the proto of the class
-            //let baseTypeName = Tools.getClassName(baseProto);
+            let curProtoContent = this.getOrAddType(Object.getPrototypeOf(baseProto), baseProto);
+            if (!curProtoContent) {
+                this.getLevelOf(baseProto);
+            }
 
 
-            //// If both name are equal we only switch from instance to class, we need to get the next proto in the hierarchy to get the base class
-            //if (baseTypeName === typeName) {
-            //    baseTypeName = Tools.getClassName(Object.getPrototypeOf(baseProto));
-            //}
-            //return this.getOrAddType(baseTypeName, typeName);
+            return this.getOrAddType(baseProto, type);
         }
         }
 
 
         getOrAddType(baseType: Object, type: Object): ClassTreeInfo<TClass, TProp> {
         getOrAddType(baseType: Object, type: Object): ClassTreeInfo<TClass, TProp> {
@@ -175,6 +171,10 @@
             return modelKey;
             return modelKey;
         }
         }
 
 
+        public get isDirty(): boolean {
+            return (this._instanceDirtyFlags !== 0) || this._modelDirty;
+        }
+
         protected static GetOrAddModelCache<TInstData>(key: string, factory: (key: string) => ModelRenderCache<TInstData>): ModelRenderCache<TInstData> {
         protected static GetOrAddModelCache<TInstData>(key: string, factory: (key: string) => ModelRenderCache<TInstData>): ModelRenderCache<TInstData> {
             return <ModelRenderCache<TInstData>>SmartPropertyPrim.ModelCache.getOrAddWithFactory(key, factory);
             return <ModelRenderCache<TInstData>>SmartPropertyPrim.ModelCache.getOrAddWithFactory(key, factory);
         }
         }
@@ -248,6 +248,11 @@
             let propMask = propInfo.flagId;
             let propMask = propInfo.flagId;
             this.propertyChanged.notifyObservers(info, propMask);
             this.propertyChanged.notifyObservers(info, propMask);
 
 
+            // If the property belong to a group, check if it's a cached one, and dirty its render sprite accordingly
+            if (this instanceof Group2D) {
+                this.handleGroupChanged(propInfo);
+            }
+
             // Check if we need to dirty only if the type change and make the test
             // Check if we need to dirty only if the type change and make the test
             var skipDirty = false;
             var skipDirty = false;
             if (typeLevelCompare && curValue != null && newValue != null) {
             if (typeLevelCompare && curValue != null && newValue != null) {
@@ -260,12 +265,12 @@
             // Set the dirty flags
             // Set the dirty flags
             if (!skipDirty) {
             if (!skipDirty) {
                 if (propInfo.kind === Prim2DPropInfo.PROPKIND_MODEL) {
                 if (propInfo.kind === Prim2DPropInfo.PROPKIND_MODEL) {
-                    if ((this._instanceDirtyFlags === 0) && (!this._modelDirty)) {
+                    if (!this.isDirty) {
                         this.onPrimBecomesDirty();
                         this.onPrimBecomesDirty();
                     }
                     }
                     this._modelDirty = true;
                     this._modelDirty = true;
                 } else if (propInfo.kind === Prim2DPropInfo.PROPKIND_INSTANCE) {
                 } else if (propInfo.kind === Prim2DPropInfo.PROPKIND_INSTANCE) {
-                    if ((this._instanceDirtyFlags === 0) && (!this._modelDirty)) {
+                    if (!this.isDirty) {
                         this.onPrimBecomesDirty();
                         this.onPrimBecomesDirty();
                     }
                     }
                     this._instanceDirtyFlags |= propMask;
                     this._instanceDirtyFlags |= propMask;
@@ -273,6 +278,10 @@
             }
             }
         }
         }
 
 
+        protected handleGroupChanged(prop: Prim2DPropInfo) {
+
+        }
+
         public checkPropertiesDirty(flags: number): boolean {
         public checkPropertiesDirty(flags: number): boolean {
             return (this._instanceDirtyFlags & flags) !== 0;
             return (this._instanceDirtyFlags & flags) !== 0;
         }
         }

+ 10 - 7
src/Canvas2d/babylon.sprite2d.ts

@@ -26,8 +26,10 @@
             engine.bindBuffers(this.vb, this.ib, [1], 4, this.effect);
             engine.bindBuffers(this.vb, this.ib, [1], 4, this.effect);
 
 
             engine.updateAndBindInstancesBuffer(instanceInfo._instancesBuffer, null, this.instancingAttributes);
             engine.updateAndBindInstancesBuffer(instanceInfo._instancesBuffer, null, this.instancingAttributes);
-
+            var cur = engine.getAlphaMode();
+            engine.setAlphaMode(Engine.ALPHA_COMBINE);
             engine.draw(true, 0, 6, instanceInfo._instancesData.usedElementCount);
             engine.draw(true, 0, 6, instanceInfo._instancesData.usedElementCount);
+            engine.setAlphaMode(cur);
 
 
             engine.unBindInstancesBuffer(instanceInfo._instancesBuffer, this.instancingAttributes);
             engine.unBindInstancesBuffer(instanceInfo._instancesBuffer, this.instancingAttributes);
 
 
@@ -63,7 +65,7 @@
     }
     }
 
 
     @className("Sprite2D")
     @className("Sprite2D")
-    export class Sprite2D extends RenderablePrim2D<Sprite2DInstanceData> {
+    export class Sprite2D extends Shape2D<Sprite2DInstanceData> {
 
 
         public static textureProperty: Prim2DPropInfo;
         public static textureProperty: Prim2DPropInfo;
         public static spriteSizeProperty: Prim2DPropInfo;
         public static spriteSizeProperty: Prim2DPropInfo;
@@ -71,7 +73,7 @@
         public static spriteFrameProperty: Prim2DPropInfo;
         public static spriteFrameProperty: Prim2DPropInfo;
         public static invertYProperty: Prim2DPropInfo;
         public static invertYProperty: Prim2DPropInfo;
 
 
-        @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, pi => Sprite2D.textureProperty = pi)
+        @modelLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 1, pi => Sprite2D.textureProperty = pi)
         public get texture(): Texture {
         public get texture(): Texture {
             return this._texture;
             return this._texture;
         }
         }
@@ -80,7 +82,7 @@
             this._texture = value;
             this._texture = value;
         }
         }
 
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, pi => Sprite2D.spriteSizeProperty = pi, false, true)
+        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 2, pi => Sprite2D.spriteSizeProperty = pi, false, true)
         public get spriteSize(): Size {
         public get spriteSize(): Size {
             return this._size;
             return this._size;
         }
         }
@@ -89,7 +91,7 @@
             this._size = value;
             this._size = value;
         }
         }
 
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Sprite2D.spriteLocationProperty = pi)
+        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 3, pi => Sprite2D.spriteLocationProperty = pi)
         public get spriteLocation(): Vector2 {
         public get spriteLocation(): Vector2 {
             return this._location;
             return this._location;
         }
         }
@@ -98,7 +100,7 @@
             this._location = value;
             this._location = value;
         }
         }
 
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, pi => Sprite2D.spriteFrameProperty = pi)
+        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 4, pi => Sprite2D.spriteFrameProperty = pi)
         public get spriteFrame(): number {
         public get spriteFrame(): number {
             return this._spriteFrame;
             return this._spriteFrame;
         }
         }
@@ -107,7 +109,7 @@
             this._spriteFrame = value;
             this._spriteFrame = value;
         }
         }
 
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5, pi => Sprite2D.invertYProperty = pi)
+        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 5, pi => Sprite2D.invertYProperty = pi)
         public get invertY(): boolean {
         public get invertY(): boolean {
             return this._invertY;
             return this._invertY;
         }
         }
@@ -128,6 +130,7 @@
             this.spriteLocation = spriteLocation;
             this.spriteLocation = spriteLocation;
             this.spriteFrame = 0;
             this.spriteFrame = 0;
             this.invertY = invertY;
             this.invertY = invertY;
+            this._isTransparent = true;
         }
         }
 
 
         public static Create(parent: Prim2DBase, id: string, x: number, y: number, texture: Texture, spriteSize: Size, spriteLocation: Vector2, invertY: boolean = false): Sprite2D {
         public static Create(parent: Prim2DBase, id: string, x: number, y: number, texture: Texture, spriteSize: Size, spriteLocation: Vector2, invertY: boolean = false): Sprite2D {