Changeset 223209 in webkit


Ignore:
Timestamp:
Oct 11, 2017 1:54:56 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

Web Inspector: Make 3D objects selectable in Layers visualization
https://bugs.webkit.org/show_bug.cgi?id=178136

Patch by Ross Kirsling <Ross Kirsling> on 2017-10-11
Reviewed by Devin Rousso.

  • UserInterface/Views/Layers3DContentView.js:

(WI.Layers3DContentView):
(WI.Layers3DContentView.prototype.initialLayout):
(WI.Layers3DContentView.prototype._canvasMouseDown):
(WI.Layers3DContentView.prototype._updateLayerGroupSelection):
Implement selection of 3D layer objects.

(WI.Layers3DContentView.prototype._addLayerGroup): Renamed from _addLayer.
(WI.Layers3DContentView.prototype._updateLayerGroupPosition):
(WI.Layers3DContentView.prototype._createLayerMesh):
Refactor -- one group per layer (visible plane and composited outline), not groups by shape.

(WI.Layers3DContentView.prototype.layout):
(WI.Layers3DContentView.prototype._updateLayers):
(WI.Layers3DContentView.prototype._clearLayers): Deleted.
Don't destroy all 3D objects on every LayerTreeDidChange; make use of layerTreeMutations.
(Not only a performance improvement, but also necessary to properly preserve highlighting.)

(WI.Layers3DContentView.prototype.selectLayerById):
Allow selection to be updated from the outside.

  • UserInterface/Views/LayerDetailsSidebarPanel.js:

(WI.LayerDetailsSidebarPanel.prototype.selectNodeByLayerId):
(WI.LayerDetailsSidebarPanel.prototype._buildDataGrid):
(WI.LayerDetailsSidebarPanel.prototype._dataGridSelectedNodeChanged):
Allow selection to be updated from the outside.

(WI.LayerDetailsSidebarPanel.prototype.inspect):
(WI.LayerDetailsSidebarPanel.prototype._updateLayers): Renamed from _updateDisplayWithLayers.
(WI.LayerDetailsSidebarPanel.prototype._updateDataGrid):
(WI.LayerDetailsSidebarPanel.prototype._updateBottomBar):
(WI.LayerDetailsSidebarPanel.prototype._contentForPopover):
(WI.LayerDetailsSidebarPanel.prototype._dataGridNodeForLayer): Deleted.
Cleanup.

  • UserInterface/Views/LayersTabContentView.js:

(WI.LayersTabContentView):
(WI.LayersTabContentView.prototype._detailsSidebarSelectedLayerChanged):
(WI.LayersTabContentView.prototype._contentViewSelectedLayerChanged):
Orchestrate communication of selection state between visualization and sidebar.

Location:
trunk/Source/WebInspectorUI
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r223171 r223209  
     12017-10-11  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        Web Inspector: Make 3D objects selectable in Layers visualization
     4        https://bugs.webkit.org/show_bug.cgi?id=178136
     5
     6        Reviewed by Devin Rousso.
     7
     8        * UserInterface/Views/Layers3DContentView.js:
     9        (WI.Layers3DContentView):
     10        (WI.Layers3DContentView.prototype.initialLayout):
     11        (WI.Layers3DContentView.prototype._canvasMouseDown):
     12        (WI.Layers3DContentView.prototype._updateLayerGroupSelection):
     13        Implement selection of 3D layer objects.
     14       
     15        (WI.Layers3DContentView.prototype._addLayerGroup): Renamed from _addLayer.
     16        (WI.Layers3DContentView.prototype._updateLayerGroupPosition):
     17        (WI.Layers3DContentView.prototype._createLayerMesh):
     18        Refactor -- one group per layer (visible plane and composited outline), not groups by shape.
     19
     20        (WI.Layers3DContentView.prototype.layout):
     21        (WI.Layers3DContentView.prototype._updateLayers):
     22        (WI.Layers3DContentView.prototype._clearLayers): Deleted.
     23        Don't destroy all 3D objects on every LayerTreeDidChange; make use of layerTreeMutations.
     24        (Not only a performance improvement, but also necessary to properly preserve highlighting.)
     25       
     26        (WI.Layers3DContentView.prototype.selectLayerById):
     27        Allow selection to be updated from the outside.
     28
     29        * UserInterface/Views/LayerDetailsSidebarPanel.js:
     30        (WI.LayerDetailsSidebarPanel.prototype.selectNodeByLayerId):
     31        (WI.LayerDetailsSidebarPanel.prototype._buildDataGrid):
     32        (WI.LayerDetailsSidebarPanel.prototype._dataGridSelectedNodeChanged):
     33        Allow selection to be updated from the outside.
     34
     35        (WI.LayerDetailsSidebarPanel.prototype.inspect):
     36        (WI.LayerDetailsSidebarPanel.prototype._updateLayers): Renamed from _updateDisplayWithLayers.
     37        (WI.LayerDetailsSidebarPanel.prototype._updateDataGrid):
     38        (WI.LayerDetailsSidebarPanel.prototype._updateBottomBar):
     39        (WI.LayerDetailsSidebarPanel.prototype._contentForPopover):
     40        (WI.LayerDetailsSidebarPanel.prototype._dataGridNodeForLayer): Deleted.
     41        Cleanup.
     42       
     43        * UserInterface/Views/LayersTabContentView.js:
     44        (WI.LayersTabContentView):
     45        (WI.LayersTabContentView.prototype._detailsSidebarSelectedLayerChanged):
     46        (WI.LayersTabContentView.prototype._contentViewSelectedLayerChanged):
     47        Orchestrate communication of selection state between visualization and sidebar.
     48
    1492017-10-11  Joseph Pecoraro  <pecoraro@apple.com>
    250
  • trunk/Source/WebInspectorUI/UserInterface/Views/LayerDetailsSidebarPanel.js

    r222801 r223209  
    5252
    5353        let layers = objects.filter((object) => object instanceof WI.Layer);
    54         this._updateDisplayWithLayers(layers);
     54        this._updateLayers(layers);
    5555
    5656        return !!layers.length;
     
    6060    {
    6161        this._popover = null;
     62    }
     63
     64    selectNodeByLayerId(layerId)
     65    {
     66        let node = this._dataGridNodesByLayerId.get(layerId);
     67        if (node === this._dataGrid.selectedNode)
     68            return;
     69
     70        if (node)
     71            node.revealAndSelect();
     72        else if (this._dataGrid.selectedNode)
     73            this._dataGrid.selectedNode.deselect();
    6274    }
    6375
     
    93105        this._dataGrid.createSettings("layer-details-sidebar-panel");
    94106
    95         this._dataGrid.element.addEventListener("mousemove", this._dataGridMouseMove.bind(this), false);
    96         this._dataGrid.element.addEventListener("mouseleave", this._dataGridMouseLeave.bind(this), false);
     107        this._dataGrid.element.addEventListener("mousemove", this._dataGridMouseMove.bind(this));
     108        this._dataGrid.element.addEventListener("mouseleave", this._dataGridMouseLeave.bind(this));
     109
     110        // FIXME: We can't use virtualized rows until DataGrid is able to scroll them programmatically.
     111        //        See TreeElement#reveal -> TreeOutline#updateVirtualizedElements for an analogy.
     112        this._dataGrid.inline = true;
     113        this._dataGrid.element.classList.remove("inline");
    97114
    98115        this.contentView.addSubview(this._dataGrid);
     
    126143    _dataGridSelectedNodeChanged()
    127144    {
     145        let layerId = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.layer.layerId : null;
     146        this.dispatchEventToListeners(WI.LayerDetailsSidebarPanel.Event.SelectedLayerChanged, {layerId});
     147
    128148        this._showPopoverForSelectedNode();
    129149    }
     
    160180    }
    161181
    162     _updateDisplayWithLayers(newLayers)
    163     {
    164         let previousLayers = this._layers;
     182    _updateLayers(newLayers)
     183    {
     184        if (this._popover)
     185            this._popover.dismiss();
     186
     187        this._updateDataGrid(newLayers);
     188        this._updateBottomBar(newLayers);
     189
    165190        this._layers = newLayers;
    166 
    167         this._updateDataGrid(previousLayers);
    168         this._updateBottomBar();
    169     }
    170 
    171     _updateDataGrid(previousLayers)
     191    }
     192
     193    _updateDataGrid(newLayers)
    172194    {
    173195        if (!this._dataGrid)
    174196            this._buildDataGrid();
    175197
    176         let mutations = WI.layerTreeManager.layerTreeMutations(previousLayers, this._layers);
    177 
    178         mutations.removals.forEach((layer) => {
     198        let {removals, additions, preserved} = WI.layerTreeManager.layerTreeMutations(this._layers, newLayers);
     199
     200        removals.forEach((layer) => {
    179201            let node = this._dataGridNodesByLayerId.get(layer.layerId);
    180             if (!node)
    181                 return;
    182 
    183202            this._dataGrid.removeChild(node);
    184203            this._dataGridNodesByLayerId.delete(layer.layerId);
    185204        });
    186205
    187         mutations.additions.forEach((layer) => {
    188             let node = this._dataGridNodeForLayer(layer);
     206        additions.forEach((layer) => {
     207            let node = new WI.LayerTreeDataGridNode(layer);
     208            this._dataGridNodesByLayerId.set(layer.layerId, node);
    189209            this._dataGrid.appendChild(node);
    190210        });
    191211
    192         mutations.preserved.forEach((layer) => {
     212        preserved.forEach((layer) => {
    193213            let node = this._dataGridNodesByLayerId.get(layer.layerId);
    194             if (!node)
    195                 return;
    196 
    197214            node.layer = layer;
    198215        });
     
    201218    }
    202219
    203     _dataGridNodeForLayer(layer)
    204     {
    205         let node = new WI.LayerTreeDataGridNode(layer);
    206         this._dataGridNodesByLayerId.set(layer.layerId, node);
    207 
    208         return node;
    209     }
    210 
    211     _updateBottomBar()
     220    _updateBottomBar(newLayers)
    212221    {
    213222        if (!this._bottomBar)
    214223            this._buildBottomBar();
    215224
    216         this._layersCountLabel.textContent = WI.UIString("Layer Count: %d").format(this._layers.length);
    217 
    218         let totalMemory = this._layers.reduce((total, layer) => total + (layer.memory || 0), 0);
     225        this._layersCountLabel.textContent = WI.UIString("Layer Count: %d").format(newLayers.length);
     226
     227        let totalMemory = newLayers.reduce((total, layer) => total + (layer.memory || 0), 0);
    219228        this._layersMemoryLabel.textContent = WI.UIString("Memory: %s").format(Number.bytesToString(totalMemory));
    220229    }
     
    274283
    275284        WI.layerTreeManager.reasonsForCompositingLayer(layer, (compositingReasons) => {
    276             if (isEmptyObject(compositingReasons)) {
    277                 callback(content);
    278                 return;
    279             }
    280 
    281             this._populateListOfCompositingReasons(list, compositingReasons);
     285            if (!isEmptyObject(compositingReasons))
     286                this._populateListOfCompositingReasons(list, compositingReasons);
    282287
    283288            callback(content);
     
    350355    }
    351356};
     357
     358WI.LayerDetailsSidebarPanel.Event = {
     359    SelectedLayerChanged: "selected-layer-changed"
     360};
  • trunk/Source/WebInspectorUI/UserInterface/Views/Layers3DContentView.js

    r222342 r223209  
    3535
    3636        this._layers = [];
     37        this._layerGroupsById = new Map;
     38        this._selectedLayerGroup = null;
    3739        this._layersChangedWhileHidden = false;
     40
    3841        this._renderer = null;
    3942        this._camera = null;
    4043        this._controls = null;
    41         this._boundsGroup = null;
    42         this._compositedBoundsGroup = null;
    4344        this._scene = null;
     45        this._raycaster = null;
     46        this._mouse = null;
    4447        this._animationFrameRequestId = null;
    4548    }
     
    7881
    7982        super.closed();
     83    }
     84
     85    selectLayerById(layerId)
     86    {
     87        let layerGroup = this._layerGroupsById.get(layerId);
     88        this._updateLayerGroupSelection(layerGroup);
    8089    }
    8190
     
    101110        this._controls.maxAzimuthAngle = Math.PI / 2;
    102111
    103         this._boundsGroup = new THREE.Group();
    104         this._compositedBoundsGroup = new THREE.Group();
    105 
    106         this._scene = new THREE.Scene();
     112        this._scene = new THREE.Scene;
    107113        this._scene.position.set(-this.element.offsetWidth / 2, this.element.offsetHeight / 2, 0);
    108         this._scene.add(this._boundsGroup);
    109         this._scene.add(this._compositedBoundsGroup);
     114
     115        this._raycaster = new THREE.Raycaster;
     116        this._mouse = new THREE.Vector2;
     117        this._renderer.domElement.addEventListener("mousedown", this._canvasMouseDown.bind(this));
    110118
    111119        this.element.appendChild(this._renderer.domElement);
     
    121129        WI.domTreeManager.requestDocument((node) => {
    122130            WI.layerTreeManager.layersForNode(node, (layerForNode, childLayers) => {
    123                 this._clearLayers();
    124                 for (let i = 0; i < childLayers.length; i++)
    125                     this._addLayer(childLayers[i], i);
    126 
    127                 this._layers = childLayers;
     131                this._updateLayers(childLayers);
    128132                this.dispatchEventToListeners(WI.ContentView.Event.SelectionPathComponentsDidChange);
    129133            });
     
    167171    }
    168172
    169     _clearLayers()
    170     {
    171         this._boundsGroup.children.length = 0;
    172         this._compositedBoundsGroup.children.length = 0;
    173     }
    174 
    175     _addLayer(layer, index)
    176     {
    177         this._boundsGroup.add(this._createLayerMesh(layer.bounds, index));
    178         this._compositedBoundsGroup.add(this._createLayerMesh(layer.compositedBounds, index, true));
    179     }
    180 
    181     _createLayerMesh(rect, index, isOutline = false)
    182     {
     173    _updateLayers(newLayers)
     174    {
     175        // FIXME: This should be made into the basic usage of the manager, if not the agent itself.
     176        //        At that point, we can remove this duplication from the visualization and sidebar.
     177        let {removals, additions, preserved} = WI.layerTreeManager.layerTreeMutations(this._layers, newLayers);
     178
     179        for (let layer of removals) {
     180            let layerGroup = this._layerGroupsById.get(layer.layerId);
     181            this._scene.remove(layerGroup);
     182            this._layerGroupsById.delete(layer.layerId);
     183        }
     184
     185        if (this._selectedLayerGroup && !this._layerGroupsById.get(this._selectedLayerGroup.userData.layerId))
     186            this.selectedLayerGroup = null;
     187
     188        additions.forEach(this._addLayerGroup, this);
     189        preserved.forEach(this._updateLayerGroupPosition, this);
     190
     191        this._layers = newLayers;
     192    }
     193
     194    _addLayerGroup(layer, index)
     195    {
     196        let layerGroup = new THREE.Group;
     197        layerGroup.userData.layerId = layer.layerId;
     198        layerGroup.add(this._createLayerMesh(layer.bounds));
     199        layerGroup.add(this._createLayerMesh(layer.compositedBounds, true));
     200
     201        this._layerGroupsById.set(layer.layerId, layerGroup);
     202        this._updateLayerGroupPosition(layer, index);
     203
     204        this._scene.add(layerGroup);
     205    }
     206
     207    _updateLayerGroupPosition(layer, index) {
     208        let layerGroup = this._layerGroupsById.get(layer.layerId);
     209        console.assert(layerGroup);
     210
    183211        const zInterval = 25;
    184 
    185         let geometry = new THREE.Geometry();
    186         geometry.vertices.push(new THREE.Vector3(rect.x,              -rect.y,               index * zInterval));
    187         geometry.vertices.push(new THREE.Vector3(rect.x + rect.width, -rect.y,               index * zInterval));
    188         geometry.vertices.push(new THREE.Vector3(rect.x + rect.width, -rect.y - rect.height, index * zInterval));
    189         geometry.vertices.push(new THREE.Vector3(rect.x,              -rect.y - rect.height, index * zInterval));
     212        layerGroup.position.set(layer.bounds.x, -layer.bounds.y, index * zInterval);
     213    }
     214
     215    _createLayerMesh({width, height}, isOutline = false)
     216    {
     217        let geometry = new THREE.Geometry;
     218        geometry.vertices.push(new THREE.Vector3(0,     0,       0));
     219        geometry.vertices.push(new THREE.Vector3(width, 0,       0));
     220        geometry.vertices.push(new THREE.Vector3(width, -height, 0));
     221        geometry.vertices.push(new THREE.Vector3(0,     -height, 0));
    190222
    191223        if (isOutline) {
    192             let material = new THREE.LineBasicMaterial({color: "hsl(79, 45%, 50%)"});
     224            let material = new THREE.LineBasicMaterial({color: WI.Layers3DContentView._layerColor.stroke});
    193225            return new THREE.LineLoop(geometry, material);
    194226        }
     
    198230
    199231        let material = new THREE.MeshBasicMaterial({
    200             color: "hsl(76, 49%, 75%)",
     232            color: WI.Layers3DContentView._layerColor.fill,
    201233            transparent: true,
    202234            opacity: 0.4,
     
    206238        return new THREE.Mesh(geometry, material);
    207239    }
    208 };
     240
     241    _canvasMouseDown(event)
     242    {
     243        this._mouse.x = (event.offsetX / event.target.width) * 2 - 1;
     244        this._mouse.y = -(event.offsetY / event.target.height) * 2 + 1;
     245        this._raycaster.setFromCamera(this._mouse, this._camera);
     246
     247        const recursive = true;
     248        let intersects = this._raycaster.intersectObjects(this._scene.children, recursive);
     249        let selection = intersects.length ? intersects[0].object.parent : null;
     250        if (selection && selection === this._selectedLayerGroup) {
     251            if (!event.metaKey)
     252                return;
     253
     254            selection = null;
     255        }
     256
     257        this._updateLayerGroupSelection(selection);
     258
     259        let layerId = selection ? selection.userData.layerId : null;
     260        this.dispatchEventToListeners(WI.Layers3DContentView.Event.SelectedLayerChanged, {layerId});
     261    }
     262
     263    _updateLayerGroupSelection(layerGroup)
     264    {
     265        let setColor = ({fill, stroke}) => {
     266            let [plane, outline] = this._selectedLayerGroup.children;
     267            plane.material.color.set(fill);
     268            outline.material.color.set(stroke);
     269        };
     270
     271        if (this._selectedLayerGroup)
     272            setColor(WI.Layers3DContentView._layerColor);
     273
     274        this._selectedLayerGroup = layerGroup;
     275
     276        if (this._selectedLayerGroup)
     277            setColor(WI.Layers3DContentView._selectedLayerColor);
     278    }
     279};
     280
     281WI.Layers3DContentView._layerColor = {
     282    fill: "hsl(76, 49%, 75%)",
     283    stroke: "hsl(79, 45%, 50%)"
     284};
     285
     286WI.Layers3DContentView._selectedLayerColor = {
     287    fill: "hsl(208, 66%, 79%)",
     288    stroke: "hsl(202, 57%, 68%)"
     289};
     290
     291WI.Layers3DContentView.Event = {
     292    SelectedLayerChanged: "selected-layer-changed"
     293};
  • trunk/Source/WebInspectorUI/UserInterface/Views/LayersTabContentView.js

    r222342 r223209  
    3636        super("layers", "layers", tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward);
    3737
     38        this._layerDetailsSidebarPanel = this.detailsSidebarPanels[0];
     39        this._layerDetailsSidebarPanel.addEventListener(WI.LayerDetailsSidebarPanel.Event.SelectedLayerChanged, this._detailsSidebarSelectedLayerChanged, this);
     40
    3841        this._layers3DContentView = new WI.Layers3DContentView;
     42        this._layers3DContentView.addEventListener(WI.Layers3DContentView.Event.SelectedLayerChanged, this._contentViewSelectedLayerChanged, this);
    3943    }
    4044
     
    6569        this.contentBrowser.showContentView(this._layers3DContentView);
    6670    }
     71
     72    // Private
     73
     74    _detailsSidebarSelectedLayerChanged(event)
     75    {
     76        this._layers3DContentView.selectLayerById(event.data.layerId);
     77    }
     78
     79    _contentViewSelectedLayerChanged(event)
     80    {
     81        this._layerDetailsSidebarPanel.selectNodeByLayerId(event.data.layerId);
     82    }
    6783};
    6884
Note: See TracChangeset for help on using the changeset viewer.