///
module BABYLON.GUI {
export class AdvancedDynamicTexture extends DynamicTexture {
private _isDirty = false;
private _renderObserver: Observer;
private _resizeObserver: Observer;
private _pointerMoveObserver: Observer;
private _pointerObserver: Observer;
private _background: string;
public _rootContainer = new Container("root");
public _lastControlOver: Control;
public _lastControlDown: Control;
public _shouldBlockPointer: boolean;
public _layerToDispose: Layer;
public _linkedControls = new Array();
private _isFullscreen = false;
private _fullscreenViewport = new Viewport(0, 0, 1, 1);
private _idealWidth = 0;
private _idealHeight = 0;
public get background(): string {
return this._background;
}
public set background(value: string) {
if (this._background === value) {
return;
}
this._background = value;
this.markAsDirty();
}
public get idealWidth(): number {
return this._idealWidth;
}
public set idealWidth(value: number) {
if (this._idealWidth === value) {
return;
}
this._idealWidth = value;
this.markAsDirty();
this._rootContainer._markAllAsDirty();
}
public get idealHeight(): number {
return this._idealHeight;
}
public set idealHeight(value: number) {
if (this._idealHeight === value) {
return;
}
this._idealHeight = value;
this.markAsDirty();
this._rootContainer._markAllAsDirty();
}
constructor(name: string, width = 0, height = 0, scene: Scene, generateMipMaps = false, samplingMode = Texture.NEAREST_SAMPLINGMODE) {
super(name, {width: width, height: height}, scene, generateMipMaps, samplingMode, Engine.TEXTUREFORMAT_RGBA);
this._renderObserver = this.getScene().onBeforeCameraRenderObservable.add((camera: Camera) => this._checkUpdate(camera));
this._rootContainer._link(null, this);
this.hasAlpha = true;
if (!width || !height) {
this._resizeObserver = this.getScene().getEngine().onResizeObservable.add(() => this._onResize());
this._onResize();
}
}
public markAsDirty() {
this._isDirty = true;
}
public addControl(control: Control): AdvancedDynamicTexture {
this._rootContainer.addControl(control);
return this;
}
public removeControl(control: Control): AdvancedDynamicTexture {
this._rootContainer.removeControl(control);
return this;
}
public dispose() {
this.getScene().onBeforeCameraRenderObservable.remove(this._renderObserver);
if (this._resizeObserver) {
this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
}
if (this._pointerMoveObserver) {
this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
}
if (this._pointerObserver) {
this.getScene().onPointerObservable.remove(this._pointerObserver);
}
if (this._layerToDispose) {
this._layerToDispose.texture = null;
this._layerToDispose.dispose();
this._layerToDispose = null;
}
super.dispose();
}
private _onResize(): void {
// Check size
var engine = this.getScene().getEngine();
var textureSize = this.getSize();
var renderWidth = engine.getRenderWidth();
var renderHeight = engine.getRenderHeight();
if (textureSize.width !== renderWidth || textureSize.height !== renderHeight) {
this.scaleTo(renderWidth, renderHeight);
this.markAsDirty();
}
}
private _checkUpdate(camera: Camera): void {
if (this._isFullscreen && this._linkedControls.length) {
var scene = this.getScene();
var engine = scene.getEngine();
var globalViewport = this._fullscreenViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
for (var control of this._linkedControls) {
var mesh = control._linkedMesh;
var position = mesh.getBoundingInfo().boundingSphere.center;
var projectedPosition = Vector3.Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
control._moveToProjectedPosition(projectedPosition);
}
}
if (!this._isDirty && !this._rootContainer.isDirty) {
return;
}
this._isDirty = false;
this._render();
this.update();
}
private _render(): void {
var textureSize = this.getSize();
var renderWidth = textureSize.width;
var renderHeight = textureSize.height;
// Clear
var context = this.getContext();
context.clearRect(0, 0, renderWidth, renderHeight);
if (this._background) {
context.save();
context.fillStyle = this._background;
context.fillRect(0, 0, renderWidth, renderHeight);
context.restore();
}
// Render
context.font = "18px Arial";
var measure = new Measure(0, 0, renderWidth, renderHeight);
this._rootContainer._draw(measure, context);
}
private _doPicking(x: number, y: number, type: number): void {
if (!this._rootContainer._processPicking(x, y, type)) {
if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
if (this._lastControlOver && this._lastControlOver.onPointerOutObservable.hasObservers()) {
this._lastControlOver.onPointerOutObservable.notifyObservers(this._lastControlOver);
}
this._lastControlOver = null;
}
}
}
public attach(): void {
var scene = this.getScene();
this._pointerMoveObserver = scene.onPrePointerObservable.add((pi, state) => {
if (pi.type !== BABYLON.PointerEventTypes.POINTERMOVE
&& pi.type !== BABYLON.PointerEventTypes.POINTERUP
&& pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
return;
}
this._shouldBlockPointer = false;
this._doPicking(scene.pointerX, scene.pointerY, pi.type);
pi.skipOnPointerObservable = this._shouldBlockPointer && pi.type !== BABYLON.PointerEventTypes.POINTERUP;
});
}
public attachToMesh(mesh: AbstractMesh): void {
var scene = this.getScene();
this._pointerObserver = scene.onPointerObservable.add((pi, state) => {
if (pi.type !== BABYLON.PointerEventTypes.POINTERUP && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
return;
}
if (pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
var uv = pi.pickInfo.getTextureCoordinates();
var size = this.getSize();
this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi.type);
}
});
}
// Statics
public static CreateForMesh(mesh: AbstractMesh, width = 1024, height = 1024): AdvancedDynamicTexture {
var result = new AdvancedDynamicTexture(mesh.name + " AdvancedDynamicTexture", width, height, mesh.getScene(), true, Texture.TRILINEAR_SAMPLINGMODE);
var material = new BABYLON.StandardMaterial("AdvancedDynamicTextureMaterial", mesh.getScene());
material.backFaceCulling = false;
material.diffuseColor = BABYLON.Color3.Black();
material.specularColor = BABYLON.Color3.Black();
material.emissiveTexture = result;
material.opacityTexture = result;
mesh.material = material;
result.attachToMesh(mesh);
return result;
}
public static CreateFullscreenUI(name: string, foreground: boolean = true, scene: Scene = null): AdvancedDynamicTexture {
var result = new AdvancedDynamicTexture(name, 0, 0, scene);
// Display
var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
layer.texture = result;
result._layerToDispose = layer;
result._isFullscreen = true;
// Attach
result.attach();
return result;
}
}
}