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.
1170 lines
50 KiB
JavaScript
1170 lines
50 KiB
JavaScript
import { d as _toPropertyKey, e as _getPrototypeOf, a as _createClass, b as _classCallCheck, _ as _inherits, c as _callSuper } from './inherits-d1a1e29b.esm.js';
|
|
import { i as indexToColor, f as floatColor } from './colors-beb06eb2.esm.js';
|
|
|
|
function _defineProperty(e, r, t) {
|
|
return (r = _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 = _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(_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__*/_createClass(function AbstractProgram(_gl, _pickGl, _renderer) {
|
|
_classCallCheck(this, AbstractProgram);
|
|
});
|
|
var Program = /*#__PURE__*/function () {
|
|
function Program(gl, pickingBuffer, renderer) {
|
|
_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 _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() {
|
|
_classCallCheck(this, AbstractNodeProgram);
|
|
return _callSuper(this, AbstractNodeProgram, arguments);
|
|
}
|
|
_inherits(AbstractNodeProgram, _AbstractProgram);
|
|
return _createClass(AbstractNodeProgram);
|
|
}(AbstractProgram);
|
|
var NodeProgram = /*#__PURE__*/function (_ref) {
|
|
function NodeProgram() {
|
|
_classCallCheck(this, NodeProgram);
|
|
return _callSuper(this, NodeProgram, arguments);
|
|
}
|
|
_inherits(NodeProgram, _ref);
|
|
return _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(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) {
|
|
_classCallCheck(this, NodeCompoundProgram);
|
|
_defineProperty(this, "drawLabel", drawLabel);
|
|
_defineProperty(this, "drawHover", drawHover);
|
|
this.programs = programClasses.map(function (Program) {
|
|
return new Program(gl, pickingBuffer, renderer);
|
|
});
|
|
}
|
|
return _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() {
|
|
_classCallCheck(this, AbstractEdgeProgram);
|
|
return _callSuper(this, AbstractEdgeProgram, arguments);
|
|
}
|
|
_inherits(AbstractEdgeProgram, _AbstractProgram);
|
|
return _createClass(AbstractEdgeProgram);
|
|
}(AbstractProgram);
|
|
var EdgeProgram = /*#__PURE__*/function (_ref) {
|
|
function EdgeProgram() {
|
|
var _this;
|
|
_classCallCheck(this, EdgeProgram);
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
_this = _callSuper(this, EdgeProgram, [].concat(args));
|
|
_defineProperty(_this, "drawLabel", undefined);
|
|
return _this;
|
|
}
|
|
_inherits(EdgeProgram, _ref);
|
|
return _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(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) {
|
|
_classCallCheck(this, EdgeCompoundProgram);
|
|
_defineProperty(this, "drawLabel", drawLabel);
|
|
this.programs = programClasses.map(function (Program) {
|
|
return new Program(gl, pickingBuffer, renderer);
|
|
});
|
|
}
|
|
return _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() {
|
|
_classCallCheck(this, NodeCircleProgram);
|
|
return _callSuper(this, NodeCircleProgram, arguments);
|
|
}
|
|
_inherits(NodeCircleProgram, _NodeProgram);
|
|
return _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 = 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() {
|
|
_classCallCheck(this, EdgeArrowHeadProgram);
|
|
return _callSuper(this, EdgeArrowHeadProgram, arguments);
|
|
}
|
|
_inherits(EdgeArrowHeadProgram, _EdgeProgram);
|
|
return _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 = 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() {
|
|
_classCallCheck(this, EdgeClampedProgram);
|
|
return _callSuper(this, EdgeClampedProgram, arguments);
|
|
}
|
|
_inherits(EdgeClampedProgram, _EdgeProgram);
|
|
return _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 = 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() {
|
|
_classCallCheck(this, EdgeRectangleProgram);
|
|
return _callSuper(this, EdgeRectangleProgram, arguments);
|
|
}
|
|
_inherits(EdgeRectangleProgram, _EdgeProgram);
|
|
return _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 = 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);
|
|
|
|
export { AbstractNodeProgram as A, DEFAULT_EDGE_ARROW_HEAD_PROGRAM_OPTIONS as D, EdgeArrowProgram$1 as E, FRAGMENT_SHADER_SOURCE as F, NodeCircleProgram as N, Program as P, _objectSpread2 as _, _defineProperty as a, drawDiscNodeLabel as b, drawDiscNodeHover as c, drawStraightEdgeLabel as d, EdgeRectangleProgram as e, NodeProgram as f, EdgeProgram as g, createEdgeCompoundProgram as h, createEdgeArrowHeadProgram as i, createNodeCompoundProgram as j, AbstractEdgeProgram as k, AbstractProgram as l, EdgeArrowHeadProgram$1 as m, EdgeClampedProgram$1 as n, createEdgeClampedProgram as o, DEFAULT_EDGE_CLAMPED_PROGRAM_OPTIONS as p, createEdgeArrowProgram as q, getAttributeItemsCount as r, getAttributesItemsCount as s, loadVertexShader as t, loadFragmentShader as u, loadProgram as v, killProgram as w, numberToGLSLFloat as x };
|