Pārlūkot izejas kodu

Canvas2D: fix + new feature for Sprite2D

Fixing default values at primitives creation time.

Sprite2D now has an alignToPixel property to render the sprite aligned to the rendering target pixel.
nockawa 9 gadi atpakaļ
vecāks
revīzija
7db25d6b70

+ 19 - 1
src/Canvas2d/babylon.ellipse2d.ts

@@ -243,7 +243,25 @@
                 let pos = options.position || new Vector2(options.x || 0, options.y || 0);
                 let size = options.size || (new Size(options.width || 10, options.height || 10));
 
-                ellipse.setupEllipse2D(parent.owner, parent, options.id || null, pos, options.origin || null, size, options.subdivisions || 64, fill, options.border || null, options.borderThickness || 1, options.isVisible || true, options.marginTop || null, options.marginLeft || null, options.marginRight || null, options.marginBottom || null, options.vAlignment || null, options.hAlignment || null);
+                ellipse.setupEllipse2D
+                (
+                    parent.owner,
+                    parent,
+                    options.id || null,
+                    pos,
+                    options.origin || null,
+                    size,
+                    (options.subdivisions == null) ? 64 : options.subdivisions,
+                    fill,
+                    options.border || null,
+                    (options.borderThickness == null) ? 1 : options.borderThickness,
+                    (options.isVisible == null) ? true : options.isVisible,
+                    options.marginTop || null,
+                    options.marginLeft || null,
+                    options.marginRight || null,
+                    options.marginBottom || null,
+                    options.vAlignment || null,
+                    options.hAlignment || null);
             }
 
             return ellipse;

+ 16 - 1
src/Canvas2d/babylon.group2d.ts

@@ -55,7 +55,22 @@
                 let pos = options.position || new Vector2(options.x || 0, options.y || 0);
                 let size = (!options.size && !options.width && !options.height) ? null : (options.size || (new Size(options.width || 0, options.height || 0)));
                 
-                g.setupGroup2D(parent.owner, parent, options.id || null, pos, options.origin || null, size, options.isVisible || true, options.cacheBehavior || Group2D.GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY, options.marginTop, options.marginLeft, options.marginRight, options.marginBottom, options.hAlignment || Prim2DBase.HAlignLeft, options.vAlignment || Prim2DBase.VAlignTop);
+                g.setupGroup2D
+                (
+                    parent.owner,
+                    parent,
+                    options.id || null,
+                    pos,
+                    options.origin || null,
+                    size,
+                    (options.isVisible == null) ? true : options.isVisible,
+                    (options.cacheBehavior == null) ? Group2D.GROUPCACHEBEHAVIOR_FOLLOWCACHESTRATEGY : options.cacheBehavior,
+                    options.marginTop,
+                    options.marginLeft,
+                    options.marginRight,
+                    options.marginBottom,
+                    options.hAlignment || Prim2DBase.HAlignLeft,
+                    options.vAlignment || Prim2DBase.VAlignTop);
             }
        
             return g;

+ 22 - 1
src/Canvas2d/babylon.lines2d.ts

@@ -343,7 +343,28 @@
                 }
                 let pos = options.position || new Vector2(options.x || 0, options.y || 0);
 
-                lines.setupLines2D(parent.owner, parent, options.id || null, pos, options.origin || null, points, options.fillThickness || 1, options.startCap || 0, options.endCap || 0, fill, options.border || null, options.borderThickness || 1, options.closed || false, options.isVisible || true, options.marginTop || null, options.marginLeft || null, options.marginRight || null, options.marginBottom || null, options.vAlignment || null, options.hAlignment || null);                
+                lines.setupLines2D
+                (
+                    parent.owner,
+                    parent,
+                    options.id || null,
+                    pos,
+                    options.origin || null,
+                    points,
+                    (options.fillThickness == null) ? 1 : options.fillThickness,
+                    (options.startCap == null) ? 0 : options.startCap,
+                    (options.endCap == null) ? 0 : options.endCap,
+                    fill,
+                    options.border || null,
+                    (options.borderThickness == null) ? 1 : options.borderThickness,
+                    (options.closed == null) ? false : options.closed,
+                    (options.isVisible == null) ? true : options.isVisible,
+                    options.marginTop || null,
+                    options.marginLeft || null,
+                    options.marginRight || null,
+                    options.marginBottom || null,
+                    options.vAlignment || null,
+                    options.hAlignment || null);                
             }
 
             return lines;

+ 19 - 1
src/Canvas2d/babylon.rectangle2d.ts

@@ -320,7 +320,25 @@
                 let size = options.size || (new Size(options.width || 10, options.height || 10));
                 let fill = options.fill===undefined ? Canvas2D.GetSolidColorBrushFromHex("#FFFFFFFF") : options.fill;
 
-                rect.setupRectangle2D(parent.owner, parent, options.id || null, pos, options.origin || null, size, options.roundRadius || 0, fill, options.border || null, options.borderThickness || 1, options.isVisible || true, options.marginTop || null, options.marginLeft || null, options.marginRight || null, options.marginBottom || null, options.vAlignment || null, options.hAlignment || null);
+                rect.setupRectangle2D
+                (
+                    parent.owner,
+                    parent,
+                    options.id || null,
+                    pos,
+                    options.origin || null,
+                    size,
+                    (options.roundRadius == null) ? 0 : options.roundRadius,
+                    fill,
+                    options.border || null,
+                    (options.borderThickness==null) ? 1 : options.borderThickness,
+                    options.isVisible || true,
+                    options.marginTop || null,
+                    options.marginLeft || null,
+                    options.marginRight || null,
+                    options.marginBottom || null,
+                    options.vAlignment || null,
+                    options.hAlignment || null);
             }
             return rect;
         }

+ 48 - 13
src/Canvas2d/babylon.sprite2d.ts

@@ -106,13 +106,12 @@
             return null;
         }
 
+        // 3 floats being:
+        // - x: frame number to display
+        // - y: invertY setting
+        // - z: alignToPixel setting
         @instanceData()
-        get frame(): number {
-            return null;
-        }
-
-        @instanceData()
-        get invertY(): number {
+        get properties(): Vector3 {
             return null;
         }
     }
@@ -126,6 +125,7 @@
         public static spriteLocationProperty: Prim2DPropInfo;
         public static spriteFrameProperty: Prim2DPropInfo;
         public static invertYProperty: Prim2DPropInfo;
+        public static alignToPixelProperty: Prim2DPropInfo;
 
         @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 1, pi => Sprite2D.textureProperty = pi)
         public get texture(): Texture {
@@ -176,6 +176,14 @@
             this._invertY = value;
         }
 
+        public get alignToPixel(): boolean {
+            return this._alignToPixel;
+        }
+
+        public set alignToPixel(value: boolean) {
+            this._alignToPixel = value;
+        }
+
         protected updateLevelBoundingInfo() {
             BoundingInfo2D.CreateFromSizeToRef(this.spriteSize, this._levelBoundingInfo, this.origin);
         }
@@ -194,7 +202,7 @@
             return true;
         }
 
-        protected setupSprite2D(owner: Canvas2D, parent: Prim2DBase, id: string, position: Vector2, origin: Vector2, texture: Texture, spriteSize: Size, spriteLocation: Vector2, invertY: boolean, isVisible: boolean, marginTop: number, marginLeft: number, marginRight: number, marginBottom: number, vAlignment: number, hAlignment: number) {
+        protected setupSprite2D(owner: Canvas2D, parent: Prim2DBase, id: string, position: Vector2, origin: Vector2, texture: Texture, spriteSize: Size, spriteLocation: Vector2, invertY: boolean, alignToPixel: boolean, isVisible: boolean, marginTop: number, marginLeft: number, marginRight: number, marginBottom: number, vAlignment: number, hAlignment: number) {
             this.setupRenderablePrim2D(owner, parent, id, position, origin, isVisible, marginTop, marginLeft, marginRight, marginBottom, hAlignment, vAlignment);
             this.texture = texture;
             this.texture.wrapU = Texture.CLAMP_ADDRESSMODE;
@@ -203,6 +211,7 @@
             this.spriteLocation = spriteLocation || new Vector2(0,0);
             this.spriteFrame = 0;
             this.invertY = invertY;
+            this.alignToPixel = alignToPixel;
             this._isTransparent = true;
 
             if (!this.spriteSize) {
@@ -222,20 +231,39 @@
          *  - spriteSize: the size of the sprite, if null the size of the given texture will be used, default is null.
          *  - spriteLocation: the location in the texture of the top/left corner of the Sprite to display, default is null (0,0)
          *  - invertY: if true the texture Y will be inverted, default is false.
+         *  - alignToPixel: if true the sprite's texels will be aligned to the rendering viewport pixels, ensuring the best rendering quality but slow animations won't be done as smooth as if you set false. If false a texel could lies between two pixels, being blended by the texture sampling mode you choose, the rendering result won't be as good, but very slow animation will be overall better looking. Default is true: content will be aligned.
          *  - isVisible: true if the sprite must be visible, false for hidden. Default is true.
          *  - marginTop/Left/Right/Bottom: define the margin for the corresponding edge, if all of them are null, margin is not used in layout computing. Default Value is null for each.
          *  - hAlighment: define horizontal alignment of the Canvas, alignment is optional, default value null: no alignment.
          *  - vAlighment: define horizontal alignment of the Canvas, alignment is optional, default value null: no alignment.
          */
-        public static Create(parent: Prim2DBase, texture: Texture, options: { id?: string, position?: Vector2, x?: number, y?: number, origin?: Vector2, spriteSize?: Size, spriteLocation?: Vector2, invertY?: boolean, isVisible?: boolean, marginTop?: number, marginLeft?: number, marginRight?: number, marginBottom?: number, vAlignment?: number, hAlignment?: number}): Sprite2D {
+        public static Create(parent: Prim2DBase, texture: Texture, options: { id?: string, position?: Vector2, x?: number, y?: number, origin?: Vector2, spriteSize?: Size, spriteLocation?: Vector2, invertY?: boolean, alignToPixel?: boolean, isVisible?: boolean, marginTop?: number, marginLeft?: number, marginRight?: number, marginBottom?: number, vAlignment?: number, hAlignment?: number}): Sprite2D {
             Prim2DBase.CheckParent(parent);
 
             let sprite = new Sprite2D();
             if (!options) {
-                sprite.setupSprite2D(parent.owner, parent, null, Vector2.Zero(), null, texture, null, null, false, true, null, null, null, null, null, null);
+                sprite.setupSprite2D(parent.owner, parent, null, Vector2.Zero(), null, texture, null, null, false, true, true, null, null, null, null, null, null);
             } else {
                 let pos = options.position || new Vector2(options.x || 0, options.y || 0);
-                sprite.setupSprite2D(parent.owner, parent, options.id || null, pos, options.origin || null, texture, options.spriteSize || null, options.spriteLocation || null, options.invertY || false, options.isVisible || true, options.marginTop || null, options.marginLeft || null, options.marginRight || null, options.marginBottom || null, options.vAlignment || null, options.hAlignment || null);
+                sprite.setupSprite2D
+                (
+                    parent.owner,
+                    parent,
+                    options.id || null,
+                    pos,
+                    options.origin || null,
+                    texture, options.spriteSize || null,
+                    options.spriteLocation || null,
+                    (options.invertY == null) ? false : options.invertY,
+                    (options.alignToPixel == null) ? true : options.alignToPixel,
+                    (options.isVisible == null) ? true : options.isVisible,
+                    options.marginTop || null,
+                    options.marginLeft || null,
+                    options.marginRight || null,
+                    options.marginBottom || null,
+                    options.vAlignment || null,
+                    options.hAlignment || null
+                );
             }
 
             return sprite;
@@ -244,7 +272,7 @@
         static _createCachedCanvasSprite(owner: Canvas2D, texture: MapTexture, size: Size, pos: Vector2): Sprite2D {
 
             let sprite = new Sprite2D();
-            sprite.setupSprite2D(owner, null, "__cachedCanvasSprite__", new Vector2(0, 0), null, texture, size, pos, false, true, null, null, null, null, null, null);
+            sprite.setupSprite2D(owner, null, "__cachedCanvasSprite__", new Vector2(0, 0), null, texture, size, pos, false, true, true, null, null, null, null, null, null);
 
             return sprite;
         }
@@ -292,6 +320,8 @@
             return [new Sprite2DInstanceData(Sprite2D.SPRITE2D_MAINPARTID)];
         }
 
+        private static _prop: Vector3 = Vector3.Zero();
+
         protected refreshInstanceDataPart(part: InstanceDataBase): boolean {
             if (!super.refreshInstanceDataPart(part)) {
                 return false;
@@ -305,9 +335,13 @@
                 d.topLeftUV = new Vector2(sl.x / ts.width, sl.y / ts.height);
                 let suv = new Vector2(ss.width / ts.width, ss.height / ts.height);
                 d.sizeUV = suv;
-                d.frame = this.spriteFrame;
+
+                Sprite2D._prop.x = this.spriteFrame;
+                Sprite2D._prop.y = this.invertY ? 1 : 0;
+                Sprite2D._prop.z = this.alignToPixel ? 1 : 0;
+                d.properties = Sprite2D._prop;
+
                 d.textureSize = new Vector2(ts.width, ts.height);
-                d.invertY = this.invertY ? 1 : 0;
             }
             return true;
         }
@@ -317,6 +351,7 @@
         private _location: Vector2;
         private _spriteFrame: number;
         private _invertY: boolean;
+        private _alignToPixel: boolean;
     }
 
 

+ 19 - 1
src/Canvas2d/babylon.text2d.ts

@@ -239,7 +239,25 @@
                 text2d.setupText2D(parent.owner, parent, null, Vector2.Zero(), null, "12pt Arial", text, null, new Color4(1,1,1,1), 4, true, null, null, null, null, null, null);
             } else {
                 let pos = options.position || new Vector2(options.x || 0, options.y || 0);
-                text2d.setupText2D(parent.owner, parent, options.id || null, pos, options.origin || null, options.fontName || "12pt Arial", text, options.areaSize, options.defaultFontColor || new Color4(1, 1, 1, 1), options.tabulationSize || 4, options.isVisible || true, options.marginTop || null, options.marginLeft || null, options.marginRight || null, options.marginBottom || null, options.vAlignment || null, options.hAlignment || null);
+                text2d.setupText2D
+                (
+                    parent.owner,
+                    parent,
+                    options.id || null,
+                    pos,
+                    options.origin || null,
+                    options.fontName || "12pt Arial",
+                    text,
+                    options.areaSize,
+                    options.defaultFontColor || new Color4(1, 1, 1, 1),
+                    (options.tabulationSize==null) ? 4 : options.tabulationSize,
+                    (options.isVisible==null) ? true : options.isVisible,
+                    options.marginTop || null,
+                    options.marginLeft || null,
+                    options.marginRight || null,
+                    options.marginBottom || null,
+                    options.vAlignment || null,
+                    options.hAlignment || null);
             }
             return text2d;
         }

+ 15 - 3
src/Shaders/sprite2d.vertex.fx

@@ -12,8 +12,10 @@ att vec2 topLeftUV;
 att vec2 sizeUV;
 att vec2 origin;
 att vec2 textureSize;
-att float frame;
-att float invertY;
+
+// x: frame, y: invertY, z: alignToPixel
+att vec3 properties;
+
 att vec2 zBias;
 att vec4 transformX;
 att vec4 transformY;
@@ -31,6 +33,10 @@ void main(void) {
 	//vec2 off = vec2(1.0 / textureSize.x, 1.0 / textureSize.y);
 	vec2 off = vec2(0.0, 0.0);
 
+	float frame = properties.x;
+	float invertY = properties.y;
+	float alignToPixel = properties.z;
+
 	// Left/Top
 	if (index == 0.0) {
 		pos2 = vec2(0.0, 0.0);
@@ -60,7 +66,13 @@ void main(void) {
 	}
 
 	vec4 pos;
-	pos.xy = (pos2.xy * sizeUV * textureSize) - origin;
+	if (alignToPixel == 1.0)
+	{
+		pos.xy = floor((pos2.xy * sizeUV * textureSize) - origin);
+	} else {
+		pos.xy = (pos2.xy * sizeUV * textureSize) - origin;
+	}
+
 	pos.z = 1.0;
 	pos.w = 1.0;
 	gl_Position = vec4(dot(pos, transformX), dot(pos, transformY), zBias.x, 1);