Browse Source

Canvas2D: big refactoring of the Positioning Engine!

 - AutoSize is now supposed to work as expected
 - AutoSize can be set on only Width or Height with a fixed size for the other dimension
 - All prim can be constructed with a padding being a number (which will be applied to top, left, right and bottom)
 - Many little bugs fixes

Hopefully not too much regressions...cross fingers!
nockawa 8 years ago
parent
commit
6ecac0cec7

+ 7 - 0
canvas2D/src/Engine/babylon.bounding2d.ts

@@ -153,6 +153,13 @@
             this._worldAABBDirty = true;
         }
 
+        public equals(other: BoundingInfo2D): boolean {
+            if (!other) {
+                return false;
+            }
+            return other.center.equals(this.center) && other.extent.equals(this.extent);
+        }
+
         /**
          * return the max extend of the bounding info
          */

+ 64 - 35
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -87,18 +87,19 @@
         }) {
             super(settings);
 
-            this._drawCallsOpaqueCounter       = new PerfCounter();
-            this._drawCallsAlphaTestCounter    = new PerfCounter();
-            this._drawCallsTransparentCounter  = new PerfCounter();
-            this._groupRenderCounter           = new PerfCounter();
-            this._updateTransparentDataCounter = new PerfCounter();
-            this._cachedGroupRenderCounter     = new PerfCounter();
-            this._updateCachedStateCounter     = new PerfCounter();
-            this._updateLayoutCounter          = new PerfCounter();
-            this._updatePositioningCounter     = new PerfCounter();
-            this._updateLocalTransformCounter  = new PerfCounter();
-            this._updateGlobalTransformCounter = new PerfCounter();
-            this._boundingInfoRecomputeCounter = new PerfCounter();
+            this._drawCallsOpaqueCounter          = new PerfCounter();
+            this._drawCallsAlphaTestCounter       = new PerfCounter();
+            this._drawCallsTransparentCounter     = new PerfCounter();
+            this._groupRenderCounter              = new PerfCounter();
+            this._updateTransparentDataCounter    = new PerfCounter();
+            this._cachedGroupRenderCounter        = new PerfCounter();
+            this._updateCachedStateCounter        = new PerfCounter();
+            this._updateLayoutCounter             = new PerfCounter();
+            this._updatePositioningCounter        = new PerfCounter();
+            this._updateLocalTransformCounter     = new PerfCounter();
+            this._updateGlobalTransformCounter    = new PerfCounter();
+            this._boundingInfoRecomputeCounter    = new PerfCounter();
+            this._layoutBoundingInfoUpdateCounter = new PerfCounter();
 
             this._cachedCanvasGroup = null;
 
@@ -276,6 +277,10 @@
             return this._boundingInfoRecomputeCounter;
         }
 
+        public get layoutBoundingInfoUpdateCounter(): PerfCounter {
+            return this._layoutBoundingInfoUpdateCounter;
+        }
+
         public static get instances() : Array<Canvas2D> {
             return Canvas2D._INSTANCES;
         }
@@ -1134,6 +1139,7 @@
             this._updateLocalTransformCounter.fetchNewFrame();
             this._updateGlobalTransformCounter.fetchNewFrame();
             this._boundingInfoRecomputeCounter.fetchNewFrame();
+            this._layoutBoundingInfoUpdateCounter.fetchNewFrame();
         }
 
         private _fetchPerfMetrics() {
@@ -1149,6 +1155,7 @@
             this._updateLocalTransformCounter.addCount(0, true);
             this._updateGlobalTransformCounter.addCount(0, true);
             this._boundingInfoRecomputeCounter.addCount(0, true);
+            this._layoutBoundingInfoUpdateCounter.addCount(0, true);
         }
 
         private _updateProfileCanvas() {
@@ -1170,7 +1177,8 @@
                     ` - Update Positioning: ${this.updatePositioningCounter.current}, (avg:${format(this.updatePositioningCounter.lastSecAverage)}, t:${format(this.updatePositioningCounter.total)})\n` + 
                     ` - Update Local  Trans: ${this.updateLocalTransformCounter.current}, (avg:${format(this.updateLocalTransformCounter.lastSecAverage)}, t:${format(this.updateLocalTransformCounter.total)})\n` + 
                     ` - Update Global Trans: ${this.updateGlobalTransformCounter.current}, (avg:${format(this.updateGlobalTransformCounter.lastSecAverage)}, t:${format(this.updateGlobalTransformCounter.total)})\n` + 
-                    ` - BoundingInfo Recompute: ${this.boundingInfoRecomputeCounter.current}, (avg:${format(this.boundingInfoRecomputeCounter.lastSecAverage)}, t:${format(this.boundingInfoRecomputeCounter.total)})`;
+                    ` - BoundingInfo Recompute: ${this.boundingInfoRecomputeCounter.current}, (avg:${format(this.boundingInfoRecomputeCounter.lastSecAverage)}, t:${format(this.boundingInfoRecomputeCounter.total)})\n` +
+                    ` - LayoutBoundingInfo Recompute: ${this.layoutBoundingInfoUpdateCounter.current}, (avg:${format(this.layoutBoundingInfoUpdateCounter.lastSecAverage)}, t:${format(this.layoutBoundingInfoUpdateCounter.total)})` ;
             this._profileInfoText.text = p;
         }
 
@@ -1189,35 +1197,57 @@
         }
 
         public _addGroupRenderCount(count: number) {
-            this._groupRenderCounter.addCount(count, false);
+            if (this._groupRenderCounter) {
+                this._groupRenderCounter.addCount(count, false);
+            }
         }
 
         public _addUpdateTransparentDataCount(count: number) {
-            this._updateTransparentDataCounter.addCount(count, false);
+            if (this._updateTransparentDataCounter) {
+                this._updateTransparentDataCounter.addCount(count, false);
+            }
         }
 
         public addCachedGroupRenderCounter(count: number) {
-            this._cachedGroupRenderCounter.addCount(count, false);
+            if (this._cachedGroupRenderCounter) {
+                this._cachedGroupRenderCounter.addCount(count, false);
+            }
         }
 
         public addUpdateCachedStateCounter(count: number) {
-            this._updateCachedStateCounter.addCount(count, false);
+            if (this._updateCachedStateCounter) {
+                this._updateCachedStateCounter.addCount(count, false);
+            }
         }
 
         public addUpdateLayoutCounter(count: number) {
-            this._updateLayoutCounter.addCount(count, false);
+            if (this._updateLayoutCounter) {
+                this._updateLayoutCounter.addCount(count, false);
+            }
         }
 
         public addUpdatePositioningCounter(count: number) {
-            this._updatePositioningCounter.addCount(count, false);
+            if (this._updatePositioningCounter) {
+                this._updatePositioningCounter.addCount(count, false);
+            }
         }
 
         public addupdateLocalTransformCounter(count: number) {
-            this._updateLocalTransformCounter.addCount(count, false);
+            if (this._updateLocalTransformCounter) {
+                this._updateLocalTransformCounter.addCount(count, false);
+            }
         }
 
         public addUpdateGlobalTransformCounter(count: number) {
-            this._updateGlobalTransformCounter.addCount(count, false);
+            if (this._updateGlobalTransformCounter) {
+                this._updateGlobalTransformCounter.addCount(count, false);
+            }
+        }
+
+        public addLayoutBoundingInfoUpdateCounter(count: number) {
+            if (this._layoutBoundingInfoUpdateCounter) {
+                this._layoutBoundingInfoUpdateCounter.addCount(count, false);
+            }
         }
 
         private _renderObservable: Observable<Canvas2D>;
@@ -1264,18 +1294,19 @@
 
         public _renderingSize: Size;
 
-        private _drawCallsOpaqueCounter      : PerfCounter;
-        private _drawCallsAlphaTestCounter   : PerfCounter;
-        private _drawCallsTransparentCounter : PerfCounter;
-        private _groupRenderCounter          : PerfCounter;
-        private _updateTransparentDataCounter: PerfCounter;
-        private _cachedGroupRenderCounter    : PerfCounter;
-        private _updateCachedStateCounter    : PerfCounter;
-        private _updateLayoutCounter         : PerfCounter;
-        private _updatePositioningCounter    : PerfCounter;
-        private _updateGlobalTransformCounter: PerfCounter;
-        private _updateLocalTransformCounter : PerfCounter;
-        private _boundingInfoRecomputeCounter: PerfCounter;
+        private _drawCallsOpaqueCounter          : PerfCounter;
+        private _drawCallsAlphaTestCounter       : PerfCounter;
+        private _drawCallsTransparentCounter     : PerfCounter;
+        private _groupRenderCounter              : PerfCounter;
+        private _updateTransparentDataCounter    : PerfCounter;
+        private _cachedGroupRenderCounter        : PerfCounter;
+        private _updateCachedStateCounter        : PerfCounter;
+        private _updateLayoutCounter             : PerfCounter;
+        private _updatePositioningCounter        : PerfCounter;
+        private _updateGlobalTransformCounter    : PerfCounter;
+        private _updateLocalTransformCounter     : PerfCounter;
+        private _boundingInfoRecomputeCounter    : PerfCounter;
+        private _layoutBoundingInfoUpdateCounter : PerfCounter;
 
         private _profilingCanvas: Canvas2D;
         private _profileInfoText: Text2D;
@@ -1447,7 +1478,6 @@
 
             // If the canvas fit the rendering size and it changed, update
             if (renderingSizeChanged && this._fitRenderingDevice) {
-                this.actualSize = this._renderingSize.clone();
                 this.size = this._renderingSize.clone();
                 if (this._background) {
                     this._background.size = this.size;
@@ -1466,7 +1496,6 @@
                     scale = this._renderingSize.height / this._designSize.height;
                 }
                 this.size = this._designSize.clone();
-                this.actualSize = this._designSize.clone();
                 this.scale = scale;
             }
 

+ 61 - 14
canvas2D/src/Engine/babylon.canvas2dLayoutEngine.ts

@@ -65,10 +65,10 @@
 
             // If this prim is layoutDiry we update  its layoutArea and also the one of its direct children
             if (prim._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
+                prim._clearFlags(SmartPropertyPrim.flagLayoutDirty);
                 for (let child of prim.children) {
                     this._doUpdate(child);
                 }
-                prim._clearFlags(SmartPropertyPrim.flagLayoutDirty);
             }
 
         }
@@ -86,7 +86,12 @@
 
             // Indirect child of Canvas
             else {
-                prim.layoutArea = prim.parent.contentArea;
+                let contentArea = prim.parent.contentArea;
+
+                // Can be null if the parent's content area depend of its children, the computation will be done in many passes
+                if (contentArea) {
+                    prim.layoutArea = contentArea;
+                }
             }
         }
 
@@ -143,47 +148,89 @@
 
         private _isHorizontal: boolean = true;
 
+        private static stackPanelLayoutArea = Size.Zero();
         private static dstOffset = Vector4.Zero();
         private static dstArea = Size.Zero();
 
+        private static computeCounter = 0;
+
         public updateLayout(prim: Prim2DBase) {
             if (prim._isFlagSet(SmartPropertyPrim.flagLayoutDirty)) {
 
+                let primLayoutArea = prim.layoutArea;
+                let isSizeAuto = prim.isSizeAuto;
+
+                // If we're not in autoSize the layoutArea of the prim having the stack panel must be computed in order for us to compute the children' position.
+                // If there's at least one auto size (Horizontal or Vertical) we will have to figure the layoutArea ourselves
+                if (!primLayoutArea && !isSizeAuto) {
+                    return;
+                }
+
+//                console.log("Compute Stack Panel Layout " + ++StackPanelLayoutEngine.computeCounter);
+
                 let x = 0;
                 let y = 0;
-                let h = this.isHorizontal;
+                let horizonStackPanel = this.isHorizontal;
+
+                // If the stack panel is horizontal we check if the primitive height is auto or not, if it's auto then we have to compute the required height, otherwise we just take the actualHeight. If the stack panel is vertical we do the same but with width
                 let max = 0;
 
+                let stackPanelLayoutArea = StackPanelLayoutEngine.stackPanelLayoutArea;
+                if (horizonStackPanel) {
+                    if (prim.isVerticalSizeAuto) {
+                        max = 0;
+                        stackPanelLayoutArea.height = 0;
+                    } else {
+                        max = prim.layoutArea.height;
+                        stackPanelLayoutArea.height = prim.layoutArea.height;
+                        stackPanelLayoutArea.width = 0;
+                    }
+                } else {
+                    if (prim.isHorizontalSizeAuto) {
+                        max = 0;
+                        stackPanelLayoutArea.width = 0;
+                    } else {
+                        max = prim.layoutArea.width;
+                        stackPanelLayoutArea.width = prim.layoutArea.width;
+                        stackPanelLayoutArea.height = 0;
+                    }
+                }
+
                 for (let child of prim.children) {
                     if (child._isFlagSet(SmartPropertyPrim.flagNoPartOfLayout)) {
                         continue;
                     }
-                    let layoutArea: Size;
+
                     if (child._hasMargin) {
-                        child.margin.computeWithAlignment(prim.layoutArea, child.actualSize, child.marginAlignment, child.actualScale, StackPanelLayoutEngine.dstOffset, StackPanelLayoutEngine.dstArea, true);
-                        layoutArea = StackPanelLayoutEngine.dstArea.clone();
-                        child.layoutArea = layoutArea;
+
+                        // Calling computeWithAlignment will return us the area taken by "child" which is its layoutArea
+                        // We also have the dstOffset which will give us the y position in horizontal mode or x position in vertical mode.
+                        //  The alignment offset on the other axis is simply ignored as it doesn't make any sense (e.g. horizontal alignment is ignored in horizontal mode)
+                        child.margin.computeWithAlignment(stackPanelLayoutArea, child.actualSize, child.marginAlignment, child.actualScale, StackPanelLayoutEngine.dstOffset, StackPanelLayoutEngine.dstArea, true);
+
+                        child.layoutArea = StackPanelLayoutEngine.dstArea;
+
                     } else {
-                        layoutArea = child.layoutArea;
-                        child.margin.computeArea(child.actualSize, layoutArea);
+                        child.margin.computeArea(child.actualSize, child.actualScale, StackPanelLayoutEngine.dstArea);
+                        child.layoutArea = StackPanelLayoutEngine.dstArea;
                     }
 
-                    max = Math.max(max, h ? layoutArea.height : layoutArea.width);
-
+                    max = Math.max(max, horizonStackPanel ? StackPanelLayoutEngine.dstArea.height : StackPanelLayoutEngine.dstArea.width);
                 }
 
                 for (let child of prim.children) {
                     if (child._isFlagSet(SmartPropertyPrim.flagNoPartOfLayout)) {
                         continue;
                     }
-                    child.layoutAreaPos = new Vector2(x, y);
 
                     let layoutArea = child.layoutArea;
 
-                    if (h) {
+                    if (horizonStackPanel) {
+                        child.layoutAreaPos = new Vector2(x, 0);
                         x += layoutArea.width;
                         child.layoutArea = new Size(layoutArea.width, max);
                     } else {
+                        child.layoutAreaPos = new Vector2(0, y);
                         y += layoutArea.height;
                         child.layoutArea = new Size(max, layoutArea.height);
                     }
@@ -333,7 +380,7 @@
                         child.margin.computeWithAlignment(prim.layoutArea, child.actualSize, child.marginAlignment, child.actualScale, GridPanelLayoutEngine.dstOffset, GridPanelLayoutEngine.dstArea, true);
                         child.layoutArea = GridPanelLayoutEngine.dstArea.clone();
                     } else {
-                        child.margin.computeArea(child.actualSize, child.layoutArea);
+                        child.margin.computeArea(child.actualSize, child.actualScale, child.layoutArea);
                     }
                 }
 

+ 1 - 16
canvas2D/src/Engine/babylon.ellipse2d.ts

@@ -168,21 +168,6 @@
         public static acutalSizeProperty: Prim2DPropInfo;
         public static subdivisionsProperty: Prim2DPropInfo;
 
-        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 1, pi => Ellipse2D.acutalSizeProperty = pi, false, true)
-        /**
-         * Get/Set the size of the ellipse
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
-        }
-
-        public set actualSize(value: Size) {
-            this._actualSize = value;
-        }
-
         @modelLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 2, pi => Ellipse2D.subdivisionsProperty = pi)
         /**
          * Get/set the number of subdivisions used to draw the ellipsis. Default is 64.
@@ -289,7 +274,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             // Avoid checking every time if the object exists

+ 2 - 45
canvas2D/src/Engine/babylon.group2d.ts

@@ -111,7 +111,7 @@
             paddingLeft             ?: number | string,
             paddingRight            ?: number | string,
             paddingBottom           ?: number | string,
-            padding                 ?: string,
+            padding                 ?: number | string,
 
         }) {
             if (settings == null) {
@@ -247,7 +247,7 @@
 
         @instanceLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, pi => Group2D.sizeProperty = pi, false, true)
         public get size(): Size {
-            return this._size;
+            return this.internalGetSize();
         }
 
         /**
@@ -262,49 +262,6 @@
             return this._viewportSize;
         }
 
-        @instanceLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 2, pi => Group2D.actualSizeProperty = pi)
-        /**
-         * Get the actual size of the group, if the size property is not null, this value will be the same, but if size is null, actualSize will return the size computed from the group's bounding content.
-         */
-        public get actualSize(): Size {
-            // The computed size will be floor on both width and height
-            let actualSize: Size;
-
-            // Return the actualSize if set
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-
-            // Return the size if set by the user
-            if (this._size) {
-                actualSize = new Size(Math.ceil(this._size.width), Math.ceil(this._size.height));
-            }
-
-            // Otherwise the size is computed based on the boundingInfo of the layout (or bounding info) content
-            else {
-                let m = this.layoutBoundingInfo.max();
-                actualSize = new Size(Math.ceil(m.x), Math.ceil(m.y));
-            }
-
-            // Compare the size with the one we previously had, if it differs we set the property dirty and trigger a GroupChanged to synchronize a displaySprite (if any)
-            if (!actualSize.equals(this._actualSize)) {
-                this.onPrimitivePropertyDirty(Group2D.actualSizeProperty.flagId);
-                this._actualSize = actualSize;
-                this.handleGroupChanged(Group2D.actualSizeProperty);
-            }
-
-            return actualSize;
-        }
-
-        public set actualSize(value: Size) {
-            if (!this._actualSize) {
-                this._actualSize = value.clone();
-            } else {
-                this._actualSize.copyFrom(value);
-            }
-        }
-
-
         /**
          * Get/set the Cache Behavior, used in case the Canvas Cache Strategy is set to CACHESTRATEGY_ALLGROUPS. Can be either GROUPCACHEBEHAVIOR_CACHEINPARENTGROUP, GROUPCACHEBEHAVIOR_DONTCACHEOVERRIDE or GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY. See their documentation for more information.
          * GROUPCACHEBEHAVIOR_NORESIZEONSCALE can also be set if you set it at creation time.

+ 1 - 1
canvas2D/src/Engine/babylon.lines2d.ts

@@ -409,7 +409,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             if (!settings) {

File diff suppressed because it is too large
+ 649 - 284
canvas2D/src/Engine/babylon.prim2dBase.ts


+ 7 - 22
canvas2D/src/Engine/babylon.rectangle2d.ts

@@ -170,25 +170,6 @@
         public static notRoundedProperty: Prim2DPropInfo;
         public static roundRadiusProperty: Prim2DPropInfo;
 
-        @instanceLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 1, pi => Rectangle2D.actualSizeProperty = pi, false, true)
-        /**
-         * Get/set the rectangle size (width/height)
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
-        }
-
-        public set actualSize(value: Size) {
-            if (!this._actualSize) {
-                this._actualSize = value.clone();
-            } else {
-                this._actualSize.copyFrom(value);
-            }
-        }
-
         @modelLevelProperty(Shape2D.SHAPE2D_PROPCOUNT + 2, pi => Rectangle2D.notRoundedProperty = pi)
         /**
          * Get if the rectangle is notRound (returns true) or rounded (returns false).
@@ -377,7 +358,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             // Avoid checking every time if the object exists
@@ -577,15 +558,19 @@
             }
         }
 
-        protected _getActualSizeFromContentToRef(primSize: Size, newPrimSize: Size) {
+        protected _getActualSizeFromContentToRef(primSize: Size, paddingOffset: Vector4, newPrimSize: Size) {
             // Fall back to default implementation if there's no round Radius
             if (this._notRounded) {
-                super._getActualSizeFromContentToRef(primSize, newPrimSize);
+                super._getActualSizeFromContentToRef(primSize, paddingOffset, newPrimSize);
             } else {
                 let rr = Math.round((this.roundRadius - (this.roundRadius / Math.sqrt(2))) * 1.3);
                 newPrimSize.copyFrom(primSize);
                 newPrimSize.width  += rr * 2;
                 newPrimSize.height += rr * 2;
+                paddingOffset.x += rr;
+                paddingOffset.y += rr;
+                paddingOffset.z += rr;
+                paddingOffset.w += rr;
             }
         }
 

+ 19 - 19
canvas2D/src/Engine/babylon.renderablePrim2d.ts

@@ -960,25 +960,25 @@
             let w = size.width;
             let h = size.height;
             let invZBias = 1 / zBias;
-            let tx = new Vector4(t.m[0] * rgScale.x * 2/* / w*/, t.m[4] * rgScale.x * 2/* / w*/, 0/*t.m[8]*/, ((t.m[12] + offX) * rgScale.x * 2 / w) - 1);
-            let ty = new Vector4(t.m[1] * rgScale.y * 2/* / h*/, t.m[5] * rgScale.y * 2/* / h*/, 0/*t.m[9]*/, ((t.m[13] + offY) * rgScale.y * 2 / h) - 1);
-
-            if (!this.applyActualScaleOnTransform()) {
-                t.m[0] = tx.x, t.m[4] = tx.y, t.m[12] = tx.w;
-                t.m[1] = ty.x, t.m[5] = ty.y, t.m[13] = ty.w;
-                let las = this.actualScale;
-                t.decompose(RenderablePrim2D._s, RenderablePrim2D._r, RenderablePrim2D._t);
-                let scale = new Vector3(RenderablePrim2D._s.x / las.x, RenderablePrim2D._s.y / las.y, 1);
-                t = Matrix.Compose(scale, RenderablePrim2D._r, RenderablePrim2D._t);
-                tx = new Vector4(t.m[0], t.m[4], 0, t.m[12]);
-                ty = new Vector4(t.m[1], t.m[5], 0, t.m[13]);
-            }
-
-            tx.x /= w;
-            tx.y /= w;
-
-            ty.x /= h;
-            ty.y /= h;
+            let tx = new Vector4(t.m[0] * rgScale.x * 2 / w, t.m[4] * rgScale.x * 2 / w, 0/*t.m[8]*/, ((t.m[12] + offX) * rgScale.x * 2 / w) - 1);
+            let ty = new Vector4(t.m[1] * rgScale.y * 2 / h, t.m[5] * rgScale.y * 2 / h, 0/*t.m[9]*/, ((t.m[13] + offY) * rgScale.y * 2 / h) - 1);
+
+            //if (!this.applyActualScaleOnTransform()) {
+            //    t.m[0] = tx.x, t.m[4] = tx.y, t.m[12] = tx.w;
+            //    t.m[1] = ty.x, t.m[5] = ty.y, t.m[13] = ty.w;
+            //    let las = this.actualScale;
+            //    t.decompose(RenderablePrim2D._s, RenderablePrim2D._r, RenderablePrim2D._t);
+            //    let scale = new Vector3(RenderablePrim2D._s.x / las.x, RenderablePrim2D._s.y / las.y, 1);
+            //    t = Matrix.Compose(scale, RenderablePrim2D._r, RenderablePrim2D._t);
+            //    tx = new Vector4(t.m[0], t.m[4], 0, t.m[12]);
+            //    ty = new Vector4(t.m[1], t.m[5], 0, t.m[13]);
+            //}
+
+            //tx.x /= w;
+            //tx.y /= w;
+
+            //ty.x /= h;
+            //ty.y /= h;
 
             part.transformX = tx;
             part.transformY = ty;

+ 6 - 1
canvas2D/src/Engine/babylon.smartPropertyPrim.ts

@@ -1112,7 +1112,9 @@
                     curprim._setFlags(SmartPropertyPrim.flagBoundingInfoDirty);
                     if (curprim.isSizeAuto) {
                         curprim.onPrimitivePropertyDirty(Prim2DBase.sizeProperty.flagId);
-                        curprim._setFlags(SmartPropertyPrim.flagPositioningDirty);
+                        if (curprim._isFlagSet(SmartPropertyPrim.flagUsePositioning)) {
+                            curprim._setFlags(SmartPropertyPrim.flagPositioningDirty);
+                        }
                     }
 
                     if (curprim instanceof Group2D) {
@@ -1305,6 +1307,9 @@
         public static flagLayoutBoundingInfoDirty = 0x0200000;    // set if the layout bounding info is dirty
         public static flagCollisionActor          = 0x0400000;    // set if the primitive is part of the collision engine
         public static flagModelUpdate             = 0x0800000;    // set if the primitive's model data is to update
+        public static flagLocalTransformDirty     = 0x1000000;    // set if the local transformation matrix must be recomputed
+        public static flagUsePositioning          = 0x2000000;    // set if the primitive rely on the positioning engine (padding or margin is used)
+        public static flagComputingPositioning    = 0x4000000;    // set if the positioning engine is computing the primitive, used to avoid re entrance
 
         private   _uid                : string;
         private   _flags              : number;

+ 1 - 19
canvas2D/src/Engine/babylon.sprite2d.ts

@@ -145,24 +145,6 @@
             this._updateSpriteScaleFactor();
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Sprite2D.actualSizeProperty = pi, false, true)
-        /**
-         * Get/set the actual size of the sprite to display
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
-        }
-
-        public set actualSize(value: Size) {
-            if (!this._actualSize) {
-                this._actualSize = value.clone();
-            } else {
-                this._actualSize.copyFrom(value);
-            }
-        }
 
         @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, pi => Sprite2D.spriteSizeProperty = pi, false, true)
         /**
@@ -363,7 +345,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             if (!settings) {

+ 16 - 9
canvas2D/src/Engine/babylon.text2d.ts

@@ -271,14 +271,12 @@
             return false;
         }
 
-        /**
-         * Get the actual size of the Text2D primitive
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
+        public get isVerticalSizeAuto(): boolean {
+            return false;
+        }
+
+        public get isHorizontalSizeAuto(): boolean {
+            return false;
         }
 
         /**
@@ -301,6 +299,15 @@
             return this._textSize;
         }
 
+        protected onSetOwner() {
+            if (!this._textSize) {
+                this.onPrimitivePropertyDirty(Prim2DBase.sizeProperty.flagId);
+                this._setLayoutDirty();
+                this._positioningDirty();
+                this._actualSize = null;
+            }
+        }
+
         protected get fontTexture(): BaseFontTexture {
             if (this._fontTexture) {
                 return this._fontTexture;
@@ -437,7 +444,7 @@
             paddingLeft             ?: number | string,
             paddingRight            ?: number | string,
             paddingBottom           ?: number | string,
-            padding                 ?: string,
+            padding                 ?: number | string,
             textAlignmentH          ?: number,
             textAlignmentV          ?: number,
             textAlignment           ?: string,

+ 1 - 20
canvas2D/src/Engine/babylon.wireFrame2d.ts

@@ -233,25 +233,6 @@
             this.internalSetSize(value);
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, pi => WireFrame2D.actualSizeProperty = pi, false, true)
-        /**
-         * Get/set the actual size of the sprite to display
-         */
-        public get actualSize(): Size {
-            if (this._actualSize) {
-                return this._actualSize;
-            }
-            return this.size;
-        }
-
-        public set actualSize(value: Size) {
-            if (!this._actualSize) {
-                this._actualSize.clone();
-            } else {
-                this._actualSize.copyFrom(value);
-            }
-        }
-
         protected updateLevelBoundingInfo(): boolean {
             let v = this._computeMinMaxTrans();
             BoundingInfo2D.CreateFromMinMaxToRef(v.x, v.z, v.y, v.w, this._levelBoundingInfo);
@@ -337,7 +318,7 @@
             paddingLeft           ?: number | string,
             paddingRight          ?: number | string,
             paddingBottom         ?: number | string,
-            padding               ?: string,
+            padding               ?: number | string,
         }) {
 
             if (!settings) {

+ 24 - 24
canvas2D/src/Tools/babylon.math2D.ts

@@ -647,15 +647,15 @@
             let radius = Math.sqrt(rs);
 
             let offset = index * 9;
-            this._array[0] = a.x;
-            this._array[1] = a.y;
-            this._array[2] = b.x;
-            this._array[3] = b.y;
-            this._array[4] = c.x;
-            this._array[5] = c.y;
-            this._array[6] = center.x;
-            this._array[7] = center.y;
-            this._array[8] = radius;
+            this._array[offset + 0] = a.x;
+            this._array[offset + 1] = a.y;
+            this._array[offset + 2] = b.x;
+            this._array[offset + 3] = b.y;
+            this._array[offset + 4] = c.x;
+            this._array[offset + 5] = c.y;
+            this._array[offset + 6] = center.x;
+            this._array[offset + 7] = center.y;
+            this._array[offset + 8] = radius;
         }
 
         /**
@@ -669,15 +669,15 @@
             }
 
             let offset = index * 9;
-            tri2dInfo.a.x      = this._array[0];
-            tri2dInfo.a.y      = this._array[1];
-            tri2dInfo.b.x      = this._array[2];
-            tri2dInfo.b.y      = this._array[3];
-            tri2dInfo.c.x      = this._array[4];
-            tri2dInfo.c.y      = this._array[5];
-            tri2dInfo.center.x = this._array[6];
-            tri2dInfo.center.y = this._array[7];
-            tri2dInfo.radius   = this._array[8];
+            tri2dInfo.a.x      = this._array[offset + 0];
+            tri2dInfo.a.y      = this._array[offset + 1];
+            tri2dInfo.b.x      = this._array[offset + 2];
+            tri2dInfo.b.y      = this._array[offset + 3];
+            tri2dInfo.c.x      = this._array[offset + 4];
+            tri2dInfo.c.y      = this._array[offset + 5];
+            tri2dInfo.center.x = this._array[offset + 6];
+            tri2dInfo.center.y = this._array[offset + 7];
+            tri2dInfo.radius   = this._array[offset + 8];
         }
 
         /**
@@ -692,12 +692,12 @@
             }
 
             let offset = index * 9;
-            tri2dInfo.a.x = this._array[0];
-            tri2dInfo.a.y = this._array[1];
-            tri2dInfo.b.x = this._array[2];
-            tri2dInfo.b.y = this._array[3];
-            tri2dInfo.c.x = this._array[4];
-            tri2dInfo.c.y = this._array[5];
+            tri2dInfo.a.x = this._array[offset + 0];
+            tri2dInfo.a.y = this._array[offset + 1];
+            tri2dInfo.b.x = this._array[offset + 2];
+            tri2dInfo.b.y = this._array[offset + 3];
+            tri2dInfo.c.x = this._array[offset + 4];
+            tri2dInfo.c.y = this._array[offset + 5];
 
             tri2dInfo.transformInPlace(transform);
         }