Skip to content

Commit b6df1d3

Browse files
committed
Cherry-pick to master: Merge pull request #3448 from cytoscape/copilot/fix-child-nodes-opacity-inheritance
WebGL: apply compound opacity inheritance to child node bodies and borders
1 parent 4093efb commit b6df1d3

4 files changed

Lines changed: 96 additions & 6 deletions

File tree

debug/webgl/index.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
':35729/livereload.js?snipver=1"></' + 'script>')
1111
</script> -->
1212

13-
<link rel="stylesheet" href="./style.css" />
13+
<script src="../livereload-setup.js"></script>
1414

15+
<link rel="stylesheet" href="./style.css" />
16+
1517
<script>
1618
var $ = function( sel ){ return document.querySelector(sel); };
1719
var $$ = function( sel ){ return document.querySelectorAll(sel); };
@@ -30,7 +32,7 @@
3032
}
3133
</script>
3234

33-
<script src="./cytoscape.umd.js"></script>
35+
<script src="../../build/cytoscape.umd.js"></script>
3436

3537
<style>
3638
.tooltip {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
"dist": "cross-env NODE_ENV=production run-s build dist:*",
7878
"release": "run-s copyright dist docs",
7979
"watch": "run-s watch:fast",
80-
"watch:sync": "livereload \"build, debug\" -w 500",
80+
"watch:sync": "livereload \"build, debug, debug/webgl\" -w 500 --extraExts 'json'",
8181
"watch:http": "http-server -p 3333 -s -c -1 -o debug",
8282
"watch:fast": "run-p watch:sync watch:http watch:build:fast",
8383
"watch:umd": "run-p watch:sync watch:http watch:build:umd",

src/extensions/renderer/canvas/webgl/drawing-elements-webgl.mjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -766,11 +766,13 @@ export class ElementDrawingWebGL {
766766

767767
// Nodes should still be clickable if they pass the visibility check but
768768
// have background-opacity: 0
769-
const opacity = this.renderTarget.picking ? 1 : node.pstyle(props.opacity).value;
769+
// Also: everything but node-body is exempt from effective opacity inheritence/stacking
770+
let opacity = this.renderTarget.picking ? 1 : (type === 'node-body' ? node.effectiveOpacity() : 1);
771+
let bgOpacity = this.renderTarget.picking ? 1 : (node.pstyle(props.opacity).value * opacity);
770772

771773
const color = node.pstyle(props.color).value;
772774
const colorView = this.colorBuffer.getView(instance);
773-
util.toWebGLColor(color, opacity, colorView);
775+
util.toWebGLColor(color, bgOpacity, colorView);
774776

775777
const lineWidthView = this.lineWidthBuffer.getView(instance); // reuse edge line width attribute for node border
776778
lineWidthView[0] = 0;
@@ -780,7 +782,7 @@ export class ElementDrawingWebGL {
780782
const borderWidth = node.pstyle('border-width').value;
781783
if(borderWidth > 0) {
782784
const borderColor = node.pstyle('border-color').value;
783-
const borderOpacity = node.pstyle('border-opacity').value;
785+
const borderOpacity = opacity * node.pstyle('border-opacity').value;
784786

785787
const borderColorView = this.borderColorBuffer.getView(instance);
786788
util.toWebGLColor(borderColor, borderOpacity, borderColorView);
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { describe, it } from 'mocha';
2+
import { expect } from 'chai';
3+
import { ElementDrawingWebGL, RENDER_TARGET } from '../../src/extensions/renderer/canvas/webgl/drawing-elements-webgl.mjs';
4+
5+
const createBuffer = (size) => ({
6+
view: new Float32Array(size),
7+
getView() {
8+
return this.view;
9+
}
10+
});
11+
12+
describe('webgl-drawing-elements', function(){
13+
14+
it('drawNode() uses effective opacity for simple-shape node body and border', function(){
15+
const colorBuffer = createBuffer(4);
16+
const borderColorBuffer = createBuffer(4);
17+
const lineWidthBuffer = createBuffer(2);
18+
const vertTypeBuffer = createBuffer(1);
19+
const indexBuffer = createBuffer(4);
20+
const cornerRadiusBuffer = createBuffer(4);
21+
const transformMatrix = new Float32Array(9);
22+
const transformBuffer = {
23+
getMatrixView() {
24+
return transformMatrix;
25+
}
26+
};
27+
28+
const drawing = {
29+
simpleShapeOptions: new Map([[
30+
'node-body',
31+
{
32+
shapeProps: {
33+
shape: 'shape',
34+
color: 'background-color',
35+
opacity: 'background-opacity',
36+
radius: 'corner-radius',
37+
border: true
38+
},
39+
getBoundingBox: () => ({ x1: 0, y1: 0, w: 10, h: 10 })
40+
}
41+
]]),
42+
_isVisible: () => true,
43+
_getVertTypeForShape: () => 4,
44+
colorBuffer,
45+
borderColorBuffer,
46+
lineWidthBuffer,
47+
vertTypeBuffer,
48+
indexBuffer,
49+
cornerRadiusBuffer,
50+
transformBuffer,
51+
renderTarget: RENDER_TARGET.SCREEN,
52+
instanceCount: 0,
53+
simpleCount: 0,
54+
maxInstances: 10,
55+
endBatch(){},
56+
setTransformMatrix(){}
57+
};
58+
59+
const styles = {
60+
shape: { value: 'rectangle' },
61+
'background-color': { value: [255, 0, 0] },
62+
'background-opacity': { value: 0.5 },
63+
'corner-radius': { value: 'auto', pfValue: 0 },
64+
'border-width': { value: 4 },
65+
'border-color': { value: [0, 0, 255] },
66+
'border-opacity': { value: 0.25 },
67+
'border-position': { value: 'center' }
68+
};
69+
70+
const node = {
71+
visible: () => true,
72+
effectiveOpacity: () => 0.4,
73+
pstyle: (name) => styles[name]
74+
};
75+
76+
ElementDrawingWebGL.prototype.drawNode.call(drawing, node, 7, 'node-body');
77+
78+
expect(colorBuffer.view[3]).to.be.closeTo(0.2, 0.000001);
79+
expect(borderColorBuffer.view[3]).to.be.closeTo(0.1, 0.000001);
80+
expect(lineWidthBuffer.view[0]).to.equal(2);
81+
expect(lineWidthBuffer.view[1]).to.equal(-2);
82+
expect(drawing.simpleCount).to.equal(1);
83+
expect(drawing.instanceCount).to.equal(1);
84+
});
85+
86+
});

0 commit comments

Comments
 (0)