Browse Source

Added support for Transparency in Brushes
Canvas2D now has its background again.
Transparency is detected by Shape2D and maintained automatically.
Transparency supported down to the ModelRenderCache.
Rectangle2D now render with alpha blending on if needed.
Added defaultFontColor to Text2D

nockawa 9 years ago
parent
commit
7c6cf59037

+ 16 - 0
src/Canvas2d/babylon.brushes2d.ts

@@ -25,6 +25,12 @@
      */
     export interface IBrush2D extends ILockable {
         /**
+         * Define if the brush will use transparency/alphablending
+         * @returns true if the brush use transparency
+         */
+        isTransparent(): boolean;
+
+        /**
          * It is critical for each instance of a given Brush2D type to return a unique string that identifies it because the Border instance will certainly be part of the computed ModelKey for a given Primitive
          * @returns A string identifier that uniquely identify the instance
          */
@@ -75,6 +81,10 @@
             }
         }
 
+        isTransparent(): boolean {
+            return this._color && this._color.a < 1.0;
+        }
+
         /**
          * The color used by this instance to render
          * @returns the color object. Note that it's not a clone of the actual object stored in the instance so you MUST NOT modify it, otherwise unexpected behavior might occurs.
@@ -115,6 +125,12 @@
                 this.lock();
             }
         }
+
+        isTransparent(): boolean {
+            return (this._color1 && this._color1.a < 1.0) || (this._color2 && this._color2.a < 1.0);
+        }
+
+
         public get color1(): Color4 {
             return this._color1;
         }

+ 25 - 6
src/Canvas2d/babylon.canvas2d.ts

@@ -91,14 +91,15 @@
             this._engine = scene.getEngine();
             this._renderingSize = new Size(0, 0);
 
-            //if (cachingstrategy !== Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
-            //    this._background = Rectangle2D.Create(this, "###CANVAS BACKGROUND###", 0, 0, size.width, size.height);
-            //    this._background.levelVisible = false;
-            //}
+            if (cachingstrategy !== Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
+                this._background = Rectangle2D.Create(this, "###CANVAS BACKGROUND###", 0, 0, size.width, size.height);
+                this._background.origin = Vector2.Zero();
+            }
             this._isScreeSpace = isScreenSpace;
 
             if (this._isScreeSpace) {
                 this._afterRenderObserver = this._scene.onAfterRenderObservable.add((d, s) => {
+                    this._engine.clear(null, false, true);
                     this.render();
                 });
             } else {
@@ -183,14 +184,14 @@
          * Property that defines the border object used to draw the background of the Canvas.
          * @returns If the background is not set, null will be returned, otherwise a valid border object is returned.
          */
-        public get border(): IBrush2D {
+        public get backgroundBorder(): IBrush2D {
             if (!this._background || !this._background.isVisible) {
                 return null;
             }
             return this._background.border;
         }
 
-        public set border(value: IBrush2D) {
+        public set backgroundBorder(value: IBrush2D) {
             this.checkBackgroundAvailability();
 
             if (value === this._background.border) {
@@ -201,6 +202,24 @@
             this._background.isVisible = true;
         }
 
+        public get backgroundRoundRadius(): number {
+            if (!this._background || !this._background.isVisible) {
+                return null;
+            }
+            return this._background.roundRadius;
+        }
+
+        public set backgroundRoundRadius(value: number) {
+            this.checkBackgroundAvailability();
+
+            if (value === this._background.roundRadius) {
+                return;
+            }
+
+            this._background.roundRadius = value;
+            this._background.isVisible = true;
+        }
+
         private checkBackgroundAvailability() {
             if (this._cachingStrategy === Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
                 throw Error("Can't use Canvas Background with the caching strategy TOPLEVELGROUPS");

+ 9 - 1
src/Canvas2d/babylon.modelRenderCache.ts

@@ -25,7 +25,9 @@
     }
 
     export class ModelRenderCache {
-        constructor() {
+        constructor(modelKey: string, isTransparent: boolean) {
+            this._modelKey = modelKey;
+            this._isTransparent = isTransparent;
             this._nextKey = 1;
             this._instancesData = new StringDictionary<InstanceDataBase[]>();
         }
@@ -145,6 +147,12 @@
             });
         }
 
+        private _modelKey: string;
+        private _isTransparent: boolean;
+
+        public get isTransparent() {
+            return this._isTransparent;
+        }
 
         _instancesData: StringDictionary<InstanceDataBase[]>;
 

+ 17 - 2
src/Canvas2d/babylon.rectangle2d.ts

@@ -12,6 +12,9 @@
         instancingBorderAttributes: InstancingAttributeInfo[];
         effectBorder: Effect;
 
+        constructor(modelKey: string, isTransparent: boolean) {
+            super(modelKey, isTransparent);
+        }
 
         render(instanceInfo: GroupInstanceInfo, context: Render2DContext): boolean {
             // Do nothing if the shader is still loading/preparing
@@ -26,6 +29,13 @@
                 depthFunction = engine.getDepthFunction();
                 engine.setDepthFunctionToLessOrEqual();
             }
+
+            var cur: number;
+            if (this.isTransparent) {
+                cur = engine.getAlphaMode();
+                engine.setAlphaMode(Engine.ALPHA_COMBINE);
+            }
+
             if (this.effectFill) {
                 let partIndex = instanceInfo._partIndexFromId.get(Shape2D.SHAPE2D_FILLPARTID.toString());
 
@@ -70,6 +80,11 @@
                     }
                 }
             }
+
+            if (this.isTransparent) {
+                engine.setAlphaMode(cur);
+            }
+
             if (this.effectFill && this.effectBorder) {
                 engine.setDepthFunction(depthFunction);
             }
@@ -156,8 +171,8 @@
 
         public static roundSubdivisions = 16;
 
-        protected createModelRenderCache(): ModelRenderCache {
-            let renderCache = new Rectangle2DRenderCache();
+        protected createModelRenderCache(modelKey: string, isTransparent: boolean): ModelRenderCache {
+            let renderCache = new Rectangle2DRenderCache(modelKey, isTransparent);
             return renderCache;
         }
 

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

@@ -290,6 +290,17 @@
     export class RenderablePrim2D extends Prim2DBase {
         static RENDERABLEPRIM2D_PROPCOUNT: number = Prim2DBase.PRIM2DBASE_PROPCOUNT + 5;
 
+        public static isTransparentProperty: Prim2DPropInfo;
+
+        @modelLevelProperty(Prim2DBase.PRIM2DBASE_PROPCOUNT + 1, pi => RenderablePrim2D.isTransparentProperty = pi)
+        public get isTransparent(): boolean {
+            return this._isTransparent;
+        }
+
+        public set isTransparent(value: boolean) {
+            this._isTransparent = value;
+        }
+
         setupRenderablePrim2D(owner: Canvas2D, parent: Prim2DBase, id: string, position: Vector2, isVisible: boolean) {
             this.setupPrim2DBase(owner, parent, id, position);
             this._isTransparent = false;
@@ -308,7 +319,7 @@
             let setupModelRenderCache = false;
             if (!this._modelRenderCache || this._modelDirty) {
                 this._modelRenderCache = SmartPropertyPrim.GetOrAddModelCache(this.modelKey, (key: string) => {
-                    let mrc = this.createModelRenderCache();
+                    let mrc = this.createModelRenderCache(key, this.isTransparent);
                     setupModelRenderCache = true;
                     return mrc;
                 });
@@ -437,15 +448,11 @@
             return { attributes: instancedArray ? vertexBufferAttributes.concat(att) : vertexBufferAttributes, uniforms: instancedArray ? [] : att, defines: defines };
         }
 
-        public get isTransparent(): boolean {
-            return this._isTransparent;
-        }
-
         protected get modelRenderCache(): ModelRenderCache {
             return this._modelRenderCache;
         }
 
-        protected createModelRenderCache(): ModelRenderCache {
+        protected createModelRenderCache(modelKey: string, isTransparent: boolean): ModelRenderCache {
             return null;
         }
 

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

@@ -22,6 +22,7 @@
 
         public set border(value: IBrush2D) {
             this._border = value;
+            this._updateTransparencyStatus();
         }
 
         @modelLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, pi => Shape2D.fillProperty = pi, true)
@@ -31,6 +32,7 @@
 
         public set fill(value: IBrush2D) {
             this._fill = value;
+            this._updateTransparencyStatus();
         }
 
         @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Shape2D.borderThicknessProperty = pi)
@@ -128,9 +130,14 @@
             return true;
         }
 
+        private _updateTransparencyStatus() {
+            this.isTransparent = (this._border && this._border.isTransparent()) || (this._fill && this._fill.isTransparent());
+        }
+
         private _border: IBrush2D;
         private _borderThickness: number;
         private _fill: IBrush2D;
+
     }
 
     export class Shape2DInstanceData extends InstanceDataBase {

+ 2 - 2
src/Canvas2d/babylon.sprite2d.ts

@@ -156,8 +156,8 @@
             return sprite;
         }
 
-        protected createModelRenderCache(): ModelRenderCache {
-            let renderCache = new Sprite2DRenderCache();
+        protected createModelRenderCache(modelKey: string, isTransparent: boolean): ModelRenderCache {
+            let renderCache = new Sprite2DRenderCache(modelKey, isTransparent);
             return renderCache;
         }
 

+ 27 - 9
src/Canvas2d/babylon.text2d.ts

@@ -66,6 +66,11 @@
         get textureSize(): Vector2 {
             return null;
         }
+
+        @instanceData()
+        get color(): Color4 {
+            return null;
+        }
     }
 
     @className("Text2D")
@@ -73,6 +78,7 @@
         static TEXT2D_MAINPARTID = 1;
 
         public static fontProperty: Prim2DPropInfo;
+        public static defaultFontColorProperty: Prim2DPropInfo;
         public static textProperty: Prim2DPropInfo;
         public static areaSizeProperty: Prim2DPropInfo;
         public static vAlignProperty: Prim2DPropInfo;
@@ -97,7 +103,16 @@
             this._fontName = value;
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, pi => Text2D.textProperty = pi, false, true)
+        @dynamicLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 2, pi => Text2D.defaultFontColorProperty = pi)
+        public get defaultFontColor(): Color4 {
+            return this._defaultFontColor;
+        }
+
+        public set defaultFontColor(value: Color4) {
+            this._defaultFontColor = value;
+        }
+
+        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Text2D.textProperty = pi, false, true)
         public get text(): string {
             return this._text;
         }
@@ -108,7 +123,7 @@
             this._updateCharCount();
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 3, pi => Text2D.areaSizeProperty = pi)
+        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, pi => Text2D.areaSizeProperty = pi)
         public get areaSize(): Size {
             return this._areaSize;
         }
@@ -117,7 +132,7 @@
             this._areaSize = value;
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 4, pi => Text2D.vAlignProperty = pi)
+        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5, pi => Text2D.vAlignProperty = pi)
         public get vAlign(): number {
             return this._vAlign;
         }
@@ -126,7 +141,7 @@
             this._vAlign = value;
         }
 
-        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 5, pi => Text2D.hAlignProperty = pi)
+        @instanceLevelProperty(RenderablePrim2D.RENDERABLEPRIM2D_PROPCOUNT + 6, pi => Text2D.hAlignProperty = pi)
         public get hAlign(): number {
             return this._hAlign;
         }
@@ -175,10 +190,11 @@
             BoundingInfo2D.ConstructFromSizeToRef(this.actualAreaSize, this._levelBoundingInfo);
         }
 
-        protected setupText2D(owner: Canvas2D, parent: Prim2DBase, id: string, position: Vector2, fontName: string, text: string, areaSize: Size, vAlign, hAlign, tabulationSize: number) {
+        protected setupText2D(owner: Canvas2D, parent: Prim2DBase, id: string, position: Vector2, fontName: string, text: string, areaSize: Size, defaultFontColor: Color4, vAlign, hAlign, tabulationSize: number) {
             this.setupRenderablePrim2D(owner, parent, id, position, true);
 
             this.fontName = fontName;
+            this.defaultFontColor = defaultFontColor;
             this.text = text;
             this.areaSize = areaSize;
             this.vAlign = vAlign;
@@ -188,16 +204,16 @@
             this.origin = Vector2.Zero();
         }
 
-        public static Create(parent: Prim2DBase, id: string, x: number, y: number, fontName: string, text: string, areaSize?: Size, vAlign = Text2D.TEXT2D_VALIGN_TOP, hAlign = Text2D.TEXT2D_HALIGN_LEFT, tabulationSize: number = 4): Text2D {
+        public static Create(parent: Prim2DBase, id: string, x: number, y: number, fontName: string, text: string, defaultFontColor?: Color4, areaSize?: Size, vAlign = Text2D.TEXT2D_VALIGN_TOP, hAlign = Text2D.TEXT2D_HALIGN_LEFT, tabulationSize: number = 4): Text2D {
             Prim2DBase.CheckParent(parent);
 
             let text2d = new Text2D();
-            text2d.setupText2D(parent.owner, parent, id, new Vector2(x, y), fontName, text, areaSize, vAlign, hAlign, tabulationSize);
+            text2d.setupText2D(parent.owner, parent, id, new Vector2(x, y), fontName, text, areaSize, defaultFontColor || new Color4(0,0,0,1), vAlign, hAlign, tabulationSize);
             return text2d;
         }
 
-        protected createModelRenderCache(): ModelRenderCache {
-            let renderCache = new Text2DRenderCache();
+        protected createModelRenderCache(modelKey: string, isTransparent: boolean): ModelRenderCache {
+            let renderCache = new Text2DRenderCache(modelKey, isTransparent);
             return renderCache;
         }
 
@@ -280,6 +296,7 @@
                     let suv = ci.bottomRightUV.subtract(ci.topLeftUV);
                     d.sizeUV = suv;
                     d.textureSize = new Vector2(ts.width, ts.height);
+                    d.color = this.defaultFontColor;
 
                     ++d.curElement;
                 }
@@ -302,6 +319,7 @@
         private _tabulationSize: number;
         private _charCount: number;
         private _fontName: string;
+        private _defaultFontColor: Color4;
         private _text: string;
         private _areaSize: Size;
         private _actualAreaSize: Size;

+ 1 - 1
src/Shaders/text2d.fragment.fx

@@ -6,5 +6,5 @@ uniform sampler2D diffuseSampler;
 
 void main(void) {
 	vec4 color = texture2D(diffuseSampler, vUV);
-	gl_FragColor = vec4(color.xyz*vColor.xyz, color.w);
+	gl_FragColor = color*vColor;
 }

+ 2 - 0
src/Shaders/text2d.vertex.fx

@@ -16,6 +16,7 @@ att vec2 topLeftUV;
 att vec2 sizeUV;
 att vec2 origin;
 att vec2 textureSize;
+att vec4 color;
 
 // Output
 varying vec2 vUV;
@@ -49,6 +50,7 @@ void main(void) {
 		vUV = vec2(topLeftUV.x + sizeUV.x, topLeftUV.y + sizeUV.y);
 	}
 
+	vColor = color;
 	vec4 pos;
 	pos.xy = (pos2.xy - origin) * sizeUV * textureSize;
 	pos.z = 1.0;