Problem: the hexagonal refactor churns the backend tree for nine more phases; the UI delivery stack (web/ SPA, cmd/desktop Wails wrapper, compose/web image) must move to its own repo first so doc/layout rewrites land once on a backend-only tree. Change: - New repo git.hubris.network/dtoro/oikos-web (v0.33.0): web/, desktop/ (updateURL repointed to oikos-web releases), compose/, own CI (web + desktop jobs), own deploy script (CI-green gate, TOCTOU guard, version-tagged images, prune-to-3), own webhook receiver on :9798 + launchd unit, own compose project publishing the same 8091:80. - Cutover executed on mac-mini in order: oikos stack's web service stopped+removed, oikos-web project brought up on 8091; outer Caddy untouched (targets the published port) — serving + Authentik flow + /wails 404 quirk verified post-cutover. - Stripped from oikos: web/, cmd/desktop/, compose/web/, desktop CI workflow, ci.yml web job, Makefile ui/desktop/desktop-package/install targets, the compose web service, oikos-web from deploy.sh's fallback prune list; wails + go-keyring dropped from go.mod, vendor synced. - README / CONTRIBUTING / AGENTS.md / .agents dev+operations docs now point at the new repo; mbse + mascot design docs carry a path note. Risk: production SPA serving depends on the new pipeline now; rollback is versioned-image re-up of the old web service from a pre-split checkout (port 8091). Desktop builds installed before the split still check dtoro/oikos releases — one manual reinstall, noted in the oikos-web release notes. Verification: go vet, make test (race), make generate-check, golangci (no new findings; baseline down 400→365); post-cutover curls — localhost:8091 200, /wails/runtime.js 404, outer Caddy 302 Authentik.
1202 lines
51 KiB
JavaScript
1202 lines
51 KiB
JavaScript
'use strict';
|
|
|
|
var inherits = require('./inherits-6434e089.cjs.prod.js');
|
|
var colors = require('./colors-ee2e2828.cjs.prod.js');
|
|
|
|
function _defineProperty(e, r, t) {
|
|
return (r = inherits._toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
value: t,
|
|
enumerable: !0,
|
|
configurable: !0,
|
|
writable: !0
|
|
}) : e[r] = t, e;
|
|
}
|
|
|
|
function ownKeys(e, r) {
|
|
var t = Object.keys(e);
|
|
if (Object.getOwnPropertySymbols) {
|
|
var o = Object.getOwnPropertySymbols(e);
|
|
r && (o = o.filter(function (r) {
|
|
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
})), t.push.apply(t, o);
|
|
}
|
|
return t;
|
|
}
|
|
function _objectSpread2(e) {
|
|
for (var r = 1; r < arguments.length; r++) {
|
|
var t = null != arguments[r] ? arguments[r] : {};
|
|
r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
|
|
_defineProperty(e, r, t[r]);
|
|
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
|
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
});
|
|
}
|
|
return e;
|
|
}
|
|
|
|
function _superPropBase(t, o) {
|
|
for (; !{}.hasOwnProperty.call(t, o) && null !== (t = inherits._getPrototypeOf(t)););
|
|
return t;
|
|
}
|
|
|
|
function _get() {
|
|
return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) {
|
|
var p = _superPropBase(e, t);
|
|
if (p) {
|
|
var n = Object.getOwnPropertyDescriptor(p, t);
|
|
return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
|
|
}
|
|
}, _get.apply(null, arguments);
|
|
}
|
|
|
|
function _superPropGet(t, o, e, r) {
|
|
var p = _get(inherits._getPrototypeOf(1 & r ? t.prototype : t), o, e);
|
|
return 2 & r && "function" == typeof p ? function (t) {
|
|
return p.apply(e, t);
|
|
} : p;
|
|
}
|
|
|
|
function getAttributeItemsCount(attr) {
|
|
return attr.normalized ? 1 : attr.size;
|
|
}
|
|
function getAttributesItemsCount(attrs) {
|
|
var res = 0;
|
|
attrs.forEach(function (attr) {
|
|
return res += getAttributeItemsCount(attr);
|
|
});
|
|
return res;
|
|
}
|
|
function loadShader(type, gl, source) {
|
|
var glType = type === "VERTEX" ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER;
|
|
|
|
// Creating the shader
|
|
var shader = gl.createShader(glType);
|
|
if (shader === null) {
|
|
throw new Error("loadShader: error while creating the shader");
|
|
}
|
|
|
|
// Loading source
|
|
gl.shaderSource(shader, source);
|
|
|
|
// Compiling the shader
|
|
gl.compileShader(shader);
|
|
|
|
// Retrieving compilation status
|
|
var successfullyCompiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
|
|
|
// Throwing if something went awry
|
|
if (!successfullyCompiled) {
|
|
var infoLog = gl.getShaderInfoLog(shader);
|
|
gl.deleteShader(shader);
|
|
throw new Error("loadShader: error while compiling the shader:\n".concat(infoLog, "\n").concat(source));
|
|
}
|
|
return shader;
|
|
}
|
|
function loadVertexShader(gl, source) {
|
|
return loadShader("VERTEX", gl, source);
|
|
}
|
|
function loadFragmentShader(gl, source) {
|
|
return loadShader("FRAGMENT", gl, source);
|
|
}
|
|
|
|
/**
|
|
* Function used to load a program.
|
|
*/
|
|
function loadProgram(gl, shaders) {
|
|
var program = gl.createProgram();
|
|
if (program === null) {
|
|
throw new Error("loadProgram: error while creating the program.");
|
|
}
|
|
var i, l;
|
|
|
|
// Attaching the shaders
|
|
for (i = 0, l = shaders.length; i < l; i++) gl.attachShader(program, shaders[i]);
|
|
gl.linkProgram(program);
|
|
|
|
// Checking status
|
|
var successfullyLinked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
|
if (!successfullyLinked) {
|
|
var info = gl.getProgramInfoLog(program);
|
|
gl.deleteProgram(program);
|
|
throw new Error("loadProgram: error while linking the program: ".concat(info));
|
|
}
|
|
return program;
|
|
}
|
|
function killProgram(_ref) {
|
|
var gl = _ref.gl,
|
|
buffer = _ref.buffer,
|
|
program = _ref.program,
|
|
vertexShader = _ref.vertexShader,
|
|
fragmentShader = _ref.fragmentShader;
|
|
gl.deleteShader(vertexShader);
|
|
gl.deleteShader(fragmentShader);
|
|
gl.deleteProgram(program);
|
|
gl.deleteBuffer(buffer);
|
|
}
|
|
|
|
/**
|
|
* Function use to print a float for inserting in a GLSL program.
|
|
*/
|
|
function numberToGLSLFloat(n) {
|
|
return n % 1 === 0 ? n.toFixed(1) : n.toString();
|
|
}
|
|
|
|
var PICKING_PREFIX = "#define PICKING_MODE\n";
|
|
var SIZE_FACTOR_PER_ATTRIBUTE_TYPE = _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, WebGL2RenderingContext.BOOL, 1), WebGL2RenderingContext.BYTE, 1), WebGL2RenderingContext.UNSIGNED_BYTE, 1), WebGL2RenderingContext.SHORT, 2), WebGL2RenderingContext.UNSIGNED_SHORT, 2), WebGL2RenderingContext.INT, 4), WebGL2RenderingContext.UNSIGNED_INT, 4), WebGL2RenderingContext.FLOAT, 4);
|
|
var AbstractProgram = /*#__PURE__*/inherits._createClass(function AbstractProgram(_gl, _pickGl, _renderer) {
|
|
inherits._classCallCheck(this, AbstractProgram);
|
|
});
|
|
var Program = /*#__PURE__*/function () {
|
|
function Program(gl, pickingBuffer, renderer) {
|
|
inherits._classCallCheck(this, Program);
|
|
// GLenum
|
|
_defineProperty(this, "array", new Float32Array());
|
|
_defineProperty(this, "constantArray", new Float32Array());
|
|
_defineProperty(this, "capacity", 0);
|
|
_defineProperty(this, "verticesCount", 0);
|
|
// Reading and caching program definition
|
|
var def = this.getDefinition();
|
|
this.VERTICES = def.VERTICES;
|
|
this.VERTEX_SHADER_SOURCE = def.VERTEX_SHADER_SOURCE;
|
|
this.FRAGMENT_SHADER_SOURCE = def.FRAGMENT_SHADER_SOURCE;
|
|
this.UNIFORMS = def.UNIFORMS;
|
|
this.ATTRIBUTES = def.ATTRIBUTES;
|
|
this.METHOD = def.METHOD;
|
|
this.CONSTANT_ATTRIBUTES = "CONSTANT_ATTRIBUTES" in def ? def.CONSTANT_ATTRIBUTES : [];
|
|
this.CONSTANT_DATA = "CONSTANT_DATA" in def ? def.CONSTANT_DATA : [];
|
|
this.isInstanced = "CONSTANT_ATTRIBUTES" in def;
|
|
|
|
// Computing stride
|
|
this.ATTRIBUTES_ITEMS_COUNT = getAttributesItemsCount(this.ATTRIBUTES);
|
|
this.STRIDE = this.VERTICES * this.ATTRIBUTES_ITEMS_COUNT;
|
|
|
|
// Members
|
|
this.renderer = renderer;
|
|
this.normalProgram = this.getProgramInfo("normal", gl, def.VERTEX_SHADER_SOURCE, def.FRAGMENT_SHADER_SOURCE, null);
|
|
this.pickProgram = pickingBuffer ? this.getProgramInfo("pick", gl, PICKING_PREFIX + def.VERTEX_SHADER_SOURCE, PICKING_PREFIX + def.FRAGMENT_SHADER_SOURCE, pickingBuffer) : null;
|
|
|
|
// For instanced programs:
|
|
if (this.isInstanced) {
|
|
var constantAttributesItemsCount = getAttributesItemsCount(this.CONSTANT_ATTRIBUTES);
|
|
if (this.CONSTANT_DATA.length !== this.VERTICES) throw new Error("Program: error while getting constant data (expected ".concat(this.VERTICES, " items, received ").concat(this.CONSTANT_DATA.length, " instead)"));
|
|
this.constantArray = new Float32Array(this.CONSTANT_DATA.length * constantAttributesItemsCount);
|
|
for (var i = 0; i < this.CONSTANT_DATA.length; i++) {
|
|
var vector = this.CONSTANT_DATA[i];
|
|
if (vector.length !== constantAttributesItemsCount) throw new Error("Program: error while getting constant data (one vector has ".concat(vector.length, " items instead of ").concat(constantAttributesItemsCount, ")"));
|
|
for (var j = 0; j < vector.length; j++) this.constantArray[i * constantAttributesItemsCount + j] = vector[j];
|
|
}
|
|
this.STRIDE = this.ATTRIBUTES_ITEMS_COUNT;
|
|
}
|
|
}
|
|
return inherits._createClass(Program, [{
|
|
key: "kill",
|
|
value: function kill() {
|
|
killProgram(this.normalProgram);
|
|
if (this.pickProgram) {
|
|
killProgram(this.pickProgram);
|
|
this.pickProgram = null;
|
|
}
|
|
}
|
|
}, {
|
|
key: "getProgramInfo",
|
|
value: function getProgramInfo(name, gl, vertexShaderSource, fragmentShaderSource, frameBuffer) {
|
|
var def = this.getDefinition();
|
|
|
|
// WebGL buffers
|
|
var buffer = gl.createBuffer();
|
|
if (buffer === null) throw new Error("Program: error while creating the WebGL buffer.");
|
|
|
|
// Shaders and program
|
|
var vertexShader = loadVertexShader(gl, vertexShaderSource);
|
|
var fragmentShader = loadFragmentShader(gl, fragmentShaderSource);
|
|
var program = loadProgram(gl, [vertexShader, fragmentShader]);
|
|
|
|
// Initializing locations
|
|
var uniformLocations = {};
|
|
def.UNIFORMS.forEach(function (uniformName) {
|
|
var location = gl.getUniformLocation(program, uniformName);
|
|
if (location) uniformLocations[uniformName] = location;
|
|
});
|
|
var attributeLocations = {};
|
|
def.ATTRIBUTES.forEach(function (attr) {
|
|
attributeLocations[attr.name] = gl.getAttribLocation(program, attr.name);
|
|
});
|
|
|
|
// For instanced programs:
|
|
var constantBuffer;
|
|
if ("CONSTANT_ATTRIBUTES" in def) {
|
|
def.CONSTANT_ATTRIBUTES.forEach(function (attr) {
|
|
attributeLocations[attr.name] = gl.getAttribLocation(program, attr.name);
|
|
});
|
|
constantBuffer = gl.createBuffer();
|
|
if (constantBuffer === null) throw new Error("Program: error while creating the WebGL constant buffer.");
|
|
}
|
|
return {
|
|
name: name,
|
|
program: program,
|
|
gl: gl,
|
|
frameBuffer: frameBuffer,
|
|
buffer: buffer,
|
|
constantBuffer: constantBuffer || {},
|
|
uniformLocations: uniformLocations,
|
|
attributeLocations: attributeLocations,
|
|
isPicking: name === "pick",
|
|
vertexShader: vertexShader,
|
|
fragmentShader: fragmentShader
|
|
};
|
|
}
|
|
}, {
|
|
key: "bindProgram",
|
|
value: function bindProgram(program) {
|
|
var _this = this;
|
|
var offset = 0;
|
|
var gl = program.gl,
|
|
buffer = program.buffer;
|
|
if (!this.isInstanced) {
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
offset = 0;
|
|
this.ATTRIBUTES.forEach(function (attr) {
|
|
return offset += _this.bindAttribute(attr, program, offset);
|
|
});
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
|
|
} else {
|
|
// Handle constant data (things that remain unchanged for all items):
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, program.constantBuffer);
|
|
offset = 0;
|
|
this.CONSTANT_ATTRIBUTES.forEach(function (attr) {
|
|
return offset += _this.bindAttribute(attr, program, offset, false);
|
|
});
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.constantArray, gl.STATIC_DRAW);
|
|
|
|
// Handle "instance specific" data (things that vary for each item):
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, program.buffer);
|
|
offset = 0;
|
|
this.ATTRIBUTES.forEach(function (attr) {
|
|
return offset += _this.bindAttribute(attr, program, offset, true);
|
|
});
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
|
|
}
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
}
|
|
}, {
|
|
key: "unbindProgram",
|
|
value: function unbindProgram(program) {
|
|
var _this2 = this;
|
|
if (!this.isInstanced) {
|
|
this.ATTRIBUTES.forEach(function (attr) {
|
|
return _this2.unbindAttribute(attr, program);
|
|
});
|
|
} else {
|
|
this.CONSTANT_ATTRIBUTES.forEach(function (attr) {
|
|
return _this2.unbindAttribute(attr, program, false);
|
|
});
|
|
this.ATTRIBUTES.forEach(function (attr) {
|
|
return _this2.unbindAttribute(attr, program, true);
|
|
});
|
|
}
|
|
}
|
|
}, {
|
|
key: "bindAttribute",
|
|
value: function bindAttribute(attr, program, offset, setDivisor) {
|
|
var sizeFactor = SIZE_FACTOR_PER_ATTRIBUTE_TYPE[attr.type];
|
|
if (typeof sizeFactor !== "number") throw new Error("Program.bind: yet unsupported attribute type \"".concat(attr.type, "\""));
|
|
var location = program.attributeLocations[attr.name];
|
|
var gl = program.gl;
|
|
if (location !== -1) {
|
|
gl.enableVertexAttribArray(location);
|
|
var stride = !this.isInstanced ? this.ATTRIBUTES_ITEMS_COUNT * Float32Array.BYTES_PER_ELEMENT : (setDivisor ? this.ATTRIBUTES_ITEMS_COUNT : getAttributesItemsCount(this.CONSTANT_ATTRIBUTES)) * Float32Array.BYTES_PER_ELEMENT;
|
|
gl.vertexAttribPointer(location, attr.size, attr.type, attr.normalized || false, stride, offset);
|
|
if (this.isInstanced && setDivisor) {
|
|
if (gl instanceof WebGL2RenderingContext) {
|
|
gl.vertexAttribDivisor(location, 1);
|
|
} else {
|
|
var ext = gl.getExtension("ANGLE_instanced_arrays");
|
|
if (ext) ext.vertexAttribDivisorANGLE(location, 1);
|
|
}
|
|
}
|
|
}
|
|
return attr.size * sizeFactor;
|
|
}
|
|
}, {
|
|
key: "unbindAttribute",
|
|
value: function unbindAttribute(attr, program, unsetDivisor) {
|
|
var location = program.attributeLocations[attr.name];
|
|
var gl = program.gl;
|
|
if (location !== -1) {
|
|
gl.disableVertexAttribArray(location);
|
|
if (this.isInstanced && unsetDivisor) {
|
|
if (gl instanceof WebGL2RenderingContext) {
|
|
gl.vertexAttribDivisor(location, 0);
|
|
} else {
|
|
var ext = gl.getExtension("ANGLE_instanced_arrays");
|
|
if (ext) ext.vertexAttribDivisorANGLE(location, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: "reallocate",
|
|
value: function reallocate(capacity) {
|
|
// If desired capacity has not changed we do nothing
|
|
// NOTE: it's possible here to implement more subtle reallocation schemes
|
|
// when the number of rendered items increase or decrease
|
|
if (capacity === this.capacity) return;
|
|
this.capacity = capacity;
|
|
this.verticesCount = this.VERTICES * capacity;
|
|
this.array = new Float32Array(!this.isInstanced ? this.verticesCount * this.ATTRIBUTES_ITEMS_COUNT : this.capacity * this.ATTRIBUTES_ITEMS_COUNT);
|
|
}
|
|
}, {
|
|
key: "hasNothingToRender",
|
|
value: function hasNothingToRender() {
|
|
return this.verticesCount === 0;
|
|
}
|
|
}, {
|
|
key: "renderProgram",
|
|
value: function renderProgram(params, programInfo) {
|
|
var gl = programInfo.gl,
|
|
program = programInfo.program;
|
|
|
|
// With the current fix for #1397, the alpha blending is enabled for the
|
|
// picking layer:
|
|
gl.enable(gl.BLEND);
|
|
|
|
// Original code:
|
|
// if (!isPicking) gl.enable(gl.BLEND);
|
|
// else gl.disable(gl.BLEND);
|
|
|
|
gl.useProgram(program);
|
|
this.setUniforms(params, programInfo);
|
|
this.drawWebGL(this.METHOD, programInfo);
|
|
}
|
|
}, {
|
|
key: "render",
|
|
value: function render(params) {
|
|
if (this.hasNothingToRender()) return;
|
|
if (this.pickProgram) {
|
|
this.pickProgram.gl.viewport(0, 0, params.width * params.pixelRatio / params.downSizingRatio, params.height * params.pixelRatio / params.downSizingRatio);
|
|
this.bindProgram(this.pickProgram);
|
|
this.renderProgram(_objectSpread2(_objectSpread2({}, params), {}, {
|
|
pixelRatio: params.pixelRatio / params.downSizingRatio
|
|
}), this.pickProgram);
|
|
this.unbindProgram(this.pickProgram);
|
|
}
|
|
this.normalProgram.gl.viewport(0, 0, params.width * params.pixelRatio, params.height * params.pixelRatio);
|
|
this.bindProgram(this.normalProgram);
|
|
this.renderProgram(params, this.normalProgram);
|
|
this.unbindProgram(this.normalProgram);
|
|
}
|
|
}, {
|
|
key: "drawWebGL",
|
|
value: function drawWebGL(method, _ref) {
|
|
var gl = _ref.gl,
|
|
frameBuffer = _ref.frameBuffer;
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
|
|
if (!this.isInstanced) {
|
|
gl.drawArrays(method, 0, this.verticesCount);
|
|
} else {
|
|
if (gl instanceof WebGL2RenderingContext) {
|
|
gl.drawArraysInstanced(method, 0, this.VERTICES, this.capacity);
|
|
} else {
|
|
var ext = gl.getExtension("ANGLE_instanced_arrays");
|
|
if (ext) ext.drawArraysInstancedANGLE(method, 0, this.VERTICES, this.capacity);
|
|
}
|
|
}
|
|
}
|
|
}]);
|
|
}();
|
|
|
|
var AbstractNodeProgram = /*#__PURE__*/function (_AbstractProgram) {
|
|
function AbstractNodeProgram() {
|
|
inherits._classCallCheck(this, AbstractNodeProgram);
|
|
return inherits._callSuper(this, AbstractNodeProgram, arguments);
|
|
}
|
|
inherits._inherits(AbstractNodeProgram, _AbstractProgram);
|
|
return inherits._createClass(AbstractNodeProgram);
|
|
}(AbstractProgram);
|
|
var NodeProgram = /*#__PURE__*/function (_ref) {
|
|
function NodeProgram() {
|
|
inherits._classCallCheck(this, NodeProgram);
|
|
return inherits._callSuper(this, NodeProgram, arguments);
|
|
}
|
|
inherits._inherits(NodeProgram, _ref);
|
|
return inherits._createClass(NodeProgram, [{
|
|
key: "kill",
|
|
value: function kill() {
|
|
_superPropGet(NodeProgram, "kill", this, 3)([]);
|
|
}
|
|
}, {
|
|
key: "process",
|
|
value: function process(nodeIndex, offset, data) {
|
|
var i = offset * this.STRIDE;
|
|
// NOTE: dealing with hidden items automatically
|
|
if (data.hidden) {
|
|
for (var l = i + this.STRIDE; i < l; i++) {
|
|
this.array[i] = 0;
|
|
}
|
|
return;
|
|
}
|
|
return this.processVisibleItem(colors.indexToColor(nodeIndex), i, data);
|
|
}
|
|
}]);
|
|
}(Program);
|
|
/**
|
|
* Helper function combining two or more programs into a single compound one.
|
|
* Note that this is more a quick & easy way to combine program than a really
|
|
* performant option. More performant programs can be written entirely.
|
|
*
|
|
* @param {array} programClasses - Program classes to combine.
|
|
* @param {function} drawLabel - An optional node "draw label" function.
|
|
* @param {function} drawHover - An optional node "draw hover" function.
|
|
* @return {function}
|
|
*/
|
|
function createNodeCompoundProgram(programClasses, drawLabel, drawHover) {
|
|
return /*#__PURE__*/function () {
|
|
function NodeCompoundProgram(gl, pickingBuffer, renderer) {
|
|
inherits._classCallCheck(this, NodeCompoundProgram);
|
|
_defineProperty(this, "drawLabel", drawLabel);
|
|
_defineProperty(this, "drawHover", drawHover);
|
|
this.programs = programClasses.map(function (Program) {
|
|
return new Program(gl, pickingBuffer, renderer);
|
|
});
|
|
}
|
|
return inherits._createClass(NodeCompoundProgram, [{
|
|
key: "reallocate",
|
|
value: function reallocate(capacity) {
|
|
this.programs.forEach(function (program) {
|
|
return program.reallocate(capacity);
|
|
});
|
|
}
|
|
}, {
|
|
key: "process",
|
|
value: function process(nodeIndex, offset, data) {
|
|
this.programs.forEach(function (program) {
|
|
return program.process(nodeIndex, offset, data);
|
|
});
|
|
}
|
|
}, {
|
|
key: "render",
|
|
value: function render(params) {
|
|
this.programs.forEach(function (program) {
|
|
return program.render(params);
|
|
});
|
|
}
|
|
}, {
|
|
key: "kill",
|
|
value: function kill() {
|
|
this.programs.forEach(function (program) {
|
|
return program.kill();
|
|
});
|
|
}
|
|
}]);
|
|
}();
|
|
}
|
|
|
|
var AbstractEdgeProgram = /*#__PURE__*/function (_AbstractProgram) {
|
|
function AbstractEdgeProgram() {
|
|
inherits._classCallCheck(this, AbstractEdgeProgram);
|
|
return inherits._callSuper(this, AbstractEdgeProgram, arguments);
|
|
}
|
|
inherits._inherits(AbstractEdgeProgram, _AbstractProgram);
|
|
return inherits._createClass(AbstractEdgeProgram);
|
|
}(AbstractProgram);
|
|
var EdgeProgram = /*#__PURE__*/function (_ref) {
|
|
function EdgeProgram() {
|
|
var _this;
|
|
inherits._classCallCheck(this, EdgeProgram);
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
_this = inherits._callSuper(this, EdgeProgram, [].concat(args));
|
|
_defineProperty(_this, "drawLabel", undefined);
|
|
return _this;
|
|
}
|
|
inherits._inherits(EdgeProgram, _ref);
|
|
return inherits._createClass(EdgeProgram, [{
|
|
key: "kill",
|
|
value: function kill() {
|
|
_superPropGet(EdgeProgram, "kill", this, 3)([]);
|
|
}
|
|
}, {
|
|
key: "process",
|
|
value: function process(edgeIndex, offset, sourceData, targetData, data) {
|
|
var i = offset * this.STRIDE;
|
|
// NOTE: dealing with hidden items automatically
|
|
if (data.hidden || sourceData.hidden || targetData.hidden) {
|
|
for (var l = i + this.STRIDE; i < l; i++) {
|
|
this.array[i] = 0;
|
|
}
|
|
return;
|
|
}
|
|
return this.processVisibleItem(colors.indexToColor(edgeIndex), i, sourceData, targetData, data);
|
|
}
|
|
}]);
|
|
}(Program);
|
|
/**
|
|
* Helper function combining two or more programs into a single compound one.
|
|
* Note that this is more a quick & easy way to combine program than a really
|
|
* performant option. More performant programs can be written entirely.
|
|
*
|
|
* @param {array} programClasses - Program classes to combine.
|
|
* @param {function} drawLabel - An optional edge "draw label" function.
|
|
* @return {function}
|
|
*/
|
|
function createEdgeCompoundProgram(programClasses, drawLabel) {
|
|
return /*#__PURE__*/function () {
|
|
function EdgeCompoundProgram(gl, pickingBuffer, renderer) {
|
|
inherits._classCallCheck(this, EdgeCompoundProgram);
|
|
_defineProperty(this, "drawLabel", drawLabel);
|
|
this.programs = programClasses.map(function (Program) {
|
|
return new Program(gl, pickingBuffer, renderer);
|
|
});
|
|
}
|
|
return inherits._createClass(EdgeCompoundProgram, [{
|
|
key: "reallocate",
|
|
value: function reallocate(capacity) {
|
|
this.programs.forEach(function (program) {
|
|
return program.reallocate(capacity);
|
|
});
|
|
}
|
|
}, {
|
|
key: "process",
|
|
value: function process(edgeIndex, offset, sourceData, targetData, data) {
|
|
this.programs.forEach(function (program) {
|
|
return program.process(edgeIndex, offset, sourceData, targetData, data);
|
|
});
|
|
}
|
|
}, {
|
|
key: "render",
|
|
value: function render(params) {
|
|
this.programs.forEach(function (program) {
|
|
return program.render(params);
|
|
});
|
|
}
|
|
}, {
|
|
key: "kill",
|
|
value: function kill() {
|
|
this.programs.forEach(function (program) {
|
|
return program.kill();
|
|
});
|
|
}
|
|
}]);
|
|
}();
|
|
}
|
|
|
|
function drawStraightEdgeLabel(context, edgeData, sourceData, targetData, settings) {
|
|
var size = settings.edgeLabelSize,
|
|
font = settings.edgeLabelFont,
|
|
weight = settings.edgeLabelWeight,
|
|
color = settings.edgeLabelColor.attribute ? edgeData[settings.edgeLabelColor.attribute] || settings.edgeLabelColor.color || "#000" : settings.edgeLabelColor.color;
|
|
var label = edgeData.label;
|
|
if (!label) return;
|
|
context.fillStyle = color;
|
|
context.font = "".concat(weight, " ").concat(size, "px ").concat(font);
|
|
|
|
// Computing positions without considering nodes sizes:
|
|
var sSize = sourceData.size;
|
|
var tSize = targetData.size;
|
|
var sx = sourceData.x;
|
|
var sy = sourceData.y;
|
|
var tx = targetData.x;
|
|
var ty = targetData.y;
|
|
var cx = (sx + tx) / 2;
|
|
var cy = (sy + ty) / 2;
|
|
var dx = tx - sx;
|
|
var dy = ty - sy;
|
|
var d = Math.sqrt(dx * dx + dy * dy);
|
|
if (d < sSize + tSize) return;
|
|
|
|
// Adding nodes sizes:
|
|
sx += dx * sSize / d;
|
|
sy += dy * sSize / d;
|
|
tx -= dx * tSize / d;
|
|
ty -= dy * tSize / d;
|
|
cx = (sx + tx) / 2;
|
|
cy = (sy + ty) / 2;
|
|
dx = tx - sx;
|
|
dy = ty - sy;
|
|
d = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
// Handling ellipsis
|
|
var textLength = context.measureText(label).width;
|
|
if (textLength > d) {
|
|
var ellipsis = "…";
|
|
label = label + ellipsis;
|
|
textLength = context.measureText(label).width;
|
|
while (textLength > d && label.length > 1) {
|
|
label = label.slice(0, -2) + ellipsis;
|
|
textLength = context.measureText(label).width;
|
|
}
|
|
if (label.length < 4) return;
|
|
}
|
|
var angle;
|
|
if (dx > 0) {
|
|
if (dy > 0) angle = Math.acos(dx / d);else angle = Math.asin(dy / d);
|
|
} else {
|
|
if (dy > 0) angle = Math.acos(dx / d) + Math.PI;else angle = Math.asin(dx / d) + Math.PI / 2;
|
|
}
|
|
context.save();
|
|
context.translate(cx, cy);
|
|
context.rotate(angle);
|
|
context.fillText(label, -textLength / 2, edgeData.size / 2 + size);
|
|
context.restore();
|
|
}
|
|
|
|
function drawDiscNodeLabel(context, data, settings) {
|
|
if (!data.label) return;
|
|
var size = settings.labelSize,
|
|
font = settings.labelFont,
|
|
weight = settings.labelWeight,
|
|
color = settings.labelColor.attribute ? data[settings.labelColor.attribute] || settings.labelColor.color || "#000" : settings.labelColor.color;
|
|
context.fillStyle = color;
|
|
context.font = "".concat(weight, " ").concat(size, "px ").concat(font);
|
|
context.fillText(data.label, data.x + data.size + 3, data.y + size / 3);
|
|
}
|
|
|
|
/**
|
|
* Draw an hovered node.
|
|
* - if there is no label => display a shadow on the node
|
|
* - if the label box is bigger than node size => display a label box that contains the node with a shadow
|
|
* - else node with shadow and the label box
|
|
*/
|
|
function drawDiscNodeHover(context, data, settings) {
|
|
var size = settings.labelSize,
|
|
font = settings.labelFont,
|
|
weight = settings.labelWeight;
|
|
context.font = "".concat(weight, " ").concat(size, "px ").concat(font);
|
|
|
|
// Then we draw the label background
|
|
context.fillStyle = "#FFF";
|
|
context.shadowOffsetX = 0;
|
|
context.shadowOffsetY = 0;
|
|
context.shadowBlur = 8;
|
|
context.shadowColor = "#000";
|
|
var PADDING = 2;
|
|
if (typeof data.label === "string") {
|
|
var textWidth = context.measureText(data.label).width,
|
|
boxWidth = Math.round(textWidth + 5),
|
|
boxHeight = Math.round(size + 2 * PADDING),
|
|
radius = Math.max(data.size, size / 2) + PADDING;
|
|
var angleRadian = Math.asin(boxHeight / 2 / radius);
|
|
var xDeltaCoord = Math.sqrt(Math.abs(Math.pow(radius, 2) - Math.pow(boxHeight / 2, 2)));
|
|
context.beginPath();
|
|
context.moveTo(data.x + xDeltaCoord, data.y + boxHeight / 2);
|
|
context.lineTo(data.x + radius + boxWidth, data.y + boxHeight / 2);
|
|
context.lineTo(data.x + radius + boxWidth, data.y - boxHeight / 2);
|
|
context.lineTo(data.x + xDeltaCoord, data.y - boxHeight / 2);
|
|
context.arc(data.x, data.y, radius, angleRadian, -angleRadian);
|
|
context.closePath();
|
|
context.fill();
|
|
} else {
|
|
context.beginPath();
|
|
context.arc(data.x, data.y, data.size + PADDING, 0, Math.PI * 2);
|
|
context.closePath();
|
|
context.fill();
|
|
}
|
|
context.shadowOffsetX = 0;
|
|
context.shadowOffsetY = 0;
|
|
context.shadowBlur = 0;
|
|
|
|
// And finally we draw the label
|
|
drawDiscNodeLabel(context, data, settings);
|
|
}
|
|
|
|
// language=GLSL
|
|
var SHADER_SOURCE$6 = /*glsl*/"\nprecision highp float;\n\nvarying vec4 v_color;\nvarying vec2 v_diffVector;\nvarying float v_radius;\n\nuniform float u_correctionRatio;\n\nconst vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);\n\nvoid main(void) {\n float border = u_correctionRatio * 2.0;\n float dist = length(v_diffVector) - v_radius + border;\n\n // No antialiasing for picking mode:\n #ifdef PICKING_MODE\n if (dist > border)\n gl_FragColor = transparent;\n else\n gl_FragColor = v_color;\n\n #else\n float t = 0.0;\n if (dist > border)\n t = 1.0;\n else if (dist > 0.0)\n t = dist / border;\n\n gl_FragColor = mix(v_color, transparent, t);\n #endif\n}\n";
|
|
var FRAGMENT_SHADER_SOURCE$2 = SHADER_SOURCE$6;
|
|
|
|
// language=GLSL
|
|
var SHADER_SOURCE$5 = /*glsl*/"\nattribute vec4 a_id;\nattribute vec4 a_color;\nattribute vec2 a_position;\nattribute float a_size;\nattribute float a_angle;\n\nuniform mat3 u_matrix;\nuniform float u_sizeRatio;\nuniform float u_correctionRatio;\n\nvarying vec4 v_color;\nvarying vec2 v_diffVector;\nvarying float v_radius;\nvarying float v_border;\n\nconst float bias = 255.0 / 254.0;\n\nvoid main() {\n float size = a_size * u_correctionRatio / u_sizeRatio * 4.0;\n vec2 diffVector = size * vec2(cos(a_angle), sin(a_angle));\n vec2 position = a_position + diffVector;\n gl_Position = vec4(\n (u_matrix * vec3(position, 1)).xy,\n 0,\n 1\n );\n\n v_diffVector = diffVector;\n v_radius = size / 2.0;\n\n #ifdef PICKING_MODE\n // For picking mode, we use the ID as the color:\n v_color = a_id;\n #else\n // For normal mode, we use the color:\n v_color = a_color;\n #endif\n\n v_color.a *= bias;\n}\n";
|
|
var VERTEX_SHADER_SOURCE$3 = SHADER_SOURCE$5;
|
|
|
|
var _WebGLRenderingContex$3 = WebGLRenderingContext,
|
|
UNSIGNED_BYTE$3 = _WebGLRenderingContex$3.UNSIGNED_BYTE,
|
|
FLOAT$3 = _WebGLRenderingContex$3.FLOAT;
|
|
var UNIFORMS$3 = ["u_sizeRatio", "u_correctionRatio", "u_matrix"];
|
|
var NodeCircleProgram = /*#__PURE__*/function (_NodeProgram) {
|
|
function NodeCircleProgram() {
|
|
inherits._classCallCheck(this, NodeCircleProgram);
|
|
return inherits._callSuper(this, NodeCircleProgram, arguments);
|
|
}
|
|
inherits._inherits(NodeCircleProgram, _NodeProgram);
|
|
return inherits._createClass(NodeCircleProgram, [{
|
|
key: "getDefinition",
|
|
value: function getDefinition() {
|
|
return {
|
|
VERTICES: 3,
|
|
VERTEX_SHADER_SOURCE: VERTEX_SHADER_SOURCE$3,
|
|
FRAGMENT_SHADER_SOURCE: FRAGMENT_SHADER_SOURCE$2,
|
|
METHOD: WebGLRenderingContext.TRIANGLES,
|
|
UNIFORMS: UNIFORMS$3,
|
|
ATTRIBUTES: [{
|
|
name: "a_position",
|
|
size: 2,
|
|
type: FLOAT$3
|
|
}, {
|
|
name: "a_size",
|
|
size: 1,
|
|
type: FLOAT$3
|
|
}, {
|
|
name: "a_color",
|
|
size: 4,
|
|
type: UNSIGNED_BYTE$3,
|
|
normalized: true
|
|
}, {
|
|
name: "a_id",
|
|
size: 4,
|
|
type: UNSIGNED_BYTE$3,
|
|
normalized: true
|
|
}],
|
|
CONSTANT_ATTRIBUTES: [{
|
|
name: "a_angle",
|
|
size: 1,
|
|
type: FLOAT$3
|
|
}],
|
|
CONSTANT_DATA: [[NodeCircleProgram.ANGLE_1], [NodeCircleProgram.ANGLE_2], [NodeCircleProgram.ANGLE_3]]
|
|
};
|
|
}
|
|
}, {
|
|
key: "processVisibleItem",
|
|
value: function processVisibleItem(nodeIndex, startIndex, data) {
|
|
var array = this.array;
|
|
var color = colors.floatColor(data.color);
|
|
array[startIndex++] = data.x;
|
|
array[startIndex++] = data.y;
|
|
array[startIndex++] = data.size;
|
|
array[startIndex++] = color;
|
|
array[startIndex++] = nodeIndex;
|
|
}
|
|
}, {
|
|
key: "setUniforms",
|
|
value: function setUniforms(params, _ref) {
|
|
var gl = _ref.gl,
|
|
uniformLocations = _ref.uniformLocations;
|
|
var u_sizeRatio = uniformLocations.u_sizeRatio,
|
|
u_correctionRatio = uniformLocations.u_correctionRatio,
|
|
u_matrix = uniformLocations.u_matrix;
|
|
gl.uniform1f(u_correctionRatio, params.correctionRatio);
|
|
gl.uniform1f(u_sizeRatio, params.sizeRatio);
|
|
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
|
|
}
|
|
}]);
|
|
}(NodeProgram);
|
|
_defineProperty(NodeCircleProgram, "ANGLE_1", 0);
|
|
_defineProperty(NodeCircleProgram, "ANGLE_2", 2 * Math.PI / 3);
|
|
_defineProperty(NodeCircleProgram, "ANGLE_3", 4 * Math.PI / 3);
|
|
|
|
// language=GLSL
|
|
var SHADER_SOURCE$4 = /*glsl*/"\nprecision mediump float;\n\nvarying vec4 v_color;\n\nvoid main(void) {\n gl_FragColor = v_color;\n}\n";
|
|
var FRAGMENT_SHADER_SOURCE$1 = SHADER_SOURCE$4;
|
|
|
|
// language=GLSL
|
|
var SHADER_SOURCE$3 = /*glsl*/"\nattribute vec2 a_position;\nattribute vec2 a_normal;\nattribute float a_radius;\nattribute vec3 a_barycentric;\n\n#ifdef PICKING_MODE\nattribute vec4 a_id;\n#else\nattribute vec4 a_color;\n#endif\n\nuniform mat3 u_matrix;\nuniform float u_sizeRatio;\nuniform float u_correctionRatio;\nuniform float u_minEdgeThickness;\nuniform float u_lengthToThicknessRatio;\nuniform float u_widenessToThicknessRatio;\n\nvarying vec4 v_color;\n\nconst float bias = 255.0 / 254.0;\n\nvoid main() {\n float minThickness = u_minEdgeThickness;\n\n float normalLength = length(a_normal);\n vec2 unitNormal = a_normal / normalLength;\n\n // These first computations are taken from edge.vert.glsl and\n // edge.clamped.vert.glsl. Please read it to get better comments on what's\n // happening:\n float pixelsThickness = max(normalLength / u_sizeRatio, minThickness);\n float webGLThickness = pixelsThickness * u_correctionRatio;\n float webGLNodeRadius = a_radius * 2.0 * u_correctionRatio / u_sizeRatio;\n float webGLArrowHeadLength = webGLThickness * u_lengthToThicknessRatio * 2.0;\n float webGLArrowHeadThickness = webGLThickness * u_widenessToThicknessRatio;\n\n float da = a_barycentric.x;\n float db = a_barycentric.y;\n float dc = a_barycentric.z;\n\n vec2 delta = vec2(\n da * (webGLNodeRadius * unitNormal.y)\n + db * ((webGLNodeRadius + webGLArrowHeadLength) * unitNormal.y + webGLArrowHeadThickness * unitNormal.x)\n + dc * ((webGLNodeRadius + webGLArrowHeadLength) * unitNormal.y - webGLArrowHeadThickness * unitNormal.x),\n\n da * (-webGLNodeRadius * unitNormal.x)\n + db * (-(webGLNodeRadius + webGLArrowHeadLength) * unitNormal.x + webGLArrowHeadThickness * unitNormal.y)\n + dc * (-(webGLNodeRadius + webGLArrowHeadLength) * unitNormal.x - webGLArrowHeadThickness * unitNormal.y)\n );\n\n vec2 position = (u_matrix * vec3(a_position + delta, 1)).xy;\n\n gl_Position = vec4(position, 0, 1);\n\n #ifdef PICKING_MODE\n // For picking mode, we use the ID as the color:\n v_color = a_id;\n #else\n // For normal mode, we use the color:\n v_color = a_color;\n #endif\n\n v_color.a *= bias;\n}\n";
|
|
var VERTEX_SHADER_SOURCE$2 = SHADER_SOURCE$3;
|
|
|
|
var _WebGLRenderingContex$2 = WebGLRenderingContext,
|
|
UNSIGNED_BYTE$2 = _WebGLRenderingContex$2.UNSIGNED_BYTE,
|
|
FLOAT$2 = _WebGLRenderingContex$2.FLOAT;
|
|
var UNIFORMS$2 = ["u_matrix", "u_sizeRatio", "u_correctionRatio", "u_minEdgeThickness", "u_lengthToThicknessRatio", "u_widenessToThicknessRatio"];
|
|
var DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS = {
|
|
extremity: "target",
|
|
lengthToThicknessRatio: 2.5,
|
|
widenessToThicknessRatio: 2
|
|
};
|
|
function createEdgeArrowHeadProgram(inputOptions) {
|
|
var options = _objectSpread2(_objectSpread2({}, DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS), inputOptions || {});
|
|
return /*#__PURE__*/function (_EdgeProgram) {
|
|
function EdgeArrowHeadProgram() {
|
|
inherits._classCallCheck(this, EdgeArrowHeadProgram);
|
|
return inherits._callSuper(this, EdgeArrowHeadProgram, arguments);
|
|
}
|
|
inherits._inherits(EdgeArrowHeadProgram, _EdgeProgram);
|
|
return inherits._createClass(EdgeArrowHeadProgram, [{
|
|
key: "getDefinition",
|
|
value: function getDefinition() {
|
|
return {
|
|
VERTICES: 3,
|
|
VERTEX_SHADER_SOURCE: VERTEX_SHADER_SOURCE$2,
|
|
FRAGMENT_SHADER_SOURCE: FRAGMENT_SHADER_SOURCE$1,
|
|
METHOD: WebGLRenderingContext.TRIANGLES,
|
|
UNIFORMS: UNIFORMS$2,
|
|
ATTRIBUTES: [{
|
|
name: "a_position",
|
|
size: 2,
|
|
type: FLOAT$2
|
|
}, {
|
|
name: "a_normal",
|
|
size: 2,
|
|
type: FLOAT$2
|
|
}, {
|
|
name: "a_radius",
|
|
size: 1,
|
|
type: FLOAT$2
|
|
}, {
|
|
name: "a_color",
|
|
size: 4,
|
|
type: UNSIGNED_BYTE$2,
|
|
normalized: true
|
|
}, {
|
|
name: "a_id",
|
|
size: 4,
|
|
type: UNSIGNED_BYTE$2,
|
|
normalized: true
|
|
}],
|
|
CONSTANT_ATTRIBUTES: [{
|
|
name: "a_barycentric",
|
|
size: 3,
|
|
type: FLOAT$2
|
|
}],
|
|
CONSTANT_DATA: [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
|
|
};
|
|
}
|
|
}, {
|
|
key: "processVisibleItem",
|
|
value: function processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) {
|
|
if (options.extremity === "source") {
|
|
var _ref = [targetData, sourceData];
|
|
sourceData = _ref[0];
|
|
targetData = _ref[1];
|
|
}
|
|
var thickness = data.size || 1;
|
|
var radius = targetData.size || 1;
|
|
var x1 = sourceData.x;
|
|
var y1 = sourceData.y;
|
|
var x2 = targetData.x;
|
|
var y2 = targetData.y;
|
|
var color = colors.floatColor(data.color);
|
|
|
|
// Computing normals
|
|
var dx = x2 - x1;
|
|
var dy = y2 - y1;
|
|
var len = dx * dx + dy * dy;
|
|
var n1 = 0;
|
|
var n2 = 0;
|
|
if (len) {
|
|
len = 1 / Math.sqrt(len);
|
|
n1 = -dy * len * thickness;
|
|
n2 = dx * len * thickness;
|
|
}
|
|
var array = this.array;
|
|
array[startIndex++] = x2;
|
|
array[startIndex++] = y2;
|
|
array[startIndex++] = -n1;
|
|
array[startIndex++] = -n2;
|
|
array[startIndex++] = radius;
|
|
array[startIndex++] = color;
|
|
array[startIndex++] = edgeIndex;
|
|
}
|
|
}, {
|
|
key: "setUniforms",
|
|
value: function setUniforms(params, _ref2) {
|
|
var gl = _ref2.gl,
|
|
uniformLocations = _ref2.uniformLocations;
|
|
var u_matrix = uniformLocations.u_matrix,
|
|
u_sizeRatio = uniformLocations.u_sizeRatio,
|
|
u_correctionRatio = uniformLocations.u_correctionRatio,
|
|
u_minEdgeThickness = uniformLocations.u_minEdgeThickness,
|
|
u_lengthToThicknessRatio = uniformLocations.u_lengthToThicknessRatio,
|
|
u_widenessToThicknessRatio = uniformLocations.u_widenessToThicknessRatio;
|
|
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
|
|
gl.uniform1f(u_sizeRatio, params.sizeRatio);
|
|
gl.uniform1f(u_correctionRatio, params.correctionRatio);
|
|
gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness);
|
|
gl.uniform1f(u_lengthToThicknessRatio, options.lengthToThicknessRatio);
|
|
gl.uniform1f(u_widenessToThicknessRatio, options.widenessToThicknessRatio);
|
|
}
|
|
}]);
|
|
}(EdgeProgram);
|
|
}
|
|
var EdgeArrowHeadProgram = createEdgeArrowHeadProgram();
|
|
var EdgeArrowHeadProgram$1 = EdgeArrowHeadProgram;
|
|
|
|
// language=GLSL
|
|
var SHADER_SOURCE$2 = /*glsl*/"\nprecision mediump float;\n\nvarying vec4 v_color;\nvarying vec2 v_normal;\nvarying float v_thickness;\nvarying float v_feather;\n\nconst vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);\n\nvoid main(void) {\n // We only handle antialiasing for normal mode:\n #ifdef PICKING_MODE\n gl_FragColor = v_color;\n #else\n float dist = length(v_normal) * v_thickness;\n\n float t = smoothstep(\n v_thickness - v_feather,\n v_thickness,\n dist\n );\n\n gl_FragColor = mix(v_color, transparent, t);\n #endif\n}\n";
|
|
var FRAGMENT_SHADER_SOURCE = SHADER_SOURCE$2;
|
|
|
|
// language=GLSL
|
|
var SHADER_SOURCE$1 = /*glsl*/"\nattribute vec4 a_id;\nattribute vec4 a_color;\nattribute vec2 a_normal;\nattribute float a_normalCoef;\nattribute vec2 a_positionStart;\nattribute vec2 a_positionEnd;\nattribute float a_positionCoef;\nattribute float a_radius;\nattribute float a_radiusCoef;\n\nuniform mat3 u_matrix;\nuniform float u_zoomRatio;\nuniform float u_sizeRatio;\nuniform float u_pixelRatio;\nuniform float u_correctionRatio;\nuniform float u_minEdgeThickness;\nuniform float u_lengthToThicknessRatio;\nuniform float u_feather;\n\nvarying vec4 v_color;\nvarying vec2 v_normal;\nvarying float v_thickness;\nvarying float v_feather;\n\nconst float bias = 255.0 / 254.0;\n\nvoid main() {\n float minThickness = u_minEdgeThickness;\n\n float radius = a_radius * a_radiusCoef;\n vec2 normal = a_normal * a_normalCoef;\n vec2 position = a_positionStart * (1.0 - a_positionCoef) + a_positionEnd * a_positionCoef;\n\n float normalLength = length(normal);\n vec2 unitNormal = normal / normalLength;\n\n // These first computations are taken from edge.vert.glsl. Please read it to\n // get better comments on what's happening:\n float pixelsThickness = max(normalLength, minThickness * u_sizeRatio);\n float webGLThickness = pixelsThickness * u_correctionRatio / u_sizeRatio;\n\n // Here, we move the point to leave space for the arrow head:\n float direction = sign(radius);\n float webGLNodeRadius = direction * radius * 2.0 * u_correctionRatio / u_sizeRatio;\n float webGLArrowHeadLength = webGLThickness * u_lengthToThicknessRatio * 2.0;\n\n vec2 compensationVector = vec2(-direction * unitNormal.y, direction * unitNormal.x) * (webGLNodeRadius + webGLArrowHeadLength);\n\n // Here is the proper position of the vertex\n gl_Position = vec4((u_matrix * vec3(position + unitNormal * webGLThickness + compensationVector, 1)).xy, 0, 1);\n\n v_thickness = webGLThickness / u_zoomRatio;\n\n v_normal = unitNormal;\n\n v_feather = u_feather * u_correctionRatio / u_zoomRatio / u_pixelRatio * 2.0;\n\n #ifdef PICKING_MODE\n // For picking mode, we use the ID as the color:\n v_color = a_id;\n #else\n // For normal mode, we use the color:\n v_color = a_color;\n #endif\n\n v_color.a *= bias;\n}\n";
|
|
var VERTEX_SHADER_SOURCE$1 = SHADER_SOURCE$1;
|
|
|
|
var _WebGLRenderingContex$1 = WebGLRenderingContext,
|
|
UNSIGNED_BYTE$1 = _WebGLRenderingContex$1.UNSIGNED_BYTE,
|
|
FLOAT$1 = _WebGLRenderingContex$1.FLOAT;
|
|
var UNIFORMS$1 = ["u_matrix", "u_zoomRatio", "u_sizeRatio", "u_correctionRatio", "u_pixelRatio", "u_feather", "u_minEdgeThickness", "u_lengthToThicknessRatio"];
|
|
var DEFAULT_EDGE_CLAMPED_PROGRAM_OPTIONS = {
|
|
lengthToThicknessRatio: DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS.lengthToThicknessRatio
|
|
};
|
|
function createEdgeClampedProgram(inputOptions) {
|
|
var options = _objectSpread2(_objectSpread2({}, DEFAULT_EDGE_CLAMPED_PROGRAM_OPTIONS), inputOptions || {});
|
|
return /*#__PURE__*/function (_EdgeProgram) {
|
|
function EdgeClampedProgram() {
|
|
inherits._classCallCheck(this, EdgeClampedProgram);
|
|
return inherits._callSuper(this, EdgeClampedProgram, arguments);
|
|
}
|
|
inherits._inherits(EdgeClampedProgram, _EdgeProgram);
|
|
return inherits._createClass(EdgeClampedProgram, [{
|
|
key: "getDefinition",
|
|
value: function getDefinition() {
|
|
return {
|
|
VERTICES: 6,
|
|
VERTEX_SHADER_SOURCE: VERTEX_SHADER_SOURCE$1,
|
|
FRAGMENT_SHADER_SOURCE: FRAGMENT_SHADER_SOURCE,
|
|
METHOD: WebGLRenderingContext.TRIANGLES,
|
|
UNIFORMS: UNIFORMS$1,
|
|
ATTRIBUTES: [{
|
|
name: "a_positionStart",
|
|
size: 2,
|
|
type: FLOAT$1
|
|
}, {
|
|
name: "a_positionEnd",
|
|
size: 2,
|
|
type: FLOAT$1
|
|
}, {
|
|
name: "a_normal",
|
|
size: 2,
|
|
type: FLOAT$1
|
|
}, {
|
|
name: "a_color",
|
|
size: 4,
|
|
type: UNSIGNED_BYTE$1,
|
|
normalized: true
|
|
}, {
|
|
name: "a_id",
|
|
size: 4,
|
|
type: UNSIGNED_BYTE$1,
|
|
normalized: true
|
|
}, {
|
|
name: "a_radius",
|
|
size: 1,
|
|
type: FLOAT$1
|
|
}],
|
|
CONSTANT_ATTRIBUTES: [
|
|
// If 0, then position will be a_positionStart
|
|
// If 1, then position will be a_positionEnd
|
|
{
|
|
name: "a_positionCoef",
|
|
size: 1,
|
|
type: FLOAT$1
|
|
}, {
|
|
name: "a_normalCoef",
|
|
size: 1,
|
|
type: FLOAT$1
|
|
}, {
|
|
name: "a_radiusCoef",
|
|
size: 1,
|
|
type: FLOAT$1
|
|
}],
|
|
CONSTANT_DATA: [[0, 1, 0], [0, -1, 0], [1, 1, 1], [1, 1, 1], [0, -1, 0], [1, -1, -1]]
|
|
};
|
|
}
|
|
}, {
|
|
key: "processVisibleItem",
|
|
value: function processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) {
|
|
var thickness = data.size || 1;
|
|
var x1 = sourceData.x;
|
|
var y1 = sourceData.y;
|
|
var x2 = targetData.x;
|
|
var y2 = targetData.y;
|
|
var color = colors.floatColor(data.color);
|
|
|
|
// Computing normals
|
|
var dx = x2 - x1;
|
|
var dy = y2 - y1;
|
|
var radius = targetData.size || 1;
|
|
var len = dx * dx + dy * dy;
|
|
var n1 = 0;
|
|
var n2 = 0;
|
|
if (len) {
|
|
len = 1 / Math.sqrt(len);
|
|
n1 = -dy * len * thickness;
|
|
n2 = dx * len * thickness;
|
|
}
|
|
var array = this.array;
|
|
array[startIndex++] = x1;
|
|
array[startIndex++] = y1;
|
|
array[startIndex++] = x2;
|
|
array[startIndex++] = y2;
|
|
array[startIndex++] = n1;
|
|
array[startIndex++] = n2;
|
|
array[startIndex++] = color;
|
|
array[startIndex++] = edgeIndex;
|
|
array[startIndex++] = radius;
|
|
}
|
|
}, {
|
|
key: "setUniforms",
|
|
value: function setUniforms(params, _ref) {
|
|
var gl = _ref.gl,
|
|
uniformLocations = _ref.uniformLocations;
|
|
var u_matrix = uniformLocations.u_matrix,
|
|
u_zoomRatio = uniformLocations.u_zoomRatio,
|
|
u_feather = uniformLocations.u_feather,
|
|
u_pixelRatio = uniformLocations.u_pixelRatio,
|
|
u_correctionRatio = uniformLocations.u_correctionRatio,
|
|
u_sizeRatio = uniformLocations.u_sizeRatio,
|
|
u_minEdgeThickness = uniformLocations.u_minEdgeThickness,
|
|
u_lengthToThicknessRatio = uniformLocations.u_lengthToThicknessRatio;
|
|
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
|
|
gl.uniform1f(u_zoomRatio, params.zoomRatio);
|
|
gl.uniform1f(u_sizeRatio, params.sizeRatio);
|
|
gl.uniform1f(u_correctionRatio, params.correctionRatio);
|
|
gl.uniform1f(u_pixelRatio, params.pixelRatio);
|
|
gl.uniform1f(u_feather, params.antiAliasingFeather);
|
|
gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness);
|
|
gl.uniform1f(u_lengthToThicknessRatio, options.lengthToThicknessRatio);
|
|
}
|
|
}]);
|
|
}(EdgeProgram);
|
|
}
|
|
var EdgeClampedProgram = createEdgeClampedProgram();
|
|
var EdgeClampedProgram$1 = EdgeClampedProgram;
|
|
|
|
function createEdgeArrowProgram(inputOptions) {
|
|
return createEdgeCompoundProgram([createEdgeClampedProgram(inputOptions), createEdgeArrowHeadProgram(inputOptions)]);
|
|
}
|
|
var EdgeArrowProgram = createEdgeArrowProgram();
|
|
var EdgeArrowProgram$1 = EdgeArrowProgram;
|
|
|
|
// language=GLSL
|
|
var SHADER_SOURCE = /*glsl*/"\nattribute vec4 a_id;\nattribute vec4 a_color;\nattribute vec2 a_normal;\nattribute float a_normalCoef;\nattribute vec2 a_positionStart;\nattribute vec2 a_positionEnd;\nattribute float a_positionCoef;\n\nuniform mat3 u_matrix;\nuniform float u_sizeRatio;\nuniform float u_zoomRatio;\nuniform float u_pixelRatio;\nuniform float u_correctionRatio;\nuniform float u_minEdgeThickness;\nuniform float u_feather;\n\nvarying vec4 v_color;\nvarying vec2 v_normal;\nvarying float v_thickness;\nvarying float v_feather;\n\nconst float bias = 255.0 / 254.0;\n\nvoid main() {\n float minThickness = u_minEdgeThickness;\n\n vec2 normal = a_normal * a_normalCoef;\n vec2 position = a_positionStart * (1.0 - a_positionCoef) + a_positionEnd * a_positionCoef;\n\n float normalLength = length(normal);\n vec2 unitNormal = normal / normalLength;\n\n // We require edges to be at least \"minThickness\" pixels thick *on screen*\n // (so we need to compensate the size ratio):\n float pixelsThickness = max(normalLength, minThickness * u_sizeRatio);\n\n // Then, we need to retrieve the normalized thickness of the edge in the WebGL\n // referential (in a ([0, 1], [0, 1]) space), using our \"magic\" correction\n // ratio:\n float webGLThickness = pixelsThickness * u_correctionRatio / u_sizeRatio;\n\n // Here is the proper position of the vertex\n gl_Position = vec4((u_matrix * vec3(position + unitNormal * webGLThickness, 1)).xy, 0, 1);\n\n // For the fragment shader though, we need a thickness that takes the \"magic\"\n // correction ratio into account (as in webGLThickness), but so that the\n // antialiasing effect does not depend on the zoom level. So here's yet\n // another thickness version:\n v_thickness = webGLThickness / u_zoomRatio;\n\n v_normal = unitNormal;\n\n v_feather = u_feather * u_correctionRatio / u_zoomRatio / u_pixelRatio * 2.0;\n\n #ifdef PICKING_MODE\n // For picking mode, we use the ID as the color:\n v_color = a_id;\n #else\n // For normal mode, we use the color:\n v_color = a_color;\n #endif\n\n v_color.a *= bias;\n}\n";
|
|
var VERTEX_SHADER_SOURCE = SHADER_SOURCE;
|
|
|
|
var _WebGLRenderingContex = WebGLRenderingContext,
|
|
UNSIGNED_BYTE = _WebGLRenderingContex.UNSIGNED_BYTE,
|
|
FLOAT = _WebGLRenderingContex.FLOAT;
|
|
var UNIFORMS = ["u_matrix", "u_zoomRatio", "u_sizeRatio", "u_correctionRatio", "u_pixelRatio", "u_feather", "u_minEdgeThickness"];
|
|
var EdgeRectangleProgram = /*#__PURE__*/function (_EdgeProgram) {
|
|
function EdgeRectangleProgram() {
|
|
inherits._classCallCheck(this, EdgeRectangleProgram);
|
|
return inherits._callSuper(this, EdgeRectangleProgram, arguments);
|
|
}
|
|
inherits._inherits(EdgeRectangleProgram, _EdgeProgram);
|
|
return inherits._createClass(EdgeRectangleProgram, [{
|
|
key: "getDefinition",
|
|
value: function getDefinition() {
|
|
return {
|
|
VERTICES: 6,
|
|
VERTEX_SHADER_SOURCE: VERTEX_SHADER_SOURCE,
|
|
FRAGMENT_SHADER_SOURCE: FRAGMENT_SHADER_SOURCE,
|
|
METHOD: WebGLRenderingContext.TRIANGLES,
|
|
UNIFORMS: UNIFORMS,
|
|
ATTRIBUTES: [{
|
|
name: "a_positionStart",
|
|
size: 2,
|
|
type: FLOAT
|
|
}, {
|
|
name: "a_positionEnd",
|
|
size: 2,
|
|
type: FLOAT
|
|
}, {
|
|
name: "a_normal",
|
|
size: 2,
|
|
type: FLOAT
|
|
}, {
|
|
name: "a_color",
|
|
size: 4,
|
|
type: UNSIGNED_BYTE,
|
|
normalized: true
|
|
}, {
|
|
name: "a_id",
|
|
size: 4,
|
|
type: UNSIGNED_BYTE,
|
|
normalized: true
|
|
}],
|
|
CONSTANT_ATTRIBUTES: [
|
|
// If 0, then position will be a_positionStart
|
|
// If 2, then position will be a_positionEnd
|
|
{
|
|
name: "a_positionCoef",
|
|
size: 1,
|
|
type: FLOAT
|
|
}, {
|
|
name: "a_normalCoef",
|
|
size: 1,
|
|
type: FLOAT
|
|
}],
|
|
CONSTANT_DATA: [[0, 1], [0, -1], [1, 1], [1, 1], [0, -1], [1, -1]]
|
|
};
|
|
}
|
|
}, {
|
|
key: "processVisibleItem",
|
|
value: function processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) {
|
|
var thickness = data.size || 1;
|
|
var x1 = sourceData.x;
|
|
var y1 = sourceData.y;
|
|
var x2 = targetData.x;
|
|
var y2 = targetData.y;
|
|
var color = colors.floatColor(data.color);
|
|
|
|
// Computing normals
|
|
var dx = x2 - x1;
|
|
var dy = y2 - y1;
|
|
var len = dx * dx + dy * dy;
|
|
var n1 = 0;
|
|
var n2 = 0;
|
|
if (len) {
|
|
len = 1 / Math.sqrt(len);
|
|
n1 = -dy * len * thickness;
|
|
n2 = dx * len * thickness;
|
|
}
|
|
var array = this.array;
|
|
array[startIndex++] = x1;
|
|
array[startIndex++] = y1;
|
|
array[startIndex++] = x2;
|
|
array[startIndex++] = y2;
|
|
array[startIndex++] = n1;
|
|
array[startIndex++] = n2;
|
|
array[startIndex++] = color;
|
|
array[startIndex++] = edgeIndex;
|
|
}
|
|
}, {
|
|
key: "setUniforms",
|
|
value: function setUniforms(params, _ref) {
|
|
var gl = _ref.gl,
|
|
uniformLocations = _ref.uniformLocations;
|
|
var u_matrix = uniformLocations.u_matrix,
|
|
u_zoomRatio = uniformLocations.u_zoomRatio,
|
|
u_feather = uniformLocations.u_feather,
|
|
u_pixelRatio = uniformLocations.u_pixelRatio,
|
|
u_correctionRatio = uniformLocations.u_correctionRatio,
|
|
u_sizeRatio = uniformLocations.u_sizeRatio,
|
|
u_minEdgeThickness = uniformLocations.u_minEdgeThickness;
|
|
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
|
|
gl.uniform1f(u_zoomRatio, params.zoomRatio);
|
|
gl.uniform1f(u_sizeRatio, params.sizeRatio);
|
|
gl.uniform1f(u_correctionRatio, params.correctionRatio);
|
|
gl.uniform1f(u_pixelRatio, params.pixelRatio);
|
|
gl.uniform1f(u_feather, params.antiAliasingFeather);
|
|
gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness);
|
|
}
|
|
}]);
|
|
}(EdgeProgram);
|
|
|
|
exports.AbstractEdgeProgram = AbstractEdgeProgram;
|
|
exports.AbstractNodeProgram = AbstractNodeProgram;
|
|
exports.AbstractProgram = AbstractProgram;
|
|
exports.DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS = DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS;
|
|
exports.DEFAULT_EDGE_CLAMPED_PROGRAM_OPTIONS = DEFAULT_EDGE_CLAMPED_PROGRAM_OPTIONS;
|
|
exports.EdgeArrowHeadProgram = EdgeArrowHeadProgram$1;
|
|
exports.EdgeArrowProgram = EdgeArrowProgram$1;
|
|
exports.EdgeClampedProgram = EdgeClampedProgram$1;
|
|
exports.EdgeProgram = EdgeProgram;
|
|
exports.EdgeRectangleProgram = EdgeRectangleProgram;
|
|
exports.FRAGMENT_SHADER_SOURCE = FRAGMENT_SHADER_SOURCE;
|
|
exports.NodeCircleProgram = NodeCircleProgram;
|
|
exports.NodeProgram = NodeProgram;
|
|
exports.Program = Program;
|
|
exports._defineProperty = _defineProperty;
|
|
exports._objectSpread2 = _objectSpread2;
|
|
exports.createEdgeArrowHeadProgram = createEdgeArrowHeadProgram;
|
|
exports.createEdgeArrowProgram = createEdgeArrowProgram;
|
|
exports.createEdgeClampedProgram = createEdgeClampedProgram;
|
|
exports.createEdgeCompoundProgram = createEdgeCompoundProgram;
|
|
exports.createNodeCompoundProgram = createNodeCompoundProgram;
|
|
exports.drawDiscNodeHover = drawDiscNodeHover;
|
|
exports.drawDiscNodeLabel = drawDiscNodeLabel;
|
|
exports.drawStraightEdgeLabel = drawStraightEdgeLabel;
|
|
exports.getAttributeItemsCount = getAttributeItemsCount;
|
|
exports.getAttributesItemsCount = getAttributesItemsCount;
|
|
exports.killProgram = killProgram;
|
|
exports.loadFragmentShader = loadFragmentShader;
|
|
exports.loadProgram = loadProgram;
|
|
exports.loadVertexShader = loadVertexShader;
|
|
exports.numberToGLSLFloat = numberToGLSLFloat;
|