export class Layers3DView extends UI.VBox{constructor(layerViewHost){super(true);this.registerRequiredCSS('layer_viewer/layers3DView.css');this.contentElement.classList.add('layers-3d-view');this._failBanner=new UI.VBox();this._failBanner.element.classList.add('full-widget-dimmed-banner');this._failBanner.element.createTextChild(Common.UIString('Layer information is not yet available.'));this._layerViewHost=layerViewHost;this._layerViewHost.registerView(this);this._transformController=new LayerViewer.TransformController(this.contentElement);this._transformController.addEventListener(LayerViewer.TransformController.Events.TransformChanged,this._update,this);this._initToolbar();this._canvasElement=this.contentElement.createChild('canvas');this._canvasElement.tabIndex=0;this._canvasElement.addEventListener('dblclick',this._onDoubleClick.bind(this),false);this._canvasElement.addEventListener('mousedown',this._onMouseDown.bind(this),false);this._canvasElement.addEventListener('mouseup',this._onMouseUp.bind(this),false);this._canvasElement.addEventListener('mouseleave',this._onMouseMove.bind(this),false);this._canvasElement.addEventListener('mousemove',this._onMouseMove.bind(this),false);this._canvasElement.addEventListener('contextmenu',this._onContextMenu.bind(this),false);UI.ARIAUtils.setAccessibleName(this._canvasElement,ls`3D Layers View`);this._lastSelection={};this._layerTree=null;this._textureManager=new LayerTextureManager(this._update.bind(this));this._chromeTextures=[];this._rects=[];this._snapshotLayers=new Map();this._layerViewHost.setLayerSnapshotMap(this._snapshotLayers);this._layerViewHost.showInternalLayersSetting().addChangeListener(this._update,this);} setLayerTree(layerTree){this._layerTree=layerTree;this._layerTexture=null;delete this._oldTextureScale;if(this._showPaints()){this._textureManager.setLayerTree(layerTree);} this._update();} showImageForLayer(layer,imageURL){if(!imageURL){this._layerTexture=null;this._update();return;} UI.loadImage(imageURL).then(image=>{const texture=image&&LayerTextureManager._createTextureForImage(this._gl,image);this._layerTexture=texture?{layer:layer,texture:texture}:null;this._update();});} onResize(){this._resizeCanvas();this._update();} willHide(){this._textureManager.suspend();} wasShown(){this._textureManager.resume();if(!this._needsUpdate){return;} this._resizeCanvas();this._update();} updateLayerSnapshot(layer){this._textureManager.layerNeedsUpdate(layer);} _setOutline(type,selection){this._lastSelection[type]=selection;this._update();} hoverObject(selection){this._setOutline(OutlineType.Hovered,selection);} selectObject(selection){this._setOutline(OutlineType.Hovered,null);this._setOutline(OutlineType.Selected,selection);} snapshotForSelection(selection){if(selection.type()===LayerViewer.LayerView.Selection.Type.Snapshot){const snapshotWithRect=(selection).snapshot();snapshotWithRect.snapshot.addReference();return(Promise.resolve(snapshotWithRect));} if(selection.layer()){const promise=selection.layer().snapshots()[0];if(promise){return promise;}} return(Promise.resolve(null));} _initGL(canvas){const gl=canvas.getContext('webgl');if(!gl){return null;} gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);gl.enable(gl.BLEND);gl.clearColor(0.0,0.0,0.0,0.0);gl.enable(gl.DEPTH_TEST);return gl;} _createShader(type,script){const shader=this._gl.createShader(type);this._gl.shaderSource(shader,script);this._gl.compileShader(shader);this._gl.attachShader(this._shaderProgram,shader);} _initShaders(){this._shaderProgram=this._gl.createProgram();this._createShader(this._gl.FRAGMENT_SHADER,FragmentShader);this._createShader(this._gl.VERTEX_SHADER,VertexShader);this._gl.linkProgram(this._shaderProgram);this._gl.useProgram(this._shaderProgram);this._shaderProgram.vertexPositionAttribute=this._gl.getAttribLocation(this._shaderProgram,'aVertexPosition');this._gl.enableVertexAttribArray(this._shaderProgram.vertexPositionAttribute);this._shaderProgram.vertexColorAttribute=this._gl.getAttribLocation(this._shaderProgram,'aVertexColor');this._gl.enableVertexAttribArray(this._shaderProgram.vertexColorAttribute);this._shaderProgram.textureCoordAttribute=this._gl.getAttribLocation(this._shaderProgram,'aTextureCoord');this._gl.enableVertexAttribArray(this._shaderProgram.textureCoordAttribute);this._shaderProgram.pMatrixUniform=this._gl.getUniformLocation(this._shaderProgram,'uPMatrix');this._shaderProgram.samplerUniform=this._gl.getUniformLocation(this._shaderProgram,'uSampler');} _resizeCanvas(){this._canvasElement.width=this._canvasElement.offsetWidth*window.devicePixelRatio;this._canvasElement.height=this._canvasElement.offsetHeight*window.devicePixelRatio;} _updateTransformAndConstraints(){const paddingFraction=0.1;const viewport=this._layerTree.viewportSize();const baseWidth=viewport?viewport.width:this._dimensionsForAutoscale.width;const baseHeight=viewport?viewport.height:this._dimensionsForAutoscale.height;const canvasWidth=this._canvasElement.width;const canvasHeight=this._canvasElement.height;const paddingX=canvasWidth*paddingFraction;const paddingY=canvasHeight*paddingFraction;const scaleX=(canvasWidth-2*paddingX)/baseWidth;const scaleY=(canvasHeight-2*paddingY)/baseHeight;const viewScale=Math.min(scaleX,scaleY);const minScaleConstraint=Math.min(baseWidth/this._dimensionsForAutoscale.width,baseHeight/this._dimensionsForAutoscale.width)/2;this._transformController.setScaleConstraints(minScaleConstraint,10/viewScale);const scale=this._transformController.scale();const rotateX=this._transformController.rotateX();const rotateY=this._transformController.rotateY();this._scale=scale*viewScale;const textureScale=Number.constrain(this._scale,0.1,1);if(textureScale!==this._oldTextureScale){this._oldTextureScale=textureScale;this._textureManager.setScale(textureScale);this.dispatchEventToListeners(Events.ScaleChanged,textureScale);} const scaleAndRotationMatrix=new WebKitCSSMatrix().scale(scale,scale,scale).translate(canvasWidth/2,canvasHeight/2,0).rotate(rotateX,rotateY,0).scale(viewScale,viewScale,viewScale).translate(-baseWidth/2,-baseHeight/2,0);let bounds;for(let i=0;i{this._chromeTextures[index]=image&&LayerTextureManager._createTextureForImage(this._gl,image)||undefined;});} loadChromeTexture.call(this,ChromeTexture.Left,'Images/chromeLeft.png');loadChromeTexture.call(this,ChromeTexture.Middle,'Images/chromeMiddle.png');loadChromeTexture.call(this,ChromeTexture.Right,'Images/chromeRight.png');} _initGLIfNecessary(){if(this._gl){return this._gl;} this._gl=this._initGL(this._canvasElement);if(!this._gl){return null;} this._initShaders();this._initWhiteTexture();this._initChromeTextures();this._textureManager.setContext(this._gl);return this._gl;} _calculateDepthsAndVisibility(){this._depthByLayerId={};let depth=0;const showInternalLayers=this._layerViewHost.showInternalLayersSetting().get();const root=showInternalLayers?this._layerTree.root():(this._layerTree.contentRoot()||this._layerTree.root());const queue=[root];this._depthByLayerId[root.id()]=0;this._visibleLayers=new Set();while(queue.length>0){const layer=queue.shift();if(showInternalLayers||layer.drawsContent()){this._visibleLayers.add(layer);} const children=layer.children();for(let i=0;i=3&&this._chromeTextures.indexOf(undefined)<0;const z=(this._maxDepth+1)*LayerSpacing;const borderWidth=Math.ceil(ViewportBorderWidth*this._scale);let vertices=[viewport.width,0,z,viewport.width,viewport.height,z,0,viewport.height,z,0,0,z];this._gl.lineWidth(borderWidth);this._drawRectangle(vertices,drawChrome?this._gl.LINE_STRIP:this._gl.LINE_LOOP,ViewportBorderColor);if(!drawChrome){return;} const borderAdjustment=ViewportBorderWidth/2;const viewportWidth=this._layerTree.viewportSize().width+2*borderAdjustment;const chromeHeight=this._chromeTextures[0].image.naturalHeight;const middleFragmentWidth=viewportWidth-this._chromeTextures[0].image.naturalWidth-this._chromeTextures[2].image.naturalWidth;let x=-borderAdjustment;const y=-chromeHeight;for(let i=0;iviewportWidth){break;} vertices=[x,y,z,x+width,y,z,x+width,y+chromeHeight,z,x,y+chromeHeight,z];this._drawTexture(vertices,(this._chromeTextures[i]));x+=width;}} _drawViewRect(rect){const vertices=rect.vertices;if(rect.texture){this._drawTexture(vertices,rect.texture,rect.fillColor||undefined);}else if(rect.fillColor){this._drawRectangle(vertices,this._gl.TRIANGLE_FAN,rect.fillColor);} this._gl.lineWidth(rect.lineWidth);if(rect.borderColor){this._drawRectangle(vertices,this._gl.LINE_LOOP,rect.borderColor);}} _update(){if(!this.isShowing()){this._needsUpdate=true;return;} if(!this._layerTree||!this._layerTree.root()){this._failBanner.show(this.contentElement);return;} const gl=this._initGLIfNecessary();if(!gl){this._failBanner.element.removeChildren();this._failBanner.element.appendChild(this._webglDisabledBanner());this._failBanner.show(this.contentElement);return;} this._failBanner.detach();this._gl.viewportWidth=this._canvasElement.width;this._gl.viewportHeight=this._canvasElement.height;this._calculateDepthsAndVisibility();this._calculateRects();this._updateTransformAndConstraints();gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight);gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);this._rects.forEach(this._drawViewRect.bind(this));this._drawViewportAndChrome();} _webglDisabledBanner(){const fragment=this.contentElement.ownerDocument.createDocumentFragment();fragment.createChild('div').textContent=Common.UIString('Can\'t display layers,');fragment.createChild('div').textContent=Common.UIString('WebGL support is disabled in your browser.');fragment.appendChild(UI.formatLocalized('Check %s for possible reasons.',[UI.XLink.create('about:gpu')]));return fragment;} _selectionFromEventPoint(event){if(!this._layerTree){return null;} let closestIntersectionPoint=Infinity;let closestObject=null;const projectionMatrix=new WebKitCSSMatrix().scale(1,-1,-1).translate(-1,-1,0).multiply(this._projectionMatrix);const x0=(event.clientX-this._canvasElement.totalOffsetLeft())*window.devicePixelRatio;const y0=-(event.clientY-this._canvasElement.totalOffsetTop())*window.devicePixelRatio;function checkIntersection(rect){if(!rect.relatedObject){return;} const t=rect.intersectWithLine(projectionMatrix,x0,y0);if(t{if(!layer.drawsContent()){return;} newLayers.add(layer);if(!this._tilesByLayer.has(layer)){this._tilesByLayer.set(layer,[]);this.layerNeedsUpdate(layer);}});} if(!oldLayers.length){this.forceUpdate();} for(const layer of oldLayers){if(newLayers.has(layer)){continue;} this._tilesByLayer.get(layer).forEach(tile=>tile.dispose());this._tilesByLayer.delete(layer);}} _setSnapshotsForLayer(layer,snapshots){const oldSnapshotsToTiles=new Map((this._tilesByLayer.get(layer)||[]).map(tile=>[tile.snapshot,tile]));const newTiles=[];const reusedTiles=[];for(const snapshot of snapshots){const oldTile=oldSnapshotsToTiles.get(snapshot);if(oldTile){reusedTiles.push(oldTile);oldSnapshotsToTiles.delete(oldTile);}else{newTiles.push(new Tile(snapshot));}} this._tilesByLayer.set(layer,reusedTiles.concat(newTiles));for(const tile of oldSnapshotsToTiles.values()){tile.dispose();} if(!this._gl||!this._scale){return Promise.resolve();} return Promise.all(newTiles.map(tile=>tile.update(this._gl,this._scale))).then(this._textureUpdatedCallback);} setScale(scale){if(this._scale&&this._scale>=scale){return;} this._scale=scale;this._updateTextures();} tilesForLayer(layer){return this._tilesByLayer.get(layer)||[];} layerNeedsUpdate(layer){if(this._queue.indexOf(layer)<0){this._queue.push(layer);} if(this._active){this._throttler.schedule(this._update.bind(this));}} forceUpdate(){this._queue.forEach(layer=>this._updateLayer(layer));this._queue=[];this._update();} _update(){const layer=this._queue.shift();if(!layer){return Promise.resolve();} if(this._queue.length){this._throttler.schedule(this._update.bind(this));} return this._updateLayer(layer);} _updateLayer(layer){return Promise.all(layer.snapshots()).then(snapshots=>this._setSnapshotsForLayer(layer,snapshots.filter(snapshot=>!!snapshot)));} _updateTextures(){if(!this._gl){return;} if(!this._scale){return;} for(const tiles of this._tilesByLayer.values()){for(const tile of tiles){const promise=tile.updateScale(this._gl,this._scale);if(promise){promise.then(this._textureUpdatedCallback);}}}}} export class Rectangle{constructor(relatedObject){this.relatedObject=relatedObject;this.lineWidth=1;this.borderColor=null;this.fillColor=null;this.texture=null;} setVertices(quad,z){this.vertices=[quad[0],quad[1],z,quad[2],quad[3],z,quad[4],quad[5],z,quad[6],quad[7],z];} _calculatePointOnQuad(quad,ratioX,ratioY){const x0=quad[0];const y0=quad[1];const x1=quad[2];const y1=quad[3];const x2=quad[4];const y2=quad[5];const x3=quad[6];const y3=quad[7];const firstSidePointX=x0+ratioX*(x1-x0);const firstSidePointY=y0+ratioX*(y1-y0);const thirdSidePointX=x3+ratioX*(x2-x3);const thirdSidePointY=y3+ratioX*(y2-y3);const x=firstSidePointX+ratioY*(thirdSidePointX-firstSidePointX);const y=firstSidePointY+ratioY*(thirdSidePointY-firstSidePointY);return[x,y];} calculateVerticesFromRect(layer,rect,z){const quad=layer.quad();const rx1=rect.x/layer.width();const rx2=(rect.x+rect.width)/layer.width();const ry1=rect.y/layer.height();const ry2=(rect.y+rect.height)/layer.height();const rectQuad=this._calculatePointOnQuad(quad,rx1,ry1).concat(this._calculatePointOnQuad(quad,rx2,ry1)).concat(this._calculatePointOnQuad(quad,rx2,ry2)).concat(this._calculatePointOnQuad(quad,rx1,ry2));this.setVertices(rectQuad,z);} intersectWithLine(matrix,x0,y0){let i;const points=[];for(i=0;i<4;++i){points[i]=UI.Geometry.multiplyVectorByMatrixAndNormalize(new UI.Geometry.Vector(this.vertices[i*3],this.vertices[i*3+1],this.vertices[i*3+2]),matrix);} const normal=UI.Geometry.crossProduct(UI.Geometry.subtract(points[1],points[0]),UI.Geometry.subtract(points[2],points[1]));const A=normal.x;const B=normal.y;const C=normal.z;const D=-(A*points[0].x+B*points[0].y+C*points[0].z);const t=-(D+A*x0+B*y0)/C;const pt=new UI.Geometry.Vector(x0,y0,t);const tVects=points.map(UI.Geometry.subtract.bind(null,pt));for(i=0;i=scale){return null;} return this.update(glContext,scale);} async update(glContext,scale){this._gl=glContext;this.scale=scale;const imageURL=await this.snapshot.replay(scale);const image=imageURL?await UI.loadImage(imageURL):null;this.texture=image?LayerTextureManager._createTextureForImage(glContext,image):null;}} self.LayerViewer=self.LayerViewer||{};LayerViewer=LayerViewer||{};LayerViewer.Layers3DView=Layers3DView;LayerViewer.Layers3DView.LayerStyle;LayerViewer.Layers3DView.OutlineType=OutlineType;LayerViewer.Layers3DView.Events=Events;LayerViewer.Layers3DView.ChromeTexture=ChromeTexture;LayerViewer.Layers3DView.ScrollRectTitles=ScrollRectTitles;LayerViewer.Layers3DView.FragmentShader=FragmentShader;LayerViewer.Layers3DView.VertexShader=VertexShader;LayerViewer.Layers3DView.HoveredBorderColor=HoveredBorderColor;LayerViewer.Layers3DView.SelectedBorderColor=SelectedBorderColor;LayerViewer.Layers3DView.BorderColor=BorderColor;LayerViewer.Layers3DView.ViewportBorderColor=ViewportBorderColor;LayerViewer.Layers3DView.ScrollRectBackgroundColor=ScrollRectBackgroundColor;LayerViewer.Layers3DView.HoveredImageMaskColor=HoveredImageMaskColor;LayerViewer.Layers3DView.BorderWidth=BorderWidth;LayerViewer.Layers3DView.SelectedBorderWidth=SelectedBorderWidth;LayerViewer.Layers3DView.ViewportBorderWidth=ViewportBorderWidth;LayerViewer.Layers3DView.LayerSpacing=LayerSpacing;LayerViewer.Layers3DView.ScrollRectSpacing=ScrollRectSpacing;LayerViewer.Layers3DView.Rectangle=Rectangle;LayerViewer.LayerTextureManager=LayerTextureManager;LayerViewer.LayerTextureManager.Tile=Tile;