소스 검색

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 년 전
부모
커밋
7c6cf59037

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

@@ -25,6 +25,12 @@
      */
      */
     export interface IBrush2D extends ILockable {
     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
          * 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
          * @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
          * 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.
          * @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();
                 this.lock();
             }
             }
         }
         }
+
+        isTransparent(): boolean {
+            return (this._color1 && this._color1.a < 1.0) || (this._color2 && this._color2.a < 1.0);
+        }
+
+
         public get color1(): Color4 {
         public get color1(): Color4 {
             return this._color1;
             return this._color1;
         }
         }

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

@@ -91,14 +91,15 @@
             this._engine = scene.getEngine();
             this._engine = scene.getEngine();
             this._renderingSize = new Size(0, 0);
             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;
             this._isScreeSpace = isScreenSpace;
 
 
             if (this._isScreeSpace) {
             if (this._isScreeSpace) {
                 this._afterRenderObserver = this._scene.onAfterRenderObservable.add((d, s) => {
                 this._afterRenderObserver = this._scene.onAfterRenderObservable.add((d, s) => {
+                    this._engine.clear(null, false, true);
                     this.render();
                     this.render();
                 });
                 });
             } else {
             } else {
@@ -183,14 +184,14 @@
          * Property that defines the border object used to draw the background of the Canvas.
          * 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.
          * @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) {
             if (!this._background || !this._background.isVisible) {
                 return null;
                 return null;
             }
             }
             return this._background.border;
             return this._background.border;
         }
         }
 
 
-        public set border(value: IBrush2D) {
+        public set backgroundBorder(value: IBrush2D) {
             this.checkBackgroundAvailability();
             this.checkBackgroundAvailability();
 
 
             if (value === this._background.border) {
             if (value === this._background.border) {
@@ -201,6 +202,24 @@
             this._background.isVisible = true;
             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() {
         private checkBackgroundAvailability() {
             if (this._cachingStrategy === Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
             if (this._cachingStrategy === Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
                 throw Error("Can't use Canvas Background with the caching strategy 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 {
     export class ModelRenderCache {
-        constructor() {
+        constructor(modelKey: string, isTransparent: boolean) {
+            this._modelKey = modelKey;
+            this._isTransparent = isTransparent;
             this._nextKey = 1;
             this._nextKey = 1;
             this._instancesData = new StringDictionary<InstanceDataBase[]>();
             this._instancesData = new StringDictionary<InstanceDataBase[]>();
         }
         }
@@ -145,6 +147,12 @@
             });
             });
         }
         }
 
 
+        private _modelKey: string;
+        private _isTransparent: boolean;
+
+        public get isTransparent() {
+            return this._isTransparent;
+        }
 
 
         _instancesData: StringDictionary<InstanceDataBase[]>;
         _instancesData: StringDictionary<InstanceDataBase[]>;
 
 

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

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

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

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

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

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

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

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

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

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

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

@@ -6,5 +6,5 @@ uniform sampler2D diffuseSampler;
 
 
 void main(void) {
 void main(void) {
 	vec4 color = texture2D(diffuseSampler, vUV);
 	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 sizeUV;
 att vec2 origin;
 att vec2 origin;
 att vec2 textureSize;
 att vec2 textureSize;
+att vec4 color;
 
 
 // Output
 // Output
 varying vec2 vUV;
 varying vec2 vUV;
@@ -49,6 +50,7 @@ void main(void) {
 		vUV = vec2(topLeftUV.x + sizeUV.x, topLeftUV.y + sizeUV.y);
 		vUV = vec2(topLeftUV.x + sizeUV.x, topLeftUV.y + sizeUV.y);
 	}
 	}
 
 
+	vColor = color;
 	vec4 pos;
 	vec4 pos;
 	pos.xy = (pos2.xy - origin) * sizeUV * textureSize;
 	pos.xy = (pos2.xy - origin) * sizeUV * textureSize;
 	pos.z = 1.0;
 	pos.z = 1.0;