Browse Source

Canvas2D: DPR, Scale, designMode, etc.

 - Device Pixel Ratio and setHardwareScalingLevel are now supported.
 - DesignMode should work again, as expected
 - Scale should now be working when spreading down the hierarchy tree
nockawa 8 years ago
parent
commit
c2874b15c3

+ 25 - 6
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -169,6 +169,8 @@
             this._scene = scene;
             this._engine = engine;
             this._renderingSize = new Size(0, 0);
+            this._curHWScale = 0;
+            this._canvasLevelScale = new Vector3(1, 1, 1);
             this._designSize = settings.designSize || null;
             this._designUseHorizAxis = settings.designUseHorizAxis === true;
             if (!this._trackedGroups) {
@@ -1292,7 +1294,9 @@
         private _designUseHorizAxis: boolean;
         public  _primitiveCollisionManager: PrimitiveCollisionManagerBase;
 
-        public _renderingSize: Size;
+        public _canvasLevelScale: Vector3;
+        public  _renderingSize: Size;
+        private _curHWScale;
 
         private _drawCallsOpaqueCounter          : PerfCounter;
         private _drawCallsAlphaTestCounter       : PerfCounter;
@@ -1458,15 +1462,26 @@
                 return;
             }
 
+            // Detect a change of HWRendering scale
+            let hwsl = this.engine.getHardwareScalingLevel();
+            let hwslChanged = this._curHWScale !== hwsl;
+            if (hwslChanged) {
+                this._curHWScale = hwsl;
+                for (let child of this.children) {
+                    child._setFlags(SmartPropertyPrim.flagLocalTransformDirty|SmartPropertyPrim.flagGlobalTransformDirty);
+                }
+                this._setLayoutDirty();
+            }
+
             // Detect a change of rendering size
             let renderingSizeChanged = false;
-            let newWidth = this.engine.getRenderWidth();
+            let newWidth = this.engine.getRenderWidth() * hwsl;
             if (newWidth !== this._renderingSize.width) {
                 renderingSizeChanged = true;
             }
             this._renderingSize.width = newWidth;
 
-            let newHeight = this.engine.getRenderHeight();
+            let newHeight = this.engine.getRenderHeight() * hwsl;
             if (newHeight !== this._renderingSize.height) {
                 renderingSizeChanged = true;
             }
@@ -1487,17 +1502,21 @@
             if (this._designSize) {
                 let scale: number;
                 if (this._designUseHorizAxis) {
-                    scale = this._renderingSize.width / this._designSize.width;
+                    scale = this._renderingSize.width / (this._designSize.width * hwsl);
                 } else {
-                    scale = this._renderingSize.height / this._designSize.height;
+                    scale = this._renderingSize.height / (this._designSize.height * hwsl);
                 }
                 this.size = this._designSize.clone();
-                this.scale = scale;
+                this._canvasLevelScale.copyFromFloats(scale, scale, 1);
+            } else if (this._curHWScale !== 1) {
+                let ratio = 1 / this._curHWScale;
+                this._canvasLevelScale.copyFromFloats(ratio, ratio, 1);
             }
 
             var context = new PrepareRender2DContext();
 
             ++this._globalTransformProcessStep;
+            this._setFlags(SmartPropertyPrim.flagLocalTransformDirty|SmartPropertyPrim.flagGlobalTransformDirty);
             this.updateCachedStates(false);
 
             this._prepareGroupRender(context);

+ 4 - 3
canvas2D/src/Engine/babylon.group2d.ts

@@ -355,8 +355,9 @@
 
             let s = this.actualSize;
             let a = this.actualScale;
-            let sw = Math.ceil(s.width * a.x);
-            let sh = Math.ceil(s.height * a.y);
+            let hwsl = 1/this.owner.engine.getHardwareScalingLevel();
+            let sw = Math.ceil(s.width * a.x * hwsl);
+            let sh = Math.ceil(s.height * a.y * hwsl);
 
             // The dimension must be overridden when using the designSize feature, the ratio is maintain to compute a uniform scale, which is mandatory but if the designSize's ratio is different from the rendering surface's ratio, content will be clipped in some cases.
             // So we set the width/height to the rendering's one because that's what we want for the viewport!
@@ -370,7 +371,7 @@
             if (!this._isCachedGroup) {
                 // Compute the WebGL viewport's location/size
                 let t = this._globalTransform.getTranslation();
-                let rs = this.owner._renderingSize;
+                let rs = this.owner._renderingSize.multiplyByFloats(hwsl, hwsl);
                 sh = Math.min(sh, rs.height - t.y);
                 sw = Math.min(sw, rs.width - t.x);
                 let x = t.x;

+ 17 - 2
canvas2D/src/Engine/babylon.prim2dBase.ts

@@ -3668,6 +3668,7 @@
         private static _t2: Matrix = new Matrix();
         private static _v0: Vector2 = Vector2.Zero();   // Must stay with the value 0,0
         private static _v30: Vector3 = Vector3.Zero();   // Must stay with the value 0,0,0
+        private static _iv3: Vector3 = new Vector3(1,1,1); // Must stay identity vector
         private static _ts0 = Size.Zero();
 
         private _updateLocalTransform(): boolean {
@@ -3683,12 +3684,19 @@
                     this._updatePositioning();
                 }
 
+
                 var rot = Quaternion.RotationAxis(new Vector3(0, 0, 1), this._rotation);
                 var local: Matrix;
                 let pos = this._position ? this.position : (this.layoutAreaPos || Prim2DBase._v0);
                 let scale = new Vector3(this._scale.x, this._scale.y, 1);
                 let postScale = this._postScale;
-                let globalScale = scale.multiplyByFloats(postScale.x, postScale.y, 1);
+                let canvasScale = Prim2DBase._iv3;
+                let hasCanvasScale = false;
+                if (this._parent instanceof Canvas2D) {
+                    hasCanvasScale = true;
+                    canvasScale = (this._parent as Canvas2D)._canvasLevelScale || Prim2DBase._iv3;
+                }
+                let globalScale = scale.multiplyByFloats(postScale.x*canvasScale.x, postScale.y*canvasScale.y, 1);
 
                 if (this._origin.x === 0 && this._origin.y === 0) {
                     // ###MATRIX PART###
@@ -3730,6 +3738,11 @@
                         Matrix.TranslationToRef(pos.x + this._marginOffset.x, pos.y + this._marginOffset.y, 0, t0);
                         t2.multiplyToRef(t0, this._localTransform);
 
+                        if (hasCanvasScale) {
+                            Matrix.ScalingToRef(canvasScale.x, canvasScale.y, canvasScale.z, Prim2DBase._t1);
+                            this._localTransform.multiplyToRef(Prim2DBase._t1, this._localTransform);
+                        }
+
                         this._localLayoutTransform = Matrix.Compose(globalScale, rot, new Vector3(pos.x, pos.y, 0));
                     }
                 }
@@ -3805,7 +3818,7 @@
             }
 
             // Check if we must update this prim
-            if ((this === <any>this.owner) || (this._globalTransformProcessStep !== this.owner._globalTransformProcessStep) || (this._areSomeFlagsSet(SmartPropertyPrim.flagGlobalTransformDirty))) {
+            if ((this._globalTransformProcessStep !== this.owner._globalTransformProcessStep) || (this._areSomeFlagsSet(SmartPropertyPrim.flagGlobalTransformDirty))) {
                 this.owner.addUpdateGlobalTransformCounter(1);
 
                 let curVisibleState = this.isVisible;
@@ -3870,6 +3883,8 @@
 
         private _updatePositioning() {
             if (!this._isFlagSet(SmartPropertyPrim.flagUsePositioning)) {
+                // Just in case, if may happen and if we don't clear some computation will keep going on forever
+                this._clearFlags(SmartPropertyPrim.flagPositioningDirty);
                 return;
             }
 

+ 15 - 27
canvas2D/src/Engine/babylon.renderablePrim2d.ts

@@ -931,7 +931,7 @@
         private static _s = Vector3.Zero();
         private static _r = Quaternion.Identity();
         private static _t = Vector3.Zero();
-        private static _uV3 = new Vector3(1, 1, 1);
+        private static _iV3 = new Vector3(1, 1, 1); // Must stay identity vector3
         /**
          * Update the instanceDataBase level properties of a part
          * @param part the part to update
@@ -939,12 +939,22 @@
          */
         protected updateInstanceDataPart(part: InstanceDataBase, positionOffset: Vector2 = null) {
             let t = this._globalTransform.multiply(this.renderGroup.invGlobalTransform);    // Compute the transformation into the renderGroup's space
-            let rgScale = this._areSomeFlagsSet(SmartPropertyPrim.flagDontInheritParentScale) ? RenderablePrim2D._uV : this.renderGroup.actualScale;         // We still need to apply the scale of the renderGroup to our rendering, so get it.
+            let scl = RenderablePrim2D._s;
+            let rot = RenderablePrim2D._r;
+            let trn = RenderablePrim2D._t;
+            t.decompose(scl, rot, trn);
+            let pas = this.actualScale;
+            scl.x = pas.x;
+            scl.y = pas.y;
+            scl.z = 1;
+            t = Matrix.Compose(this.applyActualScaleOnTransform() ? scl : RenderablePrim2D._iV3, rot, trn);
+
             let size = (<Size>this.renderGroup.viewportSize);
             let zBias = this.actualZOffset;
 
             let offX = 0;
             let offY = 0;
+
             // If there's an offset, apply the global transformation matrix on it to get a global offset
             if (positionOffset) {
                 offX = positionOffset.x * t.m[0] + positionOffset.y * t.m[4];
@@ -960,31 +970,9 @@
             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;
-
-            if (!this.applyActualScaleOnTransform()) {
-                let las = this.actualScale;
-                tx.x /= las.x;
-                ty.y /= las.y;
-            }
+            let tx = new Vector4(t.m[0] * 2 / w, t.m[4] * 2 / w, 0, ((t.m[12] + offX) * 2 / w) - 1);
+            let ty = new Vector4(t.m[1] * 2 / h, t.m[5] * 2 / h, 0, ((t.m[13] + offY) * 2 / h) - 1);
+
 
             part.transformX = tx;
             part.transformY = ty;