pantrybase 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +12 -0
- package/.claude-plugin/plugin.json +21 -0
- package/LICENSE +21 -0
- package/README.md +153 -2
- package/bin/_resolve.sh +38 -0
- package/bin/pantrybase +20 -0
- package/bin/pb-server +13 -0
- package/dist/chunk-2EMC6TJB.js +3341 -0
- package/dist/cli.js +441 -0
- package/dist/server.js +897 -0
- package/dist/web/assets/graph-Mpnwdw0-.js +3225 -0
- package/dist/web/assets/index-BQVf10Ok.js +1 -0
- package/dist/web/assets/index-PLKhwbDz.css +1 -0
- package/dist/web/index.html +14 -0
- package/package.json +85 -4
- package/providers/generic/guide.md +13 -0
- package/providers/generic/profile.yaml +16 -0
- package/providers/ucook/guide.md +62 -0
- package/providers/ucook/profile.yaml +60 -0
- package/seed/ingredients.yaml +194 -0
- package/seed/vocabulary.yaml +277 -0
- package/skills/cook/SKILL.md +28 -0
- package/skills/ingest/SKILL.md +40 -0
|
@@ -0,0 +1,3225 @@
|
|
|
1
|
+
import{a as e,c as t,d as n,i as r,l as i,n as a,o,r as s,s as c,t as l,u}from"./index-BQVf10Ok.js";var d=Object.create,f=Object.defineProperty,p=Object.getOwnPropertyDescriptor,m=Object.getOwnPropertyNames,h=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty,_=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t,t.exports),e=null),t.exports),v=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=m(t),a=0,o=i.length,s;a<o;a++)s=i[a],!g.call(e,s)&&s!==n&&f(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=p(t,s))||r.enumerable});return e},y=(e,t,n)=>(n=e==null?{}:d(h(e)),v(t||!e||!e.__esModule||!g.call(e,`default`)?f(n,`default`,{value:e,enumerable:!0}):n,e)),b=_(((e,t)=>{var n=typeof Reflect==`object`?Reflect:null,r=n&&typeof n.apply==`function`?n.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)},i=n&&typeof n.ownKeys==`function`?n.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};function a(e){console&&console.warn&&console.warn(e)}var o=Number.isNaN||function(e){return e!==e};function s(){s.init.call(this)}t.exports=s,t.exports.once=y,s.EventEmitter=s,s.prototype._events=void 0,s.prototype._eventsCount=0,s.prototype._maxListeners=void 0;var c=10;function l(e){if(typeof e!=`function`)throw TypeError(`The "listener" argument must be of type Function. Received type `+typeof e)}Object.defineProperty(s,"defaultMaxListeners",{enumerable:!0,get:function(){return c},set:function(e){if(typeof e!=`number`||e<0||o(e))throw RangeError(`The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received `+e+`.`);c=e}}),s.init=function(){(this._events===void 0||this._events===Object.getPrototypeOf(this)._events)&&(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},s.prototype.setMaxListeners=function(e){if(typeof e!=`number`||e<0||o(e))throw RangeError(`The value of "n" is out of range. It must be a non-negative number. Received `+e+`.`);return this._maxListeners=e,this};function u(e){return e._maxListeners===void 0?s.defaultMaxListeners:e._maxListeners}s.prototype.getMaxListeners=function(){return u(this)},s.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var i=e===`error`,a=this._events;if(a!==void 0)i&&=a.error===void 0;else if(!i)return!1;if(i){var o;if(t.length>0&&(o=t[0]),o instanceof Error)throw o;var s=Error(`Unhandled error.`+(o?` (`+o.message+`)`:``));throw s.context=o,s}var c=a[e];if(c===void 0)return!1;if(typeof c==`function`)r(c,this,t);else for(var l=c.length,u=g(c,l),n=0;n<l;++n)r(u[n],this,t);return!0};function d(e,t,n,r){var i,o,s;if(l(n),o=e._events,o===void 0?(o=e._events=Object.create(null),e._eventsCount=0):(o.newListener!==void 0&&(e.emit(`newListener`,t,n.listener?n.listener:n),o=e._events),s=o[t]),s===void 0)s=o[t]=n,++e._eventsCount;else if(typeof s==`function`?s=o[t]=r?[n,s]:[s,n]:r?s.unshift(n):s.push(n),i=u(e),i>0&&s.length>i&&!s.warned){s.warned=!0;var c=Error(`Possible EventEmitter memory leak detected. `+s.length+` `+String(t)+` listeners added. Use emitter.setMaxListeners() to increase limit`);c.name=`MaxListenersExceededWarning`,c.emitter=e,c.type=t,c.count=s.length,a(c)}return e}s.prototype.addListener=function(e,t){return d(this,e,t,!1)},s.prototype.on=s.prototype.addListener,s.prototype.prependListener=function(e,t){return d(this,e,t,!0)};function f(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,arguments.length===0?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function p(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},i=f.bind(r);return i.listener=n,r.wrapFn=i,i}s.prototype.once=function(e,t){return l(t),this.on(e,p(this,e,t)),this},s.prototype.prependOnceListener=function(e,t){return l(t),this.prependListener(e,p(this,e,t)),this},s.prototype.removeListener=function(e,t){var n,r,i,a,o;if(l(t),r=this._events,r===void 0||(n=r[e],n===void 0))return this;if(n===t||n.listener===t)--this._eventsCount===0?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit(`removeListener`,e,n.listener||t));else if(typeof n!=`function`){for(i=-1,a=n.length-1;a>=0;a--)if(n[a]===t||n[a].listener===t){o=n[a].listener,i=a;break}if(i<0)return this;i===0?n.shift():_(n,i),n.length===1&&(r[e]=n[0]),r.removeListener!==void 0&&this.emit(`removeListener`,e,o||t)}return this},s.prototype.off=s.prototype.removeListener,s.prototype.removeAllListeners=function(e){var t,n=this._events,r;if(n===void 0)return this;if(n.removeListener===void 0)return arguments.length===0?(this._events=Object.create(null),this._eventsCount=0):n[e]!==void 0&&(--this._eventsCount===0?this._events=Object.create(null):delete n[e]),this;if(arguments.length===0){var i=Object.keys(n),a;for(r=0;r<i.length;++r)a=i[r],a!==`removeListener`&&this.removeAllListeners(a);return this.removeAllListeners(`removeListener`),this._events=Object.create(null),this._eventsCount=0,this}if(t=n[e],typeof t==`function`)this.removeListener(e,t);else if(t!==void 0)for(r=t.length-1;r>=0;r--)this.removeListener(e,t[r]);return this};function m(e,t,n){var r=e._events;if(r===void 0)return[];var i=r[t];return i===void 0?[]:typeof i==`function`?n?[i.listener||i]:[i]:n?v(i):g(i,i.length)}s.prototype.listeners=function(e){return m(this,e,!0)},s.prototype.rawListeners=function(e){return m(this,e,!1)},s.listenerCount=function(e,t){return typeof e.listenerCount==`function`?e.listenerCount(t):h.call(e,t)},s.prototype.listenerCount=h;function h(e){var t=this._events;if(t!==void 0){var n=t[e];if(typeof n==`function`)return 1;if(n!==void 0)return n.length}return 0}s.prototype.eventNames=function(){return this._eventsCount>0?i(this._events):[]};function g(e,t){for(var n=Array(t),r=0;r<t;++r)n[r]=e[r];return n}function _(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}function v(e){for(var t=Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}function y(e,t){return new Promise(function(n,r){function i(n){e.removeListener(t,a),r(n)}function a(){typeof e.removeListener==`function`&&e.removeListener(`error`,i),n([].slice.call(arguments))}x(e,t,a,{once:!0}),t!==`error`&&b(e,i,{once:!0})})}function b(e,t,n){typeof e.on==`function`&&x(e,`error`,t,n)}function x(e,t,n,r){if(typeof e.on==`function`)r.once?e.once(t,n):e.on(t,n);else if(typeof e.addEventListener==`function`)e.addEventListener(t,function i(a){r.once&&e.removeEventListener(t,i),n(a)});else throw TypeError(`The "emitter" argument must be of type EventEmitter. Received type `+typeof e)}}))();function x(){let e=arguments[0];for(let t=1,n=arguments.length;t<n;t++)if(arguments[t])for(let n in arguments[t])e[n]=arguments[t][n];return e}var S=x;typeof Object.assign==`function`&&(S=Object.assign);function C(e,t,n,r){let i=e._nodes.get(t),a=null;return i&&(a=r===`mixed`?i.out&&i.out[n]||i.undirected&&i.undirected[n]:r===`directed`?i.out&&i.out[n]:i.undirected&&i.undirected[n]),a}function w(e){return typeof e==`object`&&!!e}function T(e){let t;for(t in e)return!1;return!0}function E(e,t,n){Object.defineProperty(e,t,{enumerable:!1,configurable:!1,writable:!0,value:n})}function D(e,t,n){let r={enumerable:!0,configurable:!0};typeof n==`function`?r.get=n:(r.value=n,r.writable=!1),Object.defineProperty(e,t,r)}function O(e){return!(!w(e)||e.attributes&&!Array.isArray(e.attributes))}function k(){let e=Math.floor(Math.random()*256)&255;return()=>e++}function A(){let e=arguments,t=null,n=-1;return{[Symbol.iterator](){return this},next(){let r=null;do{if(t===null){if(n++,n>=e.length)return{done:!0};t=e[n][Symbol.iterator]()}if(r=t.next(),r.done)t=null;else break}while(1);return r}}}function j(){return{[Symbol.iterator](){return this},next(){return{done:!0}}}}var M=class extends Error{constructor(e){super(),this.name=`GraphError`,this.message=e}},N=class e extends M{constructor(t){super(t),this.name=`InvalidArgumentsGraphError`,typeof Error.captureStackTrace==`function`&&Error.captureStackTrace(this,e.prototype.constructor)}},P=class e extends M{constructor(t){super(t),this.name=`NotFoundGraphError`,typeof Error.captureStackTrace==`function`&&Error.captureStackTrace(this,e.prototype.constructor)}},F=class e extends M{constructor(t){super(t),this.name=`UsageGraphError`,typeof Error.captureStackTrace==`function`&&Error.captureStackTrace(this,e.prototype.constructor)}};function I(e,t){this.key=e,this.attributes=t,this.clear()}I.prototype.clear=function(){this.inDegree=0,this.outDegree=0,this.undirectedDegree=0,this.undirectedLoops=0,this.directedLoops=0,this.in={},this.out={},this.undirected={}};function L(e,t){this.key=e,this.attributes=t,this.clear()}L.prototype.clear=function(){this.inDegree=0,this.outDegree=0,this.directedLoops=0,this.in={},this.out={}};function R(e,t){this.key=e,this.attributes=t,this.clear()}R.prototype.clear=function(){this.undirectedDegree=0,this.undirectedLoops=0,this.undirected={}};function z(e,t,n,r,i){this.key=t,this.attributes=i,this.undirected=e,this.source=n,this.target=r}z.prototype.attach=function(){let e=`out`,t=`in`;this.undirected&&(e=t=`undirected`);let n=this.source.key,r=this.target.key;this.source[e][r]=this,!(this.undirected&&n===r)&&(this.target[t][n]=this)},z.prototype.attachMulti=function(){let e=`out`,t=`in`,n=this.source.key,r=this.target.key;this.undirected&&(e=t=`undirected`);let i=this.source[e],a=i[r];a===void 0?(i[r]=this,this.undirected&&n===r||(this.target[t][n]=this)):(a.previous=this,this.next=a,i[r]=this,this.target[t][n]=this)},z.prototype.detach=function(){let e=this.source.key,t=this.target.key,n=`out`,r=`in`;this.undirected&&(n=r=`undirected`),delete this.source[n][t],delete this.target[r][e]},z.prototype.detachMulti=function(){let e=this.source.key,t=this.target.key,n=`out`,r=`in`;this.undirected&&(n=r=`undirected`),this.previous===void 0?this.next===void 0?(delete this.source[n][t],delete this.target[r][e]):(this.next.previous=void 0,this.source[n][t]=this.next,this.target[r][e]=this.next):(this.previous.next=this.next,this.next!==void 0&&(this.next.previous=this.previous))};var ee=0,te=1,ne=2,re=3;function ie(e,t,n,r,i,a,o){let s,c,l,u;if(r=``+r,n===ee){if(s=e._nodes.get(r),!s)throw new P(`Graph.${t}: could not find the "${r}" node in the graph.`);l=i,u=a}else if(n===re){if(i=``+i,c=e._edges.get(i),!c)throw new P(`Graph.${t}: could not find the "${i}" edge in the graph.`);let n=c.source.key,d=c.target.key;if(r===n)s=c.target;else if(r===d)s=c.source;else throw new P(`Graph.${t}: the "${r}" node is not attached to the "${i}" edge (${n}, ${d}).`);l=a,u=o}else{if(c=e._edges.get(r),!c)throw new P(`Graph.${t}: could not find the "${r}" edge in the graph.`);s=n===te?c.source:c.target,l=i,u=a}return[s,l,u]}function ae(e,t,n){e.prototype[t]=function(e,r,i){let[a,o]=ie(this,t,n,e,r,i);return a.attributes[o]}}function oe(e,t,n){e.prototype[t]=function(e,r){let[i]=ie(this,t,n,e,r);return i.attributes}}function se(e,t,n){e.prototype[t]=function(e,r,i){let[a,o]=ie(this,t,n,e,r,i);return a.attributes.hasOwnProperty(o)}}function ce(e,t,n){e.prototype[t]=function(e,r,i,a){let[o,s,c]=ie(this,t,n,e,r,i,a);return o.attributes[s]=c,this.emit(`nodeAttributesUpdated`,{key:o.key,type:`set`,attributes:o.attributes,name:s}),this}}function le(e,t,n){e.prototype[t]=function(e,r,i,a){let[o,s,c]=ie(this,t,n,e,r,i,a);if(typeof c!=`function`)throw new N(`Graph.${t}: updater should be a function.`);let l=o.attributes;return l[s]=c(l[s]),this.emit(`nodeAttributesUpdated`,{key:o.key,type:`set`,attributes:o.attributes,name:s}),this}}function ue(e,t,n){e.prototype[t]=function(e,r,i){let[a,o]=ie(this,t,n,e,r,i);return delete a.attributes[o],this.emit(`nodeAttributesUpdated`,{key:a.key,type:`remove`,attributes:a.attributes,name:o}),this}}function de(e,t,n){e.prototype[t]=function(e,r,i){let[a,o]=ie(this,t,n,e,r,i);if(!w(o))throw new N(`Graph.${t}: provided attributes are not a plain object.`);return a.attributes=o,this.emit(`nodeAttributesUpdated`,{key:a.key,type:`replace`,attributes:a.attributes}),this}}function fe(e,t,n){e.prototype[t]=function(e,r,i){let[a,o]=ie(this,t,n,e,r,i);if(!w(o))throw new N(`Graph.${t}: provided attributes are not a plain object.`);return S(a.attributes,o),this.emit(`nodeAttributesUpdated`,{key:a.key,type:`merge`,attributes:a.attributes,data:o}),this}}function pe(e,t,n){e.prototype[t]=function(e,r,i){let[a,o]=ie(this,t,n,e,r,i);if(typeof o!=`function`)throw new N(`Graph.${t}: provided updater is not a function.`);return a.attributes=o(a.attributes),this.emit(`nodeAttributesUpdated`,{key:a.key,type:`update`,attributes:a.attributes}),this}}var me=[{name:e=>`get${e}Attribute`,attacher:ae},{name:e=>`get${e}Attributes`,attacher:oe},{name:e=>`has${e}Attribute`,attacher:se},{name:e=>`set${e}Attribute`,attacher:ce},{name:e=>`update${e}Attribute`,attacher:le},{name:e=>`remove${e}Attribute`,attacher:ue},{name:e=>`replace${e}Attributes`,attacher:de},{name:e=>`merge${e}Attributes`,attacher:fe},{name:e=>`update${e}Attributes`,attacher:pe}];function he(e){me.forEach(function({name:t,attacher:n}){n(e,t(`Node`),ee),n(e,t(`Source`),te),n(e,t(`Target`),ne),n(e,t(`Opposite`),re)})}function ge(e,t,n){e.prototype[t]=function(e,r){let i;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let a=``+e,o=``+r;if(r=arguments[2],i=C(this,a,o,n),!i)throw new P(`Graph.${t}: could not find an edge for the given path ("${a}" - "${o}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,i=this._edges.get(e),!i)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}return i.attributes[r]}}function _e(e,t,n){e.prototype[t]=function(e){let r;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>1){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let i=``+e,a=``+arguments[1];if(r=C(this,i,a,n),!r)throw new P(`Graph.${t}: could not find an edge for the given path ("${i}" - "${a}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,r=this._edges.get(e),!r)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}return r.attributes}}function ve(e,t,n){e.prototype[t]=function(e,r){let i;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let a=``+e,o=``+r;if(r=arguments[2],i=C(this,a,o,n),!i)throw new P(`Graph.${t}: could not find an edge for the given path ("${a}" - "${o}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,i=this._edges.get(e),!i)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}return i.attributes.hasOwnProperty(r)}}function ye(e,t,n){e.prototype[t]=function(e,r,i){let a;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>3){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let o=``+e,s=``+r;if(r=arguments[2],i=arguments[3],a=C(this,o,s,n),!a)throw new P(`Graph.${t}: could not find an edge for the given path ("${o}" - "${s}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,a=this._edges.get(e),!a)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}return a.attributes[r]=i,this.emit(`edgeAttributesUpdated`,{key:a.key,type:`set`,attributes:a.attributes,name:r}),this}}function be(e,t,n){e.prototype[t]=function(e,r,i){let a;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>3){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let o=``+e,s=``+r;if(r=arguments[2],i=arguments[3],a=C(this,o,s,n),!a)throw new P(`Graph.${t}: could not find an edge for the given path ("${o}" - "${s}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,a=this._edges.get(e),!a)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}if(typeof i!=`function`)throw new N(`Graph.${t}: updater should be a function.`);return a.attributes[r]=i(a.attributes[r]),this.emit(`edgeAttributesUpdated`,{key:a.key,type:`set`,attributes:a.attributes,name:r}),this}}function xe(e,t,n){e.prototype[t]=function(e,r){let i;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let a=``+e,o=``+r;if(r=arguments[2],i=C(this,a,o,n),!i)throw new P(`Graph.${t}: could not find an edge for the given path ("${a}" - "${o}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,i=this._edges.get(e),!i)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}return delete i.attributes[r],this.emit(`edgeAttributesUpdated`,{key:i.key,type:`remove`,attributes:i.attributes,name:r}),this}}function Se(e,t,n){e.prototype[t]=function(e,r){let i;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let a=``+e,o=``+r;if(r=arguments[2],i=C(this,a,o,n),!i)throw new P(`Graph.${t}: could not find an edge for the given path ("${a}" - "${o}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,i=this._edges.get(e),!i)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}if(!w(r))throw new N(`Graph.${t}: provided attributes are not a plain object.`);return i.attributes=r,this.emit(`edgeAttributesUpdated`,{key:i.key,type:`replace`,attributes:i.attributes}),this}}function Ce(e,t,n){e.prototype[t]=function(e,r){let i;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let a=``+e,o=``+r;if(r=arguments[2],i=C(this,a,o,n),!i)throw new P(`Graph.${t}: could not find an edge for the given path ("${a}" - "${o}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,i=this._edges.get(e),!i)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}if(!w(r))throw new N(`Graph.${t}: provided attributes are not a plain object.`);return S(i.attributes,r),this.emit(`edgeAttributesUpdated`,{key:i.key,type:`merge`,attributes:i.attributes,data:r}),this}}function we(e,t,n){e.prototype[t]=function(e,r){let i;if(this.type!==`mixed`&&n!==`mixed`&&n!==this.type)throw new F(`Graph.${t}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new F(`Graph.${t}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let a=``+e,o=``+r;if(r=arguments[2],i=C(this,a,o,n),!i)throw new P(`Graph.${t}: could not find an edge for the given path ("${a}" - "${o}").`)}else{if(n!==`mixed`)throw new F(`Graph.${t}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(e=``+e,i=this._edges.get(e),!i)throw new P(`Graph.${t}: could not find the "${e}" edge in the graph.`)}if(typeof r!=`function`)throw new N(`Graph.${t}: provided updater is not a function.`);return i.attributes=r(i.attributes),this.emit(`edgeAttributesUpdated`,{key:i.key,type:`update`,attributes:i.attributes}),this}}var Te=[{name:e=>`get${e}Attribute`,attacher:ge},{name:e=>`get${e}Attributes`,attacher:_e},{name:e=>`has${e}Attribute`,attacher:ve},{name:e=>`set${e}Attribute`,attacher:ye},{name:e=>`update${e}Attribute`,attacher:be},{name:e=>`remove${e}Attribute`,attacher:xe},{name:e=>`replace${e}Attributes`,attacher:Se},{name:e=>`merge${e}Attributes`,attacher:Ce},{name:e=>`update${e}Attributes`,attacher:we}];function Ee(e){Te.forEach(function({name:t,attacher:n}){n(e,t(`Edge`),`mixed`),n(e,t(`DirectedEdge`),`directed`),n(e,t(`UndirectedEdge`),`undirected`)})}var De=[{name:`edges`,type:`mixed`},{name:`inEdges`,type:`directed`,direction:`in`},{name:`outEdges`,type:`directed`,direction:`out`},{name:`inboundEdges`,type:`mixed`,direction:`in`},{name:`outboundEdges`,type:`mixed`,direction:`out`},{name:`directedEdges`,type:`directed`},{name:`undirectedEdges`,type:`undirected`}];function Oe(e,t,n,r){let i=!1;for(let a in t){if(a===r)continue;let o=t[a];if(i=n(o.key,o.attributes,o.source.key,o.target.key,o.source.attributes,o.target.attributes,o.undirected),e&&i)return o.key}}function ke(e,t,n,r){let i,a,o,s=!1;for(let c in t)if(c!==r){i=t[c];do{if(a=i.source,o=i.target,s=n(i.key,i.attributes,a.key,o.key,a.attributes,o.attributes,i.undirected),e&&s)return i.key;i=i.next}while(i!==void 0)}}function Ae(e,t){let n=Object.keys(e),r=n.length,i,a=0;return{[Symbol.iterator](){return this},next(){do if(i)i=i.next;else{if(a>=r)return{done:!0};let o=n[a++];if(o===t){i=void 0;continue}i=e[o]}while(!i);return{done:!1,value:{edge:i.key,attributes:i.attributes,source:i.source.key,target:i.target.key,sourceAttributes:i.source.attributes,targetAttributes:i.target.attributes,undirected:i.undirected}}}}}function je(e,t,n,r){let i=t[n];if(!i)return;let a=i.source,o=i.target;if(r(i.key,i.attributes,a.key,o.key,a.attributes,o.attributes,i.undirected)&&e)return i.key}function Me(e,t,n,r){let i=t[n];if(!i)return;let a=!1;do{if(a=r(i.key,i.attributes,i.source.key,i.target.key,i.source.attributes,i.target.attributes,i.undirected),e&&a)return i.key;i=i.next}while(i!==void 0)}function Ne(e,t){let n=e[t];if(n.next!==void 0)return{[Symbol.iterator](){return this},next(){if(!n)return{done:!0};let e={edge:n.key,attributes:n.attributes,source:n.source.key,target:n.target.key,sourceAttributes:n.source.attributes,targetAttributes:n.target.attributes,undirected:n.undirected};return n=n.next,{done:!1,value:e}}};let r=!1;return{[Symbol.iterator](){return this},next(){return r===!0?{done:!0}:(r=!0,{done:!1,value:{edge:n.key,attributes:n.attributes,source:n.source.key,target:n.target.key,sourceAttributes:n.source.attributes,targetAttributes:n.target.attributes,undirected:n.undirected}})}}}function Pe(e,t){if(e.size===0)return[];if(t===`mixed`||t===e.type)return Array.from(e._edges.keys());let n=t===`undirected`?e.undirectedSize:e.directedSize,r=Array(n),i=t===`undirected`,a=e._edges.values(),o=0,s,c;for(;s=a.next(),s.done!==!0;)c=s.value,c.undirected===i&&(r[o++]=c.key);return r}function Fe(e,t,n,r){if(t.size===0)return;let i=n!==`mixed`&&n!==t.type,a=n===`undirected`,o,s,c=!1,l=t._edges.values();for(;o=l.next(),o.done!==!0;){if(s=o.value,i&&s.undirected!==a)continue;let{key:t,attributes:n,source:l,target:u}=s;if(c=r(t,n,l.key,u.key,l.attributes,u.attributes,s.undirected),e&&c)return t}}function Ie(e,t){if(e.size===0)return j();let n=t!==`mixed`&&t!==e.type,r=t===`undirected`,i=e._edges.values();return{[Symbol.iterator](){return this},next(){let e,t;for(;;){if(e=i.next(),e.done)return e;if(t=e.value,!(n&&t.undirected!==r))break}return{value:{edge:t.key,attributes:t.attributes,source:t.source.key,target:t.target.key,sourceAttributes:t.source.attributes,targetAttributes:t.target.attributes,undirected:t.undirected},done:!1}}}}function Le(e,t,n,r,i,a){let o=t?ke:Oe,s;if(n!==`undirected`&&(r!==`out`&&(s=o(e,i.in,a),e&&s)||r!==`in`&&(s=o(e,i.out,a,r?void 0:i.key),e&&s))||n!==`directed`&&(s=o(e,i.undirected,a),e&&s))return s}function Re(e,t,n,r){let i=[];return Le(!1,e,t,n,r,function(e){i.push(e)}),i}function ze(e,t,n){let r=j();return e!==`undirected`&&(t!==`out`&&n.in!==void 0&&(r=A(r,Ae(n.in))),t!==`in`&&n.out!==void 0&&(r=A(r,Ae(n.out,t?void 0:n.key)))),e!==`directed`&&n.undirected!==void 0&&(r=A(r,Ae(n.undirected))),r}function Be(e,t,n,r,i,a,o){let s=n?Me:je,c;if(t!==`undirected`&&(i.in!==void 0&&r!==`out`&&(c=s(e,i.in,a,o),e&&c)||i.out!==void 0&&r!==`in`&&(r||i.key!==a)&&(c=s(e,i.out,a,o),e&&c))||t!==`directed`&&i.undirected!==void 0&&(c=s(e,i.undirected,a,o),e&&c))return c}function Ve(e,t,n,r,i){let a=[];return Be(!1,e,t,n,r,i,function(e){a.push(e)}),a}function He(e,t,n,r){let i=j();return e!==`undirected`&&(n.in!==void 0&&t!==`out`&&r in n.in&&(i=A(i,Ne(n.in,r))),n.out!==void 0&&t!==`in`&&r in n.out&&(t||n.key!==r)&&(i=A(i,Ne(n.out,r)))),e!==`directed`&&n.undirected!==void 0&&r in n.undirected&&(i=A(i,Ne(n.undirected,r))),i}function Ue(e,t){let{name:n,type:r,direction:i}=t;e.prototype[n]=function(e,t){if(r!==`mixed`&&this.type!==`mixed`&&r!==this.type)return[];if(!arguments.length)return Pe(this,r);if(arguments.length===1){e=``+e;let t=this._nodes.get(e);if(t===void 0)throw new P(`Graph.${n}: could not find the "${e}" node in the graph.`);return Re(this.multi,r===`mixed`?this.type:r,i,t)}if(arguments.length===2){e=``+e,t=``+t;let a=this._nodes.get(e);if(!a)throw new P(`Graph.${n}: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new P(`Graph.${n}: could not find the "${t}" target node in the graph.`);return Ve(r,this.multi,i,a,t)}throw new N(`Graph.${n}: too many arguments (expecting 0, 1 or 2 and got ${arguments.length}).`)}}function We(e,t){let{name:n,type:r,direction:i}=t,a=`forEach`+n[0].toUpperCase()+n.slice(1,-1);e.prototype[a]=function(e,t,n){if(r===`mixed`||this.type===`mixed`||r===this.type){if(arguments.length===1)return n=e,Fe(!1,this,r,n);if(arguments.length===2){e=``+e,n=t;let o=this._nodes.get(e);if(o===void 0)throw new P(`Graph.${a}: could not find the "${e}" node in the graph.`);return Le(!1,this.multi,r===`mixed`?this.type:r,i,o,n)}if(arguments.length===3){e=``+e,t=``+t;let o=this._nodes.get(e);if(!o)throw new P(`Graph.${a}: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new P(`Graph.${a}: could not find the "${t}" target node in the graph.`);return Be(!1,r,this.multi,i,o,t,n)}throw new N(`Graph.${a}: too many arguments (expecting 1, 2 or 3 and got ${arguments.length}).`)}};let o=`map`+n[0].toUpperCase()+n.slice(1);e.prototype[o]=function(){let e=Array.prototype.slice.call(arguments),t=e.pop(),n;if(e.length===0){let i=0;r!==`directed`&&(i+=this.undirectedSize),r!==`undirected`&&(i+=this.directedSize),n=Array(i);let a=0;e.push((e,r,i,o,s,c,l)=>{n[a++]=t(e,r,i,o,s,c,l)})}else n=[],e.push((e,r,i,a,o,s,c)=>{n.push(t(e,r,i,a,o,s,c))});return this[a].apply(this,e),n};let s=`filter`+n[0].toUpperCase()+n.slice(1);e.prototype[s]=function(){let e=Array.prototype.slice.call(arguments),t=e.pop(),n=[];return e.push((e,r,i,a,o,s,c)=>{t(e,r,i,a,o,s,c)&&n.push(e)}),this[a].apply(this,e),n};let c=`reduce`+n[0].toUpperCase()+n.slice(1);e.prototype[c]=function(){let e=Array.prototype.slice.call(arguments);if(e.length<2||e.length>4)throw new N(`Graph.${c}: invalid number of arguments (expecting 2, 3 or 4 and got ${e.length}).`);if(typeof e[e.length-1]==`function`&&typeof e[e.length-2]!=`function`)throw new N(`Graph.${c}: missing initial value. You must provide it because the callback takes more than one argument and we cannot infer the initial value from the first iteration, as you could with a simple array.`);let t,n;e.length===2?(t=e[0],n=e[1],e=[]):e.length===3?(t=e[1],n=e[2],e=[e[0]]):e.length===4&&(t=e[2],n=e[3],e=[e[0],e[1]]);let r=n;return e.push((e,n,i,a,o,s,c)=>{r=t(r,e,n,i,a,o,s,c)}),this[a].apply(this,e),r}}function Ge(e,t){let{name:n,type:r,direction:i}=t,a=`find`+n[0].toUpperCase()+n.slice(1,-1);e.prototype[a]=function(e,t,n){if(r!==`mixed`&&this.type!==`mixed`&&r!==this.type)return!1;if(arguments.length===1)return n=e,Fe(!0,this,r,n);if(arguments.length===2){e=``+e,n=t;let o=this._nodes.get(e);if(o===void 0)throw new P(`Graph.${a}: could not find the "${e}" node in the graph.`);return Le(!0,this.multi,r===`mixed`?this.type:r,i,o,n)}if(arguments.length===3){e=``+e,t=``+t;let o=this._nodes.get(e);if(!o)throw new P(`Graph.${a}: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new P(`Graph.${a}: could not find the "${t}" target node in the graph.`);return Be(!0,r,this.multi,i,o,t,n)}throw new N(`Graph.${a}: too many arguments (expecting 1, 2 or 3 and got ${arguments.length}).`)};let o=`some`+n[0].toUpperCase()+n.slice(1,-1);e.prototype[o]=function(){let e=Array.prototype.slice.call(arguments),t=e.pop();return e.push((e,n,r,i,a,o,s)=>t(e,n,r,i,a,o,s)),!!this[a].apply(this,e)};let s=`every`+n[0].toUpperCase()+n.slice(1,-1);e.prototype[s]=function(){let e=Array.prototype.slice.call(arguments),t=e.pop();return e.push((e,n,r,i,a,o,s)=>!t(e,n,r,i,a,o,s)),!this[a].apply(this,e)}}function Ke(e,t){let{name:n,type:r,direction:i}=t,a=n.slice(0,-1)+`Entries`;e.prototype[a]=function(e,t){if(r!==`mixed`&&this.type!==`mixed`&&r!==this.type)return j();if(!arguments.length)return Ie(this,r);if(arguments.length===1){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.${a}: could not find the "${e}" node in the graph.`);return ze(r,i,t)}if(arguments.length===2){e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.${a}: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new P(`Graph.${a}: could not find the "${t}" target node in the graph.`);return He(r,i,n,t)}throw new N(`Graph.${a}: too many arguments (expecting 0, 1 or 2 and got ${arguments.length}).`)}}function qe(e){De.forEach(t=>{Ue(e,t),We(e,t),Ge(e,t),Ke(e,t)})}var Je=[{name:`neighbors`,type:`mixed`},{name:`inNeighbors`,type:`directed`,direction:`in`},{name:`outNeighbors`,type:`directed`,direction:`out`},{name:`inboundNeighbors`,type:`mixed`,direction:`in`},{name:`outboundNeighbors`,type:`mixed`,direction:`out`},{name:`directedNeighbors`,type:`directed`},{name:`undirectedNeighbors`,type:`undirected`}];function Ye(){this.A=null,this.B=null}Ye.prototype.wrap=function(e){this.A===null?this.A=e:this.B===null&&(this.B=e)},Ye.prototype.has=function(e){return this.A!==null&&e in this.A||this.B!==null&&e in this.B};function Xe(e,t,n,r,i){for(let a in r){let o=r[a],s=o.source,c=o.target,l=s===n?c:s;if(t&&t.has(l.key))continue;let u=i(l.key,l.attributes);if(e&&u)return l.key}}function Ze(e,t,n,r,i){if(t!==`mixed`){if(t===`undirected`)return Xe(e,null,r,r.undirected,i);if(typeof n==`string`)return Xe(e,null,r,r[n],i)}let a=new Ye,o;if(t!==`undirected`){if(n!==`out`){if(o=Xe(e,null,r,r.in,i),e&&o)return o;a.wrap(r.in)}if(n!==`in`){if(o=Xe(e,a,r,r.out,i),e&&o)return o;a.wrap(r.out)}}if(t!==`directed`&&(o=Xe(e,a,r,r.undirected,i),e&&o))return o}function Qe(e,t,n){if(e!==`mixed`){if(e===`undirected`)return Object.keys(n.undirected);if(typeof t==`string`)return Object.keys(n[t])}let r=[];return Ze(!1,e,t,n,function(e){r.push(e)}),r}function $e(e,t,n){let r=Object.keys(n),i=r.length,a=0;return{[Symbol.iterator](){return this},next(){let o=null;do{if(a>=i)return e&&e.wrap(n),{done:!0};let s=n[r[a++]],c=s.source,l=s.target;o=c===t?l:c,e&&e.has(o.key)&&(o=null)}while(o===null);return{done:!1,value:{neighbor:o.key,attributes:o.attributes}}}}}function et(e,t,n){if(e!==`mixed`){if(e===`undirected`)return $e(null,n,n.undirected);if(typeof t==`string`)return $e(null,n,n[t])}let r=j(),i=new Ye;return e!==`undirected`&&(t!==`out`&&(r=A(r,$e(i,n,n.in))),t!==`in`&&(r=A(r,$e(i,n,n.out)))),e!==`directed`&&(r=A(r,$e(i,n,n.undirected))),r}function tt(e,t){let{name:n,type:r,direction:i}=t;e.prototype[n]=function(e){if(r!==`mixed`&&this.type!==`mixed`&&r!==this.type)return[];e=``+e;let t=this._nodes.get(e);if(t===void 0)throw new P(`Graph.${n}: could not find the "${e}" node in the graph.`);return Qe(r===`mixed`?this.type:r,i,t)}}function nt(e,t){let{name:n,type:r,direction:i}=t,a=`forEach`+n[0].toUpperCase()+n.slice(1,-1);e.prototype[a]=function(e,t){if(r!==`mixed`&&this.type!==`mixed`&&r!==this.type)return;e=``+e;let n=this._nodes.get(e);if(n===void 0)throw new P(`Graph.${a}: could not find the "${e}" node in the graph.`);Ze(!1,r===`mixed`?this.type:r,i,n,t)};let o=`map`+n[0].toUpperCase()+n.slice(1);e.prototype[o]=function(e,t){let n=[];return this[a](e,(e,r)=>{n.push(t(e,r))}),n};let s=`filter`+n[0].toUpperCase()+n.slice(1);e.prototype[s]=function(e,t){let n=[];return this[a](e,(e,r)=>{t(e,r)&&n.push(e)}),n};let c=`reduce`+n[0].toUpperCase()+n.slice(1);e.prototype[c]=function(e,t,n){if(arguments.length<3)throw new N(`Graph.${c}: missing initial value. You must provide it because the callback takes more than one argument and we cannot infer the initial value from the first iteration, as you could with a simple array.`);let r=n;return this[a](e,(e,n)=>{r=t(r,e,n)}),r}}function rt(e,t){let{name:n,type:r,direction:i}=t,a=n[0].toUpperCase()+n.slice(1,-1),o=`find`+a;e.prototype[o]=function(e,t){if(r!==`mixed`&&this.type!==`mixed`&&r!==this.type)return;e=``+e;let n=this._nodes.get(e);if(n===void 0)throw new P(`Graph.${o}: could not find the "${e}" node in the graph.`);return Ze(!0,r===`mixed`?this.type:r,i,n,t)};let s=`some`+a;e.prototype[s]=function(e,t){return!!this[o](e,t)};let c=`every`+a;e.prototype[c]=function(e,t){return!this[o](e,(e,n)=>!t(e,n))}}function it(e,t){let{name:n,type:r,direction:i}=t,a=n.slice(0,-1)+`Entries`;e.prototype[a]=function(e){if(r!==`mixed`&&this.type!==`mixed`&&r!==this.type)return j();e=``+e;let t=this._nodes.get(e);if(t===void 0)throw new P(`Graph.${a}: could not find the "${e}" node in the graph.`);return et(r===`mixed`?this.type:r,i,t)}}function at(e){Je.forEach(t=>{tt(e,t),nt(e,t),rt(e,t),it(e,t)})}function ot(e,t,n,r,i){let a=r._nodes.values(),o=r.type,s,c,l,u,d,f,p;for(;s=a.next(),s.done!==!0;){let r=!1;if(c=s.value,o!==`undirected`)for(l in u=c.out,u){d=u[l];do{if(f=d.target,r=!0,p=i(c.key,f.key,c.attributes,f.attributes,d.key,d.attributes,d.undirected),e&&p)return d;d=d.next}while(d)}if(o!==`directed`){for(l in u=c.undirected,u)if(!(t&&c.key>l)){d=u[l];do{if(f=d.target,f.key!==l&&(f=d.source),r=!0,p=i(c.key,f.key,c.attributes,f.attributes,d.key,d.attributes,d.undirected),e&&p)return d;d=d.next}while(d)}}if(n&&!r&&(p=i(c.key,null,c.attributes,null,null,null,null),e&&p))return null}}function st(e,t){let n={key:e};return T(t.attributes)||(n.attributes=S({},t.attributes)),n}function ct(e,t,n){let r={key:t,source:n.source.key,target:n.target.key};return T(n.attributes)||(r.attributes=S({},n.attributes)),e===`mixed`&&n.undirected&&(r.undirected=!0),r}function lt(e){if(!w(e))throw new N(`Graph.import: invalid serialized node. A serialized node should be a plain object with at least a "key" property.`);if(!(`key`in e))throw new N(`Graph.import: serialized node is missing its key.`);if(`attributes`in e&&(!w(e.attributes)||e.attributes===null))throw new N(`Graph.import: invalid attributes. Attributes should be a plain object, null or omitted.`)}function ut(e){if(!w(e))throw new N(`Graph.import: invalid serialized edge. A serialized edge should be a plain object with at least a "source" & "target" property.`);if(!(`source`in e))throw new N(`Graph.import: serialized edge is missing its source.`);if(!(`target`in e))throw new N(`Graph.import: serialized edge is missing its target.`);if(`attributes`in e&&(!w(e.attributes)||e.attributes===null))throw new N(`Graph.import: invalid attributes. Attributes should be a plain object, null or omitted.`);if(`undirected`in e&&typeof e.undirected!=`boolean`)throw new N(`Graph.import: invalid undirectedness information. Undirected should be boolean or omitted.`)}var dt=k(),ft=new Set([`directed`,`undirected`,`mixed`]),pt=new Set([`domain`,`_events`,`_eventsCount`,`_maxListeners`]),mt=[{name:e=>`${e}Edge`,generateKey:!0},{name:e=>`${e}DirectedEdge`,generateKey:!0,type:`directed`},{name:e=>`${e}UndirectedEdge`,generateKey:!0,type:`undirected`},{name:e=>`${e}EdgeWithKey`},{name:e=>`${e}DirectedEdgeWithKey`,type:`directed`},{name:e=>`${e}UndirectedEdgeWithKey`,type:`undirected`}],ht={allowSelfLoops:!0,multi:!1,type:`mixed`};function gt(e,t,n){if(n&&!w(n))throw new N(`Graph.addNode: invalid attributes. Expecting an object but got "${n}"`);if(t=``+t,n||={},e._nodes.has(t))throw new F(`Graph.addNode: the "${t}" node already exist in the graph.`);let r=new e.NodeDataClass(t,n);return e._nodes.set(t,r),e.emit(`nodeAdded`,{key:t,attributes:n}),r}function _t(e,t,n){let r=new e.NodeDataClass(t,n);return e._nodes.set(t,r),e.emit(`nodeAdded`,{key:t,attributes:n}),r}function vt(e,t,n,r,i,a,o,s){if(!r&&e.type===`undirected`)throw new F(`Graph.${t}: you cannot add a directed edge to an undirected graph. Use the #.addEdge or #.addUndirectedEdge instead.`);if(r&&e.type===`directed`)throw new F(`Graph.${t}: you cannot add an undirected edge to a directed graph. Use the #.addEdge or #.addDirectedEdge instead.`);if(s&&!w(s))throw new N(`Graph.${t}: invalid attributes. Expecting an object but got "${s}"`);if(a=``+a,o=``+o,s||={},!e.allowSelfLoops&&a===o)throw new F(`Graph.${t}: source & target are the same ("${a}"), thus creating a loop explicitly forbidden by this graph 'allowSelfLoops' option set to false.`);let c=e._nodes.get(a),l=e._nodes.get(o);if(!c)throw new P(`Graph.${t}: source node "${a}" not found.`);if(!l)throw new P(`Graph.${t}: target node "${o}" not found.`);let u={key:null,undirected:r,source:a,target:o,attributes:s};if(n)i=e._edgeKeyGenerator();else if(i=``+i,e._edges.has(i))throw new F(`Graph.${t}: the "${i}" edge already exists in the graph.`);if(!e.multi&&(r?c.undirected[o]!==void 0:c.out[o]!==void 0))throw new F(`Graph.${t}: an edge linking "${a}" to "${o}" already exists. If you really want to add multiple edges linking those nodes, you should create a multi graph by using the 'multi' option.`);let d=new z(r,i,c,l,s);e._edges.set(i,d);let f=a===o;return r?(c.undirectedDegree++,l.undirectedDegree++,f&&(c.undirectedLoops++,e._undirectedSelfLoopCount++)):(c.outDegree++,l.inDegree++,f&&(c.directedLoops++,e._directedSelfLoopCount++)),e.multi?d.attachMulti():d.attach(),r?e._undirectedSize++:e._directedSize++,u.key=i,e.emit(`edgeAdded`,u),i}function yt(e,t,n,r,i,a,o,s,c){if(!r&&e.type===`undirected`)throw new F(`Graph.${t}: you cannot merge/update a directed edge to an undirected graph. Use the #.mergeEdge/#.updateEdge or #.addUndirectedEdge instead.`);if(r&&e.type===`directed`)throw new F(`Graph.${t}: you cannot merge/update an undirected edge to a directed graph. Use the #.mergeEdge/#.updateEdge or #.addDirectedEdge instead.`);if(s){if(c){if(typeof s!=`function`)throw new N(`Graph.${t}: invalid updater function. Expecting a function but got "${s}"`)}else if(!w(s))throw new N(`Graph.${t}: invalid attributes. Expecting an object but got "${s}"`)}a=``+a,o=``+o;let l;if(c&&(l=s,s=void 0),!e.allowSelfLoops&&a===o)throw new F(`Graph.${t}: source & target are the same ("${a}"), thus creating a loop explicitly forbidden by this graph 'allowSelfLoops' option set to false.`);let u=e._nodes.get(a),d=e._nodes.get(o),f,p;if(!n&&(f=e._edges.get(i),f)){if((f.source.key!==a||f.target.key!==o)&&(!r||f.source.key!==o||f.target.key!==a))throw new F(`Graph.${t}: inconsistency detected when attempting to merge the "${i}" edge with "${a}" source & "${o}" target vs. ("${f.source.key}", "${f.target.key}").`);p=f}if(!p&&!e.multi&&u&&(p=r?u.undirected[o]:u.out[o]),p){let t=[p.key,!1,!1,!1];if(c?!l:!s)return t;if(c){let t=p.attributes;p.attributes=l(t),e.emit(`edgeAttributesUpdated`,{type:`replace`,key:p.key,attributes:p.attributes})}else S(p.attributes,s),e.emit(`edgeAttributesUpdated`,{type:`merge`,key:p.key,attributes:p.attributes,data:s});return t}s||={},c&&l&&(s=l(s));let m={key:null,undirected:r,source:a,target:o,attributes:s};if(n)i=e._edgeKeyGenerator();else if(i=``+i,e._edges.has(i))throw new F(`Graph.${t}: the "${i}" edge already exists in the graph.`);let h=!1,g=!1;u||(u=_t(e,a,{}),h=!0,a===o&&(d=u,g=!0)),d||(d=_t(e,o,{}),g=!0),f=new z(r,i,u,d,s),e._edges.set(i,f);let _=a===o;return r?(u.undirectedDegree++,d.undirectedDegree++,_&&(u.undirectedLoops++,e._undirectedSelfLoopCount++)):(u.outDegree++,d.inDegree++,_&&(u.directedLoops++,e._directedSelfLoopCount++)),e.multi?f.attachMulti():f.attach(),r?e._undirectedSize++:e._directedSize++,m.key=i,e.emit(`edgeAdded`,m),[i,!0,h,g]}function bt(e,t){e._edges.delete(t.key);let{source:n,target:r,attributes:i}=t,a=t.undirected,o=n===r;a?(n.undirectedDegree--,r.undirectedDegree--,o&&(n.undirectedLoops--,e._undirectedSelfLoopCount--)):(n.outDegree--,r.inDegree--,o&&(n.directedLoops--,e._directedSelfLoopCount--)),e.multi?t.detachMulti():t.detach(),a?e._undirectedSize--:e._directedSize--,e.emit(`edgeDropped`,{key:t.key,attributes:i,source:n.key,target:r.key,undirected:a})}var B=class e extends b.EventEmitter{constructor(e){if(super(),e=S({},ht,e),typeof e.multi!=`boolean`)throw new N(`Graph.constructor: invalid 'multi' option. Expecting a boolean but got "${e.multi}".`);if(!ft.has(e.type))throw new N(`Graph.constructor: invalid 'type' option. Should be one of "mixed", "directed" or "undirected" but got "${e.type}".`);if(typeof e.allowSelfLoops!=`boolean`)throw new N(`Graph.constructor: invalid 'allowSelfLoops' option. Expecting a boolean but got "${e.allowSelfLoops}".`);let t=e.type===`mixed`?I:e.type===`directed`?L:R;E(this,`NodeDataClass`,t);let n=`geid_`+dt()+`_`,r=0;E(this,`_attributes`,{}),E(this,`_nodes`,new Map),E(this,`_edges`,new Map),E(this,`_directedSize`,0),E(this,`_undirectedSize`,0),E(this,`_directedSelfLoopCount`,0),E(this,`_undirectedSelfLoopCount`,0),E(this,`_edgeKeyGenerator`,()=>{let e;do e=n+r++;while(this._edges.has(e));return e}),E(this,`_options`,e),pt.forEach(e=>E(this,e,this[e])),D(this,`order`,()=>this._nodes.size),D(this,`size`,()=>this._edges.size),D(this,`directedSize`,()=>this._directedSize),D(this,`undirectedSize`,()=>this._undirectedSize),D(this,`selfLoopCount`,()=>this._directedSelfLoopCount+this._undirectedSelfLoopCount),D(this,`directedSelfLoopCount`,()=>this._directedSelfLoopCount),D(this,`undirectedSelfLoopCount`,()=>this._undirectedSelfLoopCount),D(this,`multi`,this._options.multi),D(this,`type`,this._options.type),D(this,`allowSelfLoops`,this._options.allowSelfLoops),D(this,`implementation`,()=>`graphology`)}_resetInstanceCounters(){this._directedSize=0,this._undirectedSize=0,this._directedSelfLoopCount=0,this._undirectedSelfLoopCount=0}hasNode(e){return this._nodes.has(``+e)}hasDirectedEdge(e,t){if(this.type===`undirected`)return!1;if(arguments.length===1){let t=``+e,n=this._edges.get(t);return!!n&&!n.undirected}if(arguments.length===2){e=``+e,t=``+t;let n=this._nodes.get(e);return n?n.out.hasOwnProperty(t):!1}throw new N(`Graph.hasDirectedEdge: invalid arity (${arguments.length}, instead of 1 or 2). You can either ask for an edge id or for the existence of an edge between a source & a target.`)}hasUndirectedEdge(e,t){if(this.type===`directed`)return!1;if(arguments.length===1){let t=``+e,n=this._edges.get(t);return!!n&&n.undirected}if(arguments.length===2){e=``+e,t=``+t;let n=this._nodes.get(e);return n?n.undirected.hasOwnProperty(t):!1}throw new N(`Graph.hasDirectedEdge: invalid arity (${arguments.length}, instead of 1 or 2). You can either ask for an edge id or for the existence of an edge between a source & a target.`)}hasEdge(e,t){if(arguments.length===1){let t=``+e;return this._edges.has(t)}if(arguments.length===2){e=``+e,t=``+t;let n=this._nodes.get(e);return n?n.out!==void 0&&n.out.hasOwnProperty(t)||n.undirected!==void 0&&n.undirected.hasOwnProperty(t):!1}throw new N(`Graph.hasEdge: invalid arity (${arguments.length}, instead of 1 or 2). You can either ask for an edge id or for the existence of an edge between a source & a target.`)}directedEdge(e,t){if(this.type===`undirected`)return;if(e=``+e,t=``+t,this.multi)throw new F(`Graph.directedEdge: this method is irrelevant with multigraphs since there might be multiple edges between source & target. See #.directedEdges instead.`);let n=this._nodes.get(e);if(!n)throw new P(`Graph.directedEdge: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new P(`Graph.directedEdge: could not find the "${t}" target node in the graph.`);let r=n.out&&n.out[t]||void 0;if(r)return r.key}undirectedEdge(e,t){if(this.type===`directed`)return;if(e=``+e,t=``+t,this.multi)throw new F(`Graph.undirectedEdge: this method is irrelevant with multigraphs since there might be multiple edges between source & target. See #.undirectedEdges instead.`);let n=this._nodes.get(e);if(!n)throw new P(`Graph.undirectedEdge: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new P(`Graph.undirectedEdge: could not find the "${t}" target node in the graph.`);let r=n.undirected&&n.undirected[t]||void 0;if(r)return r.key}edge(e,t){if(this.multi)throw new F(`Graph.edge: this method is irrelevant with multigraphs since there might be multiple edges between source & target. See #.edges instead.`);e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.edge: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new P(`Graph.edge: could not find the "${t}" target node in the graph.`);let r=n.out&&n.out[t]||n.undirected&&n.undirected[t]||void 0;if(r)return r.key}areDirectedNeighbors(e,t){e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.areDirectedNeighbors: could not find the "${e}" node in the graph.`);return this.type===`undirected`?!1:t in n.in||t in n.out}areOutNeighbors(e,t){e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.areOutNeighbors: could not find the "${e}" node in the graph.`);return this.type!==`undirected`&&t in n.out}areInNeighbors(e,t){e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.areInNeighbors: could not find the "${e}" node in the graph.`);return this.type!==`undirected`&&t in n.in}areUndirectedNeighbors(e,t){e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.areUndirectedNeighbors: could not find the "${e}" node in the graph.`);return this.type!==`directed`&&t in n.undirected}areNeighbors(e,t){e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.areNeighbors: could not find the "${e}" node in the graph.`);return this.type!==`undirected`&&(t in n.in||t in n.out)||this.type!==`directed`&&t in n.undirected}areInboundNeighbors(e,t){e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.areInboundNeighbors: could not find the "${e}" node in the graph.`);return this.type!==`undirected`&&t in n.in||this.type!==`directed`&&t in n.undirected}areOutboundNeighbors(e,t){e=``+e,t=``+t;let n=this._nodes.get(e);if(!n)throw new P(`Graph.areOutboundNeighbors: could not find the "${e}" node in the graph.`);return this.type!==`undirected`&&t in n.out||this.type!==`directed`&&t in n.undirected}inDegree(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.inDegree: could not find the "${e}" node in the graph.`);return this.type===`undirected`?0:t.inDegree}outDegree(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.outDegree: could not find the "${e}" node in the graph.`);return this.type===`undirected`?0:t.outDegree}directedDegree(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.directedDegree: could not find the "${e}" node in the graph.`);return this.type===`undirected`?0:t.inDegree+t.outDegree}undirectedDegree(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.undirectedDegree: could not find the "${e}" node in the graph.`);return this.type===`directed`?0:t.undirectedDegree}inboundDegree(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.inboundDegree: could not find the "${e}" node in the graph.`);let n=0;return this.type!==`directed`&&(n+=t.undirectedDegree),this.type!==`undirected`&&(n+=t.inDegree),n}outboundDegree(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.outboundDegree: could not find the "${e}" node in the graph.`);let n=0;return this.type!==`directed`&&(n+=t.undirectedDegree),this.type!==`undirected`&&(n+=t.outDegree),n}degree(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.degree: could not find the "${e}" node in the graph.`);let n=0;return this.type!==`directed`&&(n+=t.undirectedDegree),this.type!==`undirected`&&(n+=t.inDegree+t.outDegree),n}inDegreeWithoutSelfLoops(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.inDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);return this.type===`undirected`?0:t.inDegree-t.directedLoops}outDegreeWithoutSelfLoops(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.outDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);return this.type===`undirected`?0:t.outDegree-t.directedLoops}directedDegreeWithoutSelfLoops(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.directedDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);return this.type===`undirected`?0:t.inDegree+t.outDegree-t.directedLoops*2}undirectedDegreeWithoutSelfLoops(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.undirectedDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);return this.type===`directed`?0:t.undirectedDegree-t.undirectedLoops*2}inboundDegreeWithoutSelfLoops(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.inboundDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);let n=0,r=0;return this.type!==`directed`&&(n+=t.undirectedDegree,r+=t.undirectedLoops*2),this.type!==`undirected`&&(n+=t.inDegree,r+=t.directedLoops),n-r}outboundDegreeWithoutSelfLoops(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.outboundDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);let n=0,r=0;return this.type!==`directed`&&(n+=t.undirectedDegree,r+=t.undirectedLoops*2),this.type!==`undirected`&&(n+=t.outDegree,r+=t.directedLoops),n-r}degreeWithoutSelfLoops(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.degreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);let n=0,r=0;return this.type!==`directed`&&(n+=t.undirectedDegree,r+=t.undirectedLoops*2),this.type!==`undirected`&&(n+=t.inDegree+t.outDegree,r+=t.directedLoops*2),n-r}source(e){e=``+e;let t=this._edges.get(e);if(!t)throw new P(`Graph.source: could not find the "${e}" edge in the graph.`);return t.source.key}target(e){e=``+e;let t=this._edges.get(e);if(!t)throw new P(`Graph.target: could not find the "${e}" edge in the graph.`);return t.target.key}extremities(e){e=``+e;let t=this._edges.get(e);if(!t)throw new P(`Graph.extremities: could not find the "${e}" edge in the graph.`);return[t.source.key,t.target.key]}opposite(e,t){e=``+e,t=``+t;let n=this._edges.get(t);if(!n)throw new P(`Graph.opposite: could not find the "${t}" edge in the graph.`);let r=n.source.key,i=n.target.key;if(e===r)return i;if(e===i)return r;throw new P(`Graph.opposite: the "${e}" node is not attached to the "${t}" edge (${r}, ${i}).`)}hasExtremity(e,t){e=``+e,t=``+t;let n=this._edges.get(e);if(!n)throw new P(`Graph.hasExtremity: could not find the "${e}" edge in the graph.`);return n.source.key===t||n.target.key===t}isUndirected(e){e=``+e;let t=this._edges.get(e);if(!t)throw new P(`Graph.isUndirected: could not find the "${e}" edge in the graph.`);return t.undirected}isDirected(e){e=``+e;let t=this._edges.get(e);if(!t)throw new P(`Graph.isDirected: could not find the "${e}" edge in the graph.`);return!t.undirected}isSelfLoop(e){e=``+e;let t=this._edges.get(e);if(!t)throw new P(`Graph.isSelfLoop: could not find the "${e}" edge in the graph.`);return t.source===t.target}addNode(e,t){return gt(this,e,t).key}mergeNode(e,t){if(t&&!w(t))throw new N(`Graph.mergeNode: invalid attributes. Expecting an object but got "${t}"`);e=``+e,t||={};let n=this._nodes.get(e);return n?(t&&(S(n.attributes,t),this.emit(`nodeAttributesUpdated`,{type:`merge`,key:e,attributes:n.attributes,data:t})),[e,!1]):(n=new this.NodeDataClass(e,t),this._nodes.set(e,n),this.emit(`nodeAdded`,{key:e,attributes:t}),[e,!0])}updateNode(e,t){if(t&&typeof t!=`function`)throw new N(`Graph.updateNode: invalid updater function. Expecting a function but got "${t}"`);e=``+e;let n=this._nodes.get(e);if(n){if(t){let r=n.attributes;n.attributes=t(r),this.emit(`nodeAttributesUpdated`,{type:`replace`,key:e,attributes:n.attributes})}return[e,!1]}let r=t?t({}):{};return n=new this.NodeDataClass(e,r),this._nodes.set(e,n),this.emit(`nodeAdded`,{key:e,attributes:r}),[e,!0]}dropNode(e){e=``+e;let t=this._nodes.get(e);if(!t)throw new P(`Graph.dropNode: could not find the "${e}" node in the graph.`);let n;if(this.type!==`undirected`){for(let e in t.out){n=t.out[e];do bt(this,n),n=n.next;while(n)}for(let e in t.in){n=t.in[e];do bt(this,n),n=n.next;while(n)}}if(this.type!==`directed`)for(let e in t.undirected){n=t.undirected[e];do bt(this,n),n=n.next;while(n)}this._nodes.delete(e),this.emit(`nodeDropped`,{key:e,attributes:t.attributes})}dropEdge(e){let t;if(arguments.length>1){let e=``+arguments[0],n=``+arguments[1];if(t=C(this,e,n,this.type),!t)throw new P(`Graph.dropEdge: could not find the "${e}" -> "${n}" edge in the graph.`)}else if(e=``+e,t=this._edges.get(e),!t)throw new P(`Graph.dropEdge: could not find the "${e}" edge in the graph.`);return bt(this,t),this}dropDirectedEdge(e,t){if(arguments.length<2)throw new F(`Graph.dropDirectedEdge: it does not make sense to try and drop a directed edge by key. What if the edge with this key is undirected? Use #.dropEdge for this purpose instead.`);if(this.multi)throw new F(`Graph.dropDirectedEdge: cannot use a {source,target} combo when dropping an edge in a MultiGraph since we cannot infer the one you want to delete as there could be multiple ones.`);e=``+e,t=``+t;let n=C(this,e,t,`directed`);if(!n)throw new P(`Graph.dropDirectedEdge: could not find a "${e}" -> "${t}" edge in the graph.`);return bt(this,n),this}dropUndirectedEdge(e,t){if(arguments.length<2)throw new F(`Graph.dropUndirectedEdge: it does not make sense to drop a directed edge by key. What if the edge with this key is undirected? Use #.dropEdge for this purpose instead.`);if(this.multi)throw new F(`Graph.dropUndirectedEdge: cannot use a {source,target} combo when dropping an edge in a MultiGraph since we cannot infer the one you want to delete as there could be multiple ones.`);let n=C(this,e,t,`undirected`);if(!n)throw new P(`Graph.dropUndirectedEdge: could not find a "${e}" -> "${t}" edge in the graph.`);return bt(this,n),this}clear(){this._edges.clear(),this._nodes.clear(),this._resetInstanceCounters(),this.emit(`cleared`)}clearEdges(){let e=this._nodes.values(),t;for(;t=e.next(),t.done!==!0;)t.value.clear();this._edges.clear(),this._resetInstanceCounters(),this.emit(`edgesCleared`)}getAttribute(e){return this._attributes[e]}getAttributes(){return this._attributes}hasAttribute(e){return this._attributes.hasOwnProperty(e)}setAttribute(e,t){return this._attributes[e]=t,this.emit(`attributesUpdated`,{type:`set`,attributes:this._attributes,name:e}),this}updateAttribute(e,t){if(typeof t!=`function`)throw new N(`Graph.updateAttribute: updater should be a function.`);let n=this._attributes[e];return this._attributes[e]=t(n),this.emit(`attributesUpdated`,{type:`set`,attributes:this._attributes,name:e}),this}removeAttribute(e){return delete this._attributes[e],this.emit(`attributesUpdated`,{type:`remove`,attributes:this._attributes,name:e}),this}replaceAttributes(e){if(!w(e))throw new N(`Graph.replaceAttributes: provided attributes are not a plain object.`);return this._attributes=e,this.emit(`attributesUpdated`,{type:`replace`,attributes:this._attributes}),this}mergeAttributes(e){if(!w(e))throw new N(`Graph.mergeAttributes: provided attributes are not a plain object.`);return S(this._attributes,e),this.emit(`attributesUpdated`,{type:`merge`,attributes:this._attributes,data:e}),this}updateAttributes(e){if(typeof e!=`function`)throw new N(`Graph.updateAttributes: provided updater is not a function.`);return this._attributes=e(this._attributes),this.emit(`attributesUpdated`,{type:`update`,attributes:this._attributes}),this}updateEachNodeAttributes(e,t){if(typeof e!=`function`)throw new N(`Graph.updateEachNodeAttributes: expecting an updater function.`);if(t&&!O(t))throw new N(`Graph.updateEachNodeAttributes: invalid hints. Expecting an object having the following shape: {attributes?: [string]}`);let n=this._nodes.values(),r,i;for(;r=n.next(),r.done!==!0;)i=r.value,i.attributes=e(i.key,i.attributes);this.emit(`eachNodeAttributesUpdated`,{hints:t||null})}updateEachEdgeAttributes(e,t){if(typeof e!=`function`)throw new N(`Graph.updateEachEdgeAttributes: expecting an updater function.`);if(t&&!O(t))throw new N(`Graph.updateEachEdgeAttributes: invalid hints. Expecting an object having the following shape: {attributes?: [string]}`);let n=this._edges.values(),r,i,a,o;for(;r=n.next(),r.done!==!0;)i=r.value,a=i.source,o=i.target,i.attributes=e(i.key,i.attributes,a.key,o.key,a.attributes,o.attributes,i.undirected);this.emit(`eachEdgeAttributesUpdated`,{hints:t||null})}forEachAdjacencyEntry(e){if(typeof e!=`function`)throw new N(`Graph.forEachAdjacencyEntry: expecting a callback.`);ot(!1,!1,!1,this,e)}forEachAdjacencyEntryWithOrphans(e){if(typeof e!=`function`)throw new N(`Graph.forEachAdjacencyEntryWithOrphans: expecting a callback.`);ot(!1,!1,!0,this,e)}forEachAssymetricAdjacencyEntry(e){if(typeof e!=`function`)throw new N(`Graph.forEachAssymetricAdjacencyEntry: expecting a callback.`);ot(!1,!0,!1,this,e)}forEachAssymetricAdjacencyEntryWithOrphans(e){if(typeof e!=`function`)throw new N(`Graph.forEachAssymetricAdjacencyEntryWithOrphans: expecting a callback.`);ot(!1,!0,!0,this,e)}nodes(){return Array.from(this._nodes.keys())}forEachNode(e){if(typeof e!=`function`)throw new N(`Graph.forEachNode: expecting a callback.`);let t=this._nodes.values(),n,r;for(;n=t.next(),n.done!==!0;)r=n.value,e(r.key,r.attributes)}findNode(e){if(typeof e!=`function`)throw new N(`Graph.findNode: expecting a callback.`);let t=this._nodes.values(),n,r;for(;n=t.next(),n.done!==!0;)if(r=n.value,e(r.key,r.attributes))return r.key}mapNodes(e){if(typeof e!=`function`)throw new N(`Graph.mapNode: expecting a callback.`);let t=this._nodes.values(),n,r,i=Array(this.order),a=0;for(;n=t.next(),n.done!==!0;)r=n.value,i[a++]=e(r.key,r.attributes);return i}someNode(e){if(typeof e!=`function`)throw new N(`Graph.someNode: expecting a callback.`);let t=this._nodes.values(),n,r;for(;n=t.next(),n.done!==!0;)if(r=n.value,e(r.key,r.attributes))return!0;return!1}everyNode(e){if(typeof e!=`function`)throw new N(`Graph.everyNode: expecting a callback.`);let t=this._nodes.values(),n,r;for(;n=t.next(),n.done!==!0;)if(r=n.value,!e(r.key,r.attributes))return!1;return!0}filterNodes(e){if(typeof e!=`function`)throw new N(`Graph.filterNodes: expecting a callback.`);let t=this._nodes.values(),n,r,i=[];for(;n=t.next(),n.done!==!0;)r=n.value,e(r.key,r.attributes)&&i.push(r.key);return i}reduceNodes(e,t){if(typeof e!=`function`)throw new N(`Graph.reduceNodes: expecting a callback.`);if(arguments.length<2)throw new N(`Graph.reduceNodes: missing initial value. You must provide it because the callback takes more than one argument and we cannot infer the initial value from the first iteration, as you could with a simple array.`);let n=t,r=this._nodes.values(),i,a;for(;i=r.next(),i.done!==!0;)a=i.value,n=e(n,a.key,a.attributes);return n}nodeEntries(){let e=this._nodes.values();return{[Symbol.iterator](){return this},next(){let t=e.next();if(t.done)return t;let n=t.value;return{value:{node:n.key,attributes:n.attributes},done:!1}}}}export(){let e=Array(this._nodes.size),t=0;this._nodes.forEach((n,r)=>{e[t++]=st(r,n)});let n=Array(this._edges.size);return t=0,this._edges.forEach((e,r)=>{n[t++]=ct(this.type,r,e)}),{options:{type:this.type,multi:this.multi,allowSelfLoops:this.allowSelfLoops},attributes:this.getAttributes(),nodes:e,edges:n}}import(t,n=!1){if(t instanceof e)return t.forEachNode((e,t)=>{n?this.mergeNode(e,t):this.addNode(e,t)}),t.forEachEdge((e,t,r,i,a,o,s)=>{n?s?this.mergeUndirectedEdgeWithKey(e,r,i,t):this.mergeDirectedEdgeWithKey(e,r,i,t):s?this.addUndirectedEdgeWithKey(e,r,i,t):this.addDirectedEdgeWithKey(e,r,i,t)}),this;if(!w(t))throw new N(`Graph.import: invalid argument. Expecting a serialized graph or, alternatively, a Graph instance.`);if(t.attributes){if(!w(t.attributes))throw new N(`Graph.import: invalid attributes. Expecting a plain object.`);n?this.mergeAttributes(t.attributes):this.replaceAttributes(t.attributes)}let r,i,a,o,s;if(t.nodes){if(a=t.nodes,!Array.isArray(a))throw new N(`Graph.import: invalid nodes. Expecting an array.`);for(r=0,i=a.length;r<i;r++){o=a[r],lt(o);let{key:e,attributes:t}=o;n?this.mergeNode(e,t):this.addNode(e,t)}}if(t.edges){let e=!1;if(this.type===`undirected`&&(e=!0),a=t.edges,!Array.isArray(a))throw new N(`Graph.import: invalid edges. Expecting an array.`);for(r=0,i=a.length;r<i;r++){s=a[r],ut(s);let{source:t,target:i,attributes:o,undirected:c=e}=s,l;`key`in s?(l=n?c?this.mergeUndirectedEdgeWithKey:this.mergeDirectedEdgeWithKey:c?this.addUndirectedEdgeWithKey:this.addDirectedEdgeWithKey,l.call(this,s.key,t,i,o)):(l=n?c?this.mergeUndirectedEdge:this.mergeDirectedEdge:c?this.addUndirectedEdge:this.addDirectedEdge,l.call(this,t,i,o))}}return this}nullCopy(t){let n=new e(S({},this._options,t));return n.replaceAttributes(S({},this.getAttributes())),n}emptyCopy(e){let t=this.nullCopy(e);return this._nodes.forEach((e,n)=>{let r=S({},e.attributes);e=new t.NodeDataClass(n,r),t._nodes.set(n,e)}),t}copy(e){if(e||={},typeof e.type==`string`&&e.type!==this.type&&e.type!==`mixed`)throw new F(`Graph.copy: cannot create an incompatible copy from "${this.type}" type to "${e.type}" because this would mean losing information about the current graph.`);if(typeof e.multi==`boolean`&&e.multi!==this.multi&&e.multi!==!0)throw new F(`Graph.copy: cannot create an incompatible copy by downgrading a multi graph to a simple one because this would mean losing information about the current graph.`);if(typeof e.allowSelfLoops==`boolean`&&e.allowSelfLoops!==this.allowSelfLoops&&e.allowSelfLoops!==!0)throw new F(`Graph.copy: cannot create an incompatible copy from a graph allowing self loops to one that does not because this would mean losing information about the current graph.`);let t=this.emptyCopy(e),n=this._edges.values(),r,i;for(;r=n.next(),r.done!==!0;)i=r.value,vt(t,`copy`,!1,i.undirected,i.key,i.source.key,i.target.key,S({},i.attributes));return t}toJSON(){return this.export()}toString(){return`[object Graph]`}inspect(){let e={};this._nodes.forEach((t,n)=>{e[n]=t.attributes});let t={},n={};this._edges.forEach((e,r)=>{let i=e.undirected?`--`:`->`,a=``,o=e.source.key,s=e.target.key,c;e.undirected&&o>s&&(c=o,o=s,s=c);let l=`(${o})${i}(${s})`;r.startsWith(`geid_`)?this.multi&&(n[l]===void 0?n[l]=0:n[l]++,a+=`${n[l]}. `):a+=`[${r}]: `,a+=l,t[a]=e.attributes});let r={};for(let e in this)this.hasOwnProperty(e)&&!pt.has(e)&&typeof this[e]!=`function`&&typeof e!=`symbol`&&(r[e]=this[e]);return r.attributes=this._attributes,r.nodes=e,r.edges=t,E(r,`constructor`,this.constructor),r}};typeof Symbol<`u`&&(B.prototype[Symbol.for(`nodejs.util.inspect.custom`)]=B.prototype.inspect),mt.forEach(e=>{[`add`,`merge`,`update`].forEach(t=>{let n=e.name(t),r=t===`add`?vt:yt;e.generateKey?B.prototype[n]=function(i,a,o){return r(this,n,!0,(e.type||this.type)===`undirected`,null,i,a,o,t===`update`)}:B.prototype[n]=function(i,a,o,s){return r(this,n,!1,(e.type||this.type)===`undirected`,i,a,o,s,t===`update`)}})}),he(B),Ee(B),qe(B),at(B);var xt=class extends B{constructor(e){let t=S({type:`directed`},e);if(`multi`in t&&t.multi!==!1)throw new N(`DirectedGraph.from: inconsistent indication that the graph should be multi in given options!`);if(t.type!==`directed`)throw new N(`DirectedGraph.from: inconsistent "`+t.type+`" type in given options!`);super(t)}},St=class extends B{constructor(e){let t=S({type:`undirected`},e);if(`multi`in t&&t.multi!==!1)throw new N(`UndirectedGraph.from: inconsistent indication that the graph should be multi in given options!`);if(t.type!==`undirected`)throw new N(`UndirectedGraph.from: inconsistent "`+t.type+`" type in given options!`);super(t)}},Ct=class extends B{constructor(e){let t=S({multi:!0},e);if(`multi`in t&&t.multi!==!0)throw new N(`MultiGraph.from: inconsistent indication that the graph should be simple in given options!`);super(t)}},wt=class extends B{constructor(e){let t=S({type:`directed`,multi:!0},e);if(`multi`in t&&t.multi!==!0)throw new N(`MultiDirectedGraph.from: inconsistent indication that the graph should be simple in given options!`);if(t.type!==`directed`)throw new N(`MultiDirectedGraph.from: inconsistent "`+t.type+`" type in given options!`);super(t)}},Tt=class extends B{constructor(e){let t=S({type:`undirected`,multi:!0},e);if(`multi`in t&&t.multi!==!0)throw new N(`MultiUndirectedGraph.from: inconsistent indication that the graph should be simple in given options!`);if(t.type!==`undirected`)throw new N(`MultiUndirectedGraph.from: inconsistent "`+t.type+`" type in given options!`);super(t)}};function Et(e){e.from=function(t,n){let r=new e(S({},t.options,n));return r.import(t),r}}Et(B),Et(xt),Et(St),Et(Ct),Et(wt),Et(Tt),B.Graph=B,B.DirectedGraph=xt,B.UndirectedGraph=St,B.MultiGraph=Ct,B.MultiDirectedGraph=wt,B.MultiUndirectedGraph=Tt,B.InvalidArgumentsGraphError=N,B.NotFoundGraphError=P,B.UsageGraphError=F;var Dt=_(((e,t)=>{t.exports=function(e){return typeof e==`object`&&!!e&&typeof e.addUndirectedEdgeWithKey==`function`&&typeof e.dropNode==`function`&&typeof e.multi==`boolean`}})),Ot=_((e=>{function t(e){return typeof e!=`number`||isNaN(e)?1:e}function n(e,t){var n={},r=function(e){return e===void 0?t:e};typeof t==`function`&&(r=t);var i=function(t){return r(t[e])},a=function(){return r(void 0)};return typeof e==`string`?(n.fromAttributes=i,n.fromGraph=function(e,t){return i(e.getNodeAttributes(t))},n.fromEntry=function(e,t){return i(t)}):typeof e==`function`?(n.fromAttributes=function(){throw Error(`graphology-utils/getters/createNodeValueGetter: irrelevant usage.`)},n.fromGraph=function(t,n){return r(e(n,t.getNodeAttributes(n)))},n.fromEntry=function(t,n){return r(e(t,n))}):(n.fromAttributes=a,n.fromGraph=a,n.fromEntry=a),n}function r(e,t){var n={},r=function(e){return e===void 0?t:e};typeof t==`function`&&(r=t);var i=function(t){return r(t[e])},a=function(){return r(void 0)};return typeof e==`string`?(n.fromAttributes=i,n.fromGraph=function(e,t){return i(e.getEdgeAttributes(t))},n.fromEntry=function(e,t){return i(t)},n.fromPartialEntry=n.fromEntry,n.fromMinimalEntry=n.fromEntry):typeof e==`function`?(n.fromAttributes=function(){throw Error(`graphology-utils/getters/createEdgeValueGetter: irrelevant usage.`)},n.fromGraph=function(t,n){var i=t.extremities(n);return r(e(n,t.getEdgeAttributes(n),i[0],i[1],t.getNodeAttributes(i[0]),t.getNodeAttributes(i[1]),t.isUndirected(n)))},n.fromEntry=function(t,n,i,a,o,s,c){return r(e(t,n,i,a,o,s,c))},n.fromPartialEntry=function(t,n,i,a){return r(e(t,n,i,a))},n.fromMinimalEntry=function(t,n){return r(e(t,n))}):(n.fromAttributes=a,n.fromGraph=a,n.fromEntry=a,n.fromMinimalEntry=a),n}e.createNodeValueGetter=n,e.createEdgeValueGetter=r,e.createEdgeWeightGetter=function(e){return r(e,t)}})),kt=_(((e,t)=>{t.exports=function(e,t,n){var r,i,a,o,s,c,l,u,d,f,p=t.length,m=n.length,h=e.adjustSizes,g=e.barnesHutTheta*e.barnesHutTheta,_,v,y,b,x,S,C,w=[];for(a=0;a<p;a+=10)t[a+4]=t[a+2],t[a+5]=t[a+3],t[a+2]=0,t[a+3]=0;if(e.outboundAttractionDistribution){for(_=0,a=0;a<p;a+=10)_+=t[a+6];_/=p/10}if(e.barnesHutOptimize){var T=1/0,E=-1/0,D=1/0,O=-1/0,k,A,j;for(a=0;a<p;a+=10)T=Math.min(T,t[a+0]),E=Math.max(E,t[a+0]),D=Math.min(D,t[a+1]),O=Math.max(O,t[a+1]);var M=E-T,N=O-D;for(M>N?(D-=(M-N)/2,O=D+M):(T-=(N-M)/2,E=T+N),w[0]=-1,w[1]=(T+E)/2,w[2]=(D+O)/2,w[3]=Math.max(E-T,O-D),w[4]=-1,w[5]=-1,w[6]=0,w[7]=0,w[8]=0,r=1,a=0;a<p;a+=10)for(i=0,j=3;;)if(w[i+5]>=0){k=t[a+0]<w[i+1]?t[a+1]<w[i+2]?w[i+5]:w[i+5]+9:t[a+1]<w[i+2]?w[i+5]+18:w[i+5]+27,w[i+7]=(w[i+7]*w[i+6]+t[a+0]*t[a+6])/(w[i+6]+t[a+6]),w[i+8]=(w[i+8]*w[i+6]+t[a+1]*t[a+6])/(w[i+6]+t[a+6]),w[i+6]+=t[a+6],i=k;continue}else if(w[i+0]<0){w[i+0]=a;break}else{if(w[i+5]=r*9,u=w[i+3]/2,d=w[i+5],w[d+0]=-1,w[d+1]=w[i+1]-u,w[d+2]=w[i+2]-u,w[d+3]=u,w[d+4]=d+9,w[d+5]=-1,w[d+6]=0,w[d+7]=0,w[d+8]=0,d+=9,w[d+0]=-1,w[d+1]=w[i+1]-u,w[d+2]=w[i+2]+u,w[d+3]=u,w[d+4]=d+9,w[d+5]=-1,w[d+6]=0,w[d+7]=0,w[d+8]=0,d+=9,w[d+0]=-1,w[d+1]=w[i+1]+u,w[d+2]=w[i+2]-u,w[d+3]=u,w[d+4]=d+9,w[d+5]=-1,w[d+6]=0,w[d+7]=0,w[d+8]=0,d+=9,w[d+0]=-1,w[d+1]=w[i+1]+u,w[d+2]=w[i+2]+u,w[d+3]=u,w[d+4]=w[i+4],w[d+5]=-1,w[d+6]=0,w[d+7]=0,w[d+8]=0,r+=4,k=t[w[i+0]+0]<w[i+1]?t[w[i+0]+1]<w[i+2]?w[i+5]:w[i+5]+9:t[w[i+0]+1]<w[i+2]?w[i+5]+18:w[i+5]+27,w[i+6]=t[w[i+0]+6],w[i+7]=t[w[i+0]+0],w[i+8]=t[w[i+0]+1],w[k+0]=w[i+0],w[i+0]=-1,A=t[a+0]<w[i+1]?t[a+1]<w[i+2]?w[i+5]:w[i+5]+9:t[a+1]<w[i+2]?w[i+5]+18:w[i+5]+27,k===A){if(j--){i=k;continue}j=3;break}w[A+0]=a;break}}if(e.barnesHutOptimize)for(v=e.scalingRatio,a=0;a<p;a+=10)for(i=0;;)if(w[i+5]>=0){if(S=(t[a+0]-w[i+7])**2+(t[a+1]-w[i+8])**2,f=w[i+3],4*f*f/S<g){if(y=t[a+0]-w[i+7],b=t[a+1]-w[i+8],h===!0?S>0?(C=v*t[a+6]*w[i+6]/S,t[a+2]+=y*C,t[a+3]+=b*C):S<0&&(C=-v*t[a+6]*w[i+6]/Math.sqrt(S),t[a+2]+=y*C,t[a+3]+=b*C):S>0&&(C=v*t[a+6]*w[i+6]/S,t[a+2]+=y*C,t[a+3]+=b*C),i=w[i+4],i<0)break;continue}i=w[i+5];continue}else{if(c=w[i+0],c>=0&&c!==a&&(y=t[a+0]-t[c+0],b=t[a+1]-t[c+1],S=y*y+b*b,h===!0?S>0?(C=v*t[a+6]*t[c+6]/S,t[a+2]+=y*C,t[a+3]+=b*C):S<0&&(C=-v*t[a+6]*t[c+6]/Math.sqrt(S),t[a+2]+=y*C,t[a+3]+=b*C):S>0&&(C=v*t[a+6]*t[c+6]/S,t[a+2]+=y*C,t[a+3]+=b*C)),i=w[i+4],i<0)break;continue}else for(v=e.scalingRatio,o=0;o<p;o+=10)for(s=0;s<o;s+=10)y=t[o+0]-t[s+0],b=t[o+1]-t[s+1],h===!0?(S=Math.sqrt(y*y+b*b)-t[o+8]-t[s+8],S>0?(C=v*t[o+6]*t[s+6]/S/S,t[o+2]+=y*C,t[o+3]+=b*C,t[s+2]-=y*C,t[s+3]-=b*C):S<0&&(C=100*v*t[o+6]*t[s+6],t[o+2]+=y*C,t[o+3]+=b*C,t[s+2]-=y*C,t[s+3]-=b*C)):(S=Math.sqrt(y*y+b*b),S>0&&(C=v*t[o+6]*t[s+6]/S/S,t[o+2]+=y*C,t[o+3]+=b*C,t[s+2]-=y*C,t[s+3]-=b*C));for(d=e.gravity/e.scalingRatio,v=e.scalingRatio,a=0;a<p;a+=10)C=0,y=t[a+0],b=t[a+1],S=Math.sqrt(y**2+b**2),e.strongGravityMode?S>0&&(C=v*t[a+6]*d):S>0&&(C=v*t[a+6]*d/S),t[a+2]-=y*C,t[a+3]-=b*C;for(v=1*(e.outboundAttractionDistribution?_:1),l=0;l<m;l+=3)o=n[l+0],s=n[l+1],u=n[l+2],x=u**+e.edgeWeightInfluence,y=t[o+0]-t[s+0],b=t[o+1]-t[s+1],h===!0?(S=Math.sqrt(y*y+b*b)-t[o+8]-t[s+8],e.linLogMode?e.outboundAttractionDistribution?S>0&&(C=-v*x*Math.log(1+S)/S/t[o+6]):S>0&&(C=-v*x*Math.log(1+S)/S):e.outboundAttractionDistribution?S>0&&(C=-v*x/t[o+6]):S>0&&(C=-v*x)):(S=Math.sqrt(y**2+b**2),e.linLogMode?e.outboundAttractionDistribution?S>0&&(C=-v*x*Math.log(1+S)/S/t[o+6]):S>0&&(C=-v*x*Math.log(1+S)/S):e.outboundAttractionDistribution?(S=1,C=-v*x/t[o+6]):(S=1,C=-v*x)),S>0&&(t[o+2]+=y*C,t[o+3]+=b*C,t[s+2]-=y*C,t[s+3]-=b*C);var P,F,I,L,R,z;if(h===!0)for(a=0;a<p;a+=10)t[a+9]!==1&&(P=Math.sqrt(t[a+2]**2+t[a+3]**2),P>10&&(t[a+2]=t[a+2]*10/P,t[a+3]=t[a+3]*10/P),F=t[a+6]*Math.sqrt((t[a+4]-t[a+2])*(t[a+4]-t[a+2])+(t[a+5]-t[a+3])*(t[a+5]-t[a+3])),I=Math.sqrt((t[a+4]+t[a+2])*(t[a+4]+t[a+2])+(t[a+5]+t[a+3])*(t[a+5]+t[a+3]))/2,L=.1*Math.log(1+I)/(1+Math.sqrt(F)),R=t[a+0]+t[a+2]*(L/e.slowDown),t[a+0]=R,z=t[a+1]+t[a+3]*(L/e.slowDown),t[a+1]=z);else for(a=0;a<p;a+=10)t[a+9]!==1&&(F=t[a+6]*Math.sqrt((t[a+4]-t[a+2])*(t[a+4]-t[a+2])+(t[a+5]-t[a+3])*(t[a+5]-t[a+3])),I=Math.sqrt((t[a+4]+t[a+2])*(t[a+4]+t[a+2])+(t[a+5]+t[a+3])*(t[a+5]+t[a+3]))/2,L=t[a+7]*Math.log(1+I)/(1+Math.sqrt(F)),t[a+7]=Math.min(1,Math.sqrt(L*(t[a+2]**2+t[a+3]**2)/(1+Math.sqrt(F)))),R=t[a+0]+t[a+2]*(L/e.slowDown),t[a+0]=R,z=t[a+1]+t[a+3]*(L/e.slowDown),t[a+1]=z);return{}}})),At=_((e=>{e.assign=function(e){e||={};for(var t=Array.prototype.slice.call(arguments).slice(1),n=0,r,i=t.length;n<i;n++)if(t[n])for(r in t[n])e[r]=t[n][r];return e},e.validateSettings=function(e){return`linLogMode`in e&&typeof e.linLogMode!=`boolean`?{message:"the `linLogMode` setting should be a boolean."}:`outboundAttractionDistribution`in e&&typeof e.outboundAttractionDistribution!=`boolean`?{message:"the `outboundAttractionDistribution` setting should be a boolean."}:`adjustSizes`in e&&typeof e.adjustSizes!=`boolean`?{message:"the `adjustSizes` setting should be a boolean."}:`edgeWeightInfluence`in e&&typeof e.edgeWeightInfluence!=`number`?{message:"the `edgeWeightInfluence` setting should be a number."}:`scalingRatio`in e&&!(typeof e.scalingRatio==`number`&&e.scalingRatio>=0)?{message:"the `scalingRatio` setting should be a number >= 0."}:`strongGravityMode`in e&&typeof e.strongGravityMode!=`boolean`?{message:"the `strongGravityMode` setting should be a boolean."}:`gravity`in e&&!(typeof e.gravity==`number`&&e.gravity>=0)?{message:"the `gravity` setting should be a number >= 0."}:`slowDown`in e&&!(typeof e.slowDown==`number`||e.slowDown>=0)?{message:"the `slowDown` setting should be a number >= 0."}:`barnesHutOptimize`in e&&typeof e.barnesHutOptimize!=`boolean`?{message:"the `barnesHutOptimize` setting should be a boolean."}:`barnesHutTheta`in e&&!(typeof e.barnesHutTheta==`number`&&e.barnesHutTheta>=0)?{message:"the `barnesHutTheta` setting should be a number >= 0."}:null},e.graphToByteArrays=function(e,t){var n=e.order,r=e.size,i={},a,o=new Float32Array(n*10),s=new Float32Array(r*3);return a=0,e.forEachNode(function(e,t){i[e]=a,o[a]=t.x,o[a+1]=t.y,o[a+2]=0,o[a+3]=0,o[a+4]=0,o[a+5]=0,o[a+6]=1,o[a+7]=1,o[a+8]=t.size||1,o[a+9]=+!!t.fixed,a+=10}),a=0,e.forEachEdge(function(e,n,r,c,l,u,d){var f=i[r],p=i[c],m=t(e,n,r,c,l,u,d);o[f+6]+=m,o[p+6]+=m,s[a]=f,s[a+1]=p,s[a+2]=m,a+=3}),{nodes:o,edges:s}},e.assignLayoutChanges=function(e,t,n){var r=0;e.updateEachNodeAttributes(function(e,i){return i.x=t[r],i.y=t[r+1],r+=10,n?n(e,i):i})},e.readGraphPositions=function(e,t){var n=0;e.forEachNode(function(e,r){t[n]=r.x,t[n+1]=r.y,n+=10})},e.collectLayoutChanges=function(e,t,n){for(var r=e.nodes(),i={},a=0,o=0,s=t.length;a<s;a+=10){if(n){var c=Object.assign({},e.getNodeAttributes(r[o]));c.x=t[a],c.y=t[a+1],c=n(r[o],c),i[r[o]]={x:c.x,y:c.y}}else i[r[o]]={x:t[a],y:t[a+1]};o++}return i},e.createWorker=function(e){var t=window.URL||window.webkitURL,n=e.toString(),r=t.createObjectURL(new Blob([`(`+n+`).call(this);`],{type:`text/javascript`})),i=new Worker(r);return t.revokeObjectURL(r),i}})),jt=_(((e,t)=>{t.exports={linLogMode:!1,outboundAttractionDistribution:!1,adjustSizes:!1,edgeWeightInfluence:1,scalingRatio:1,strongGravityMode:!1,gravity:1,slowDown:1,barnesHutOptimize:!1,barnesHutTheta:.5}})),Mt=y(_(((e,t)=>{var n=Dt(),r=Ot().createEdgeWeightGetter,i=kt(),a=At(),o=jt();function s(e,t,s){if(!n(t))throw Error(`graphology-layout-forceatlas2: the given graph is not a valid graphology instance.`);typeof s==`number`&&(s={iterations:s});var c=s.iterations;if(typeof c!=`number`)throw Error(`graphology-layout-forceatlas2: invalid number of iterations.`);if(c<=0)throw Error(`graphology-layout-forceatlas2: you should provide a positive number of iterations.`);var l=r(`getEdgeWeight`in s?s.getEdgeWeight:`weight`).fromEntry,u=typeof s.outputReducer==`function`?s.outputReducer:null,d=a.assign({},o,s.settings),f=a.validateSettings(d);if(f)throw Error(`graphology-layout-forceatlas2: `+f.message);for(var p=a.graphToByteArrays(t,l),m=0;m<c;m++)i(d,p.nodes,p.edges);if(e)a.assignLayoutChanges(t,p.nodes,u);else return a.collectLayoutChanges(t,p.nodes)}function c(e){var t=typeof e==`number`?e:e.order;return{barnesHutOptimize:t>2e3,strongGravityMode:!0,gravity:.05,scalingRatio:10,slowDown:1+Math.log(t)}}var l=s.bind(null,!1);l.assign=s.bind(null,!0),l.inferSettings=c,t.exports=l}))(),1);function Nt(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function Pt(e,t){if(e){if(typeof e==`string`)return Nt(e,t);var n={}.toString.call(e).slice(8,-1);return n===`Object`&&e.constructor&&(n=e.constructor.name),n===`Map`||n===`Set`?Array.from(e):n===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Nt(e,t):void 0}}function Ft(e){if(Array.isArray(e))return e}function It(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t===0){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function Lt(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
|
|
2
|
+
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function V(e,t){return Ft(e)||It(e,t)||Pt(e,t)||Lt()}function H(e,t){var n=typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(!n){if(Array.isArray(e)||(n=Pt(e))||t&&e&&typeof e.length==`number`){n&&(e=n);var r=0,i=function(){};return{s:i,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw TypeError(`Invalid attempt to iterate non-iterable instance.
|
|
3
|
+
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var a,o=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){s=!0,a=e},f:function(){try{o||n.return==null||n.return()}finally{if(s)throw a}}}}function Rt(){return Float32Array.of(1,0,0,0,1,0,0,0,1)}function zt(e,t,n){return e[0]=t,e[4]=typeof n==`number`?n:t,e}function Bt(e,t){var n=Math.sin(t),r=Math.cos(t);return e[0]=r,e[1]=n,e[3]=-n,e[4]=r,e}function Vt(e,t,n){return e[6]=t,e[7]=n,e}function Ht(e,t){var n=e[0],r=e[1],i=e[2],a=e[3],o=e[4],s=e[5],c=e[6],l=e[7],u=e[8],d=t[0],f=t[1],p=t[2],m=t[3],h=t[4],g=t[5],_=t[6],v=t[7],y=t[8];return e[0]=d*n+f*a+p*c,e[1]=d*r+f*o+p*l,e[2]=d*i+f*s+p*u,e[3]=m*n+h*a+g*c,e[4]=m*r+h*o+g*l,e[5]=m*i+h*s+g*u,e[6]=_*n+v*a+y*c,e[7]=_*r+v*o+y*l,e[8]=_*i+v*s+y*u,e}function Ut(e,t){var n=Math.cos(t),r=Math.sin(t);return{x:n*e.x+r*e.y,y:-r*e.x+n*e.y}}function Wt(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:1,r=e[0],i=e[1],a=e[3],o=e[4],s=e[6],c=e[7],l=t.x,u=t.y;return{x:l*r+u*a+s*n,y:l*i+u*o+c*n}}function Gt(e,t){var n=e.height/e.width,r=t.height/t.width;return n<1&&r>1||n>1&&r<1?1:Math.min(Math.max(r,1/r),Math.max(1/n,n))}function Kt(e,t,n,r,i){var a=e.angle,o=e.ratio,s=e.x,c=e.y,l=t.width,u=t.height,d=Rt(),f=Math.min(l,u)-2*r,p=Gt(t,n);return i?(Ht(d,Vt(Rt(),s,c)),Ht(d,zt(Rt(),o)),Ht(d,Bt(Rt(),a)),Ht(d,zt(Rt(),l/f/2/p,u/f/2/p))):(Ht(d,zt(Rt(),f/l*2*p,f/u*2*p)),Ht(d,Bt(Rt(),-a)),Ht(d,zt(Rt(),1/o)),Ht(d,Vt(Rt(),-s,-c))),d}function qt(e,t,n){var r=Wt(e,{x:Math.cos(t.angle),y:Math.sin(t.angle)},0),i=r.x,a=r.y;return 1/Math.sqrt(i**2+a**2)/n.width}function Jt(e,t,n,r,i){return[Math.floor(t/i*r),Math.floor(e.drawingBufferHeight/i-n/i*r)]}var Yt={black:`#000000`,silver:`#C0C0C0`,gray:`#808080`,grey:`#808080`,white:`#FFFFFF`,maroon:`#800000`,red:`#FF0000`,purple:`#800080`,fuchsia:`#FF00FF`,green:`#008000`,lime:`#00FF00`,olive:`#808000`,yellow:`#FFFF00`,navy:`#000080`,blue:`#0000FF`,teal:`#008080`,aqua:`#00FFFF`,darkblue:`#00008B`,mediumblue:`#0000CD`,darkgreen:`#006400`,darkcyan:`#008B8B`,deepskyblue:`#00BFFF`,darkturquoise:`#00CED1`,mediumspringgreen:`#00FA9A`,springgreen:`#00FF7F`,cyan:`#00FFFF`,midnightblue:`#191970`,dodgerblue:`#1E90FF`,lightseagreen:`#20B2AA`,forestgreen:`#228B22`,seagreen:`#2E8B57`,darkslategray:`#2F4F4F`,darkslategrey:`#2F4F4F`,limegreen:`#32CD32`,mediumseagreen:`#3CB371`,turquoise:`#40E0D0`,royalblue:`#4169E1`,steelblue:`#4682B4`,darkslateblue:`#483D8B`,mediumturquoise:`#48D1CC`,indigo:`#4B0082`,darkolivegreen:`#556B2F`,cadetblue:`#5F9EA0`,cornflowerblue:`#6495ED`,rebeccapurple:`#663399`,mediumaquamarine:`#66CDAA`,dimgray:`#696969`,dimgrey:`#696969`,slateblue:`#6A5ACD`,olivedrab:`#6B8E23`,slategray:`#708090`,slategrey:`#708090`,lightslategray:`#778899`,lightslategrey:`#778899`,mediumslateblue:`#7B68EE`,lawngreen:`#7CFC00`,chartreuse:`#7FFF00`,aquamarine:`#7FFFD4`,skyblue:`#87CEEB`,lightskyblue:`#87CEFA`,blueviolet:`#8A2BE2`,darkred:`#8B0000`,darkmagenta:`#8B008B`,saddlebrown:`#8B4513`,darkseagreen:`#8FBC8F`,lightgreen:`#90EE90`,mediumpurple:`#9370DB`,darkviolet:`#9400D3`,palegreen:`#98FB98`,darkorchid:`#9932CC`,yellowgreen:`#9ACD32`,sienna:`#A0522D`,brown:`#A52A2A`,darkgray:`#A9A9A9`,darkgrey:`#A9A9A9`,lightblue:`#ADD8E6`,greenyellow:`#ADFF2F`,paleturquoise:`#AFEEEE`,lightsteelblue:`#B0C4DE`,powderblue:`#B0E0E6`,firebrick:`#B22222`,darkgoldenrod:`#B8860B`,mediumorchid:`#BA55D3`,rosybrown:`#BC8F8F`,darkkhaki:`#BDB76B`,mediumvioletred:`#C71585`,indianred:`#CD5C5C`,peru:`#CD853F`,chocolate:`#D2691E`,tan:`#D2B48C`,lightgray:`#D3D3D3`,lightgrey:`#D3D3D3`,thistle:`#D8BFD8`,orchid:`#DA70D6`,goldenrod:`#DAA520`,palevioletred:`#DB7093`,crimson:`#DC143C`,gainsboro:`#DCDCDC`,plum:`#DDA0DD`,burlywood:`#DEB887`,lightcyan:`#E0FFFF`,lavender:`#E6E6FA`,darksalmon:`#E9967A`,violet:`#EE82EE`,palegoldenrod:`#EEE8AA`,lightcoral:`#F08080`,khaki:`#F0E68C`,aliceblue:`#F0F8FF`,honeydew:`#F0FFF0`,azure:`#F0FFFF`,sandybrown:`#F4A460`,wheat:`#F5DEB3`,beige:`#F5F5DC`,whitesmoke:`#F5F5F5`,mintcream:`#F5FFFA`,ghostwhite:`#F8F8FF`,salmon:`#FA8072`,antiquewhite:`#FAEBD7`,linen:`#FAF0E6`,lightgoldenrodyellow:`#FAFAD2`,oldlace:`#FDF5E6`,magenta:`#FF00FF`,deeppink:`#FF1493`,orangered:`#FF4500`,tomato:`#FF6347`,hotpink:`#FF69B4`,coral:`#FF7F50`,darkorange:`#FF8C00`,lightsalmon:`#FFA07A`,orange:`#FFA500`,lightpink:`#FFB6C1`,pink:`#FFC0CB`,gold:`#FFD700`,peachpuff:`#FFDAB9`,navajowhite:`#FFDEAD`,moccasin:`#FFE4B5`,bisque:`#FFE4C4`,mistyrose:`#FFE4E1`,blanchedalmond:`#FFEBCD`,papayawhip:`#FFEFD5`,lavenderblush:`#FFF0F5`,seashell:`#FFF5EE`,cornsilk:`#FFF8DC`,lemonchiffon:`#FFFACD`,floralwhite:`#FFFAF0`,snow:`#FFFAFA`,lightyellow:`#FFFFE0`,ivory:`#FFFFF0`},Xt=new Int8Array(4),Zt=new Int32Array(Xt.buffer,0,1),Qt=new Float32Array(Xt.buffer,0,1),$t=/^\s*rgba?\s*\(/,en=/^\s*rgba?\s*\(\s*([0-9]*)\s*,\s*([0-9]*)\s*,\s*([0-9]*)(?:\s*,\s*(.*)?)?\)\s*$/;function tn(e){var t=0,n=0,r=0,i=1,a=e.toLowerCase();if(a===`transparent`)return{r:0,g:0,b:0,a:0};if(a in Yt)return tn(Yt[a]);if(e[0]===`#`)e.length===4?(t=parseInt(e.charAt(1)+e.charAt(1),16),n=parseInt(e.charAt(2)+e.charAt(2),16),r=parseInt(e.charAt(3)+e.charAt(3),16)):(t=parseInt(e.charAt(1)+e.charAt(2),16),n=parseInt(e.charAt(3)+e.charAt(4),16),r=parseInt(e.charAt(5)+e.charAt(6),16)),e.length===9&&(i=parseInt(e.charAt(7)+e.charAt(8),16)/255);else if($t.test(e)){var o=e.match(en);o&&(t=+o[1],n=+o[2],r=+o[3],o[4]&&(i=+o[4]))}return{r:t,g:n,b:r,a:i}}function nn(e){var t=arguments.length>1&&arguments[1]!==void 0&&arguments[1],n=tn(e),r=n.r,i=n.g,a=n.b,o=n.a;return t?[r/255*o,i/255*o,a/255*o,o]:[r/255,i/255,a/255,o]}var rn={};for(var an in Yt)rn[an]=sn(Yt[an]),rn[Yt[an]]=rn[an];function on(e,t,n,r,i){return Zt[0]=r<<24|n<<16|t<<8|e,i&&(Zt[0]&=4278190079),Qt[0]}function sn(e){if(e=e.toLowerCase(),rn[e]!==void 0)return rn[e];var t=tn(e),n=t.r,r=t.g,i=t.b,a=t.a;a=a*255|0;var o=on(n,r,i,a,!0);return rn[e]=o,o}function cn(e,t){Qt[0]=sn(e);var n=Zt[0];return t&&(n|=16777216),[n&255,n>>8&255,n>>16&255,n>>24&255]}function ln(e){var t=e>>>8&255,n=e>>>16&255,r=e>>>24&255;return((e&255)<<24|r<<16|n<<8|t)>>>0}function un(e,t,n,r){return(n<<24|t<<16|e<<8|r)>>>0}function dn(e,t,n,r,i,a){var o=V(Jt(e,n,r,i,a),2),s=o[0],c=o[1],l=new Uint8Array(4);e.bindFramebuffer(e.FRAMEBUFFER,t),e.readPixels(s,c,1,1,e.RGBA,e.UNSIGNED_BYTE,l);var u=V(l,4);return[u[0],u[1],u[2],u[3]]}function fn(e){var t=tn(e),n=t.r,r=t.g,i=t.b,a=t.a;return`vec4(${(n/255).toFixed(6)}, ${(r/255).toFixed(6)}, ${(i/255).toFixed(6)}, ${a.toFixed(6)})`}function pn(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function mn(e){var t=pn(e,`string`);return typeof t==`symbol`?t:t+``}function U(e,t,n){return(t=mn(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function hn(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function W(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?hn(Object(n),!0).forEach(function(t){U(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):hn(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function G(e,t){if(!(e instanceof t))throw TypeError(`Cannot call a class as a function`)}function gn(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,`value`in r&&(r.writable=!0),Object.defineProperty(e,mn(r.key),r)}}function K(e,t,n){return t&&gn(e.prototype,t),n&&gn(e,n),Object.defineProperty(e,"prototype",{writable:!1}),e}function _n(e){return _n=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},_n(e)}function vn(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(vn=function(){return!!e})()}function yn(e){if(e===void 0)throw ReferenceError(`this hasn't been initialised - super() hasn't been called`);return e}function bn(e,t){if(t&&(typeof t==`object`||typeof t==`function`))return t;if(t!==void 0)throw TypeError(`Derived constructors may only return object or undefined`);return yn(e)}function q(e,t,n){return t=_n(t),bn(e,vn()?Reflect.construct(t,n||[],_n(e).constructor):t.apply(e,n))}function xn(e,t){return xn=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},xn(e,t)}function J(e,t){if(typeof t!=`function`&&t!==null)throw TypeError(`Super expression must either be null or a function`);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&xn(e,t)}function Sn(e){if(Array.isArray(e))return Nt(e)}function Cn(e){if(typeof Symbol<`u`&&e[Symbol.iterator]!=null||e[`@@iterator`]!=null)return Array.from(e)}function wn(){throw TypeError(`Invalid attempt to spread non-iterable instance.
|
|
4
|
+
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function Y(e){return Sn(e)||Cn(e)||Pt(e)||wn()}function X(e){"@babel/helpers - typeof";return X=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},X(e)}function Tn(e){return X(e)===`object`&&e!==null&&`attribute`in e}function En(){return{name:`circle`,glsl:`
|
|
5
|
+
float sdf_circle(vec2 uv, float size) {
|
|
6
|
+
return length(uv) - size;
|
|
7
|
+
}
|
|
8
|
+
`,uniforms:[]}}function Dn(e){var t=WebGL2RenderingContext.UNSIGNED_BYTE,n=e?.color??{attribute:`color`};return Tn(n)?{name:`fill`,uniforms:[],attributes:[{name:`fillColor`,size:4,type:t,normalized:!0,source:n.attribute}],glsl:`
|
|
9
|
+
vec4 layer_fill(vec4 v_fillColor) {
|
|
10
|
+
return v_fillColor;
|
|
11
|
+
}
|
|
12
|
+
`}:{name:`fill`,uniforms:[],attributes:[],glsl:`
|
|
13
|
+
vec4 layer_fill() {
|
|
14
|
+
return ${fn(n)};
|
|
15
|
+
}
|
|
16
|
+
`}}function On(e,t){if(typeof e==`string`){var n=V(nn(e).map(function(e){return e.toFixed(6)}),4);return{glsl:`vec4(${n[0]}, ${n[1]}, ${n[2]}, ${n[3]})`,attributes:[],needsNodeColors:!1}}if(`node`in e&&e.node)return{glsl:e.node===`source`?`v_sourceColor`:`v_targetColor`,attributes:[],needsNodeColors:!0};var r=e;return{glsl:`v_${t}`,attributes:[{name:`a_${t}`,size:4,type:WebGL2RenderingContext.UNSIGNED_BYTE,normalized:!0,source:r.attribute,defaultValue:r.default}],needsNodeColors:!1}}function kn(e){var t=e?.color;if(t===void 0)return{name:`plain`,glsl:`
|
|
17
|
+
// Plain solid color layer
|
|
18
|
+
vec4 layer_plain(EdgeContext ctx) {
|
|
19
|
+
return v_color;
|
|
20
|
+
}
|
|
21
|
+
`,uniforms:[],attributes:[]};var n=On(t,`plainColor`);return{name:`plain`,glsl:`
|
|
22
|
+
// Plain solid color layer
|
|
23
|
+
vec4 layer_plain(EdgeContext ctx) {
|
|
24
|
+
return ${n.glsl};
|
|
25
|
+
}
|
|
26
|
+
`,uniforms:[],attributes:n.attributes,needsNodeColors:n.needsNodeColors}}function An(){return{name:`straight`,segments:1,minBodyLengthRatio:0,linearParameterization:!0,glsl:`
|
|
27
|
+
// Position at parameter t ∈ [0, 1]
|
|
28
|
+
vec2 path_straight_position(float t, vec2 source, vec2 target) {
|
|
29
|
+
return mix(source, target, t);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Total length of the path (analytical - more efficient than sampling)
|
|
33
|
+
float path_straight_length(vec2 source, vec2 target) {
|
|
34
|
+
return length(target - source);
|
|
35
|
+
}
|
|
36
|
+
`,uniforms:[],attributes:[]}}function jn(e){var t=(e??{}).segments;return{name:`loop`,segments:t===void 0?32:t,glsl:`
|
|
37
|
+
const float LOOP_PI = 3.141592653589793;
|
|
38
|
+
|
|
39
|
+
float loopWorldRadius() {
|
|
40
|
+
float nodeWorldRadius = v_sourceNodeSize * u_correctionRatio / u_sizeRatio;
|
|
41
|
+
return max(v_loopRadius * nodeWorldRadius, 0.001);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Cubic Bézier with P0 = P3 = source.
|
|
45
|
+
// Control points extend outward orthogonal to the node surface at exit/entry angles.
|
|
46
|
+
vec2 path_loop_position(float t, vec2 source, vec2 target) {
|
|
47
|
+
float R = loopWorldRadius();
|
|
48
|
+
float angle = v_loopAngle + (v_loopFixedOrientation > 0.5 ? u_cameraAngle : 0.0);
|
|
49
|
+
float halfSpread = v_loopSpread * 0.5;
|
|
50
|
+
|
|
51
|
+
float exitAngle = angle - halfSpread;
|
|
52
|
+
float entryAngle = angle + halfSpread;
|
|
53
|
+
|
|
54
|
+
// Control point distance: at t=0.5 the Bézier reaches 0.75 * cpDist * cos(halfSpread)
|
|
55
|
+
// from source. Solve for cpDist so the loop tip reaches exactly R.
|
|
56
|
+
float cpDist = R / (0.75 * cos(halfSpread));
|
|
57
|
+
|
|
58
|
+
vec2 cp1 = source + cpDist * vec2(cos(exitAngle), sin(exitAngle));
|
|
59
|
+
vec2 cp2 = source + cpDist * vec2(cos(entryAngle), sin(entryAngle));
|
|
60
|
+
|
|
61
|
+
float u = 1.0 - t;
|
|
62
|
+
vec2 d1 = cp1 - source;
|
|
63
|
+
vec2 d2 = cp2 - source;
|
|
64
|
+
return source + 3.0 * t * u * (u * d1 + t * d2);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Approximate arc length via chord sampling
|
|
68
|
+
float path_loop_length(vec2 source, vec2 target) {
|
|
69
|
+
float len = 0.0;
|
|
70
|
+
vec2 prev = path_loop_position(0.0, source, target);
|
|
71
|
+
const int STEPS = 16;
|
|
72
|
+
for (int i = 1; i <= STEPS; i++) {
|
|
73
|
+
float t = float(i) / float(STEPS);
|
|
74
|
+
vec2 cur = path_loop_position(t, source, target);
|
|
75
|
+
len += length(cur - prev);
|
|
76
|
+
prev = cur;
|
|
77
|
+
}
|
|
78
|
+
return len;
|
|
79
|
+
}
|
|
80
|
+
`,needsNodeSize:!0,uniforms:[],attributes:[{name:`loopRadius`,size:1,type:WebGL2RenderingContext.FLOAT},{name:`loopAngle`,size:1,type:WebGL2RenderingContext.FLOAT},{name:`loopSpread`,size:1,type:WebGL2RenderingContext.FLOAT},{name:`loopFixedOrientation`,size:1,type:WebGL2RenderingContext.FLOAT}],variables:{loopRadius:{type:`number`,default:4},loopAngle:{type:`number`,default:Math.PI/4},loopSpread:{type:`number`,default:80*Math.PI/180},loopFixedOrientation:{type:`number`,default:0}},spread:{variable:`loopRadius`,compute:function(e){return e+4}}}}function Mn(e){return X(e)===`object`&&`glsl`in e&&!(`attributes`in e)}function Nn(e){return X(e)===`object`&&`glsl`in e&&!(`attributes`in e)}var Pn={shapes:[En()],variables:{},layers:[Dn()],label:{},backdrop:{},labelAttachments:{}},Fn={paths:[An(),jn()],extremities:[],variables:{},layers:[kn()],defaultHead:`none`,defaultTail:`none`,label:{}},In=[`nodes`,`topNodes`],Ln=[`edges`,`topEdges`],Rn=[].concat(Ln,In),zn={nodes:Pn,edges:Fn,depthLayers:Y(Rn)},Bn={linear:function(e){return e},quadraticIn:function(e){return e*e},quadraticOut:function(e){return e*(2-e)},quadraticInOut:function(e){return(e*=2)<1?.5*e*e:-.5*(--e*(e-2)-1)},cubicIn:function(e){return e*e*e},cubicOut:function(e){return--e*e*e+1},cubicInOut:function(e){return(e*=2)<1?.5*e*e*e:.5*((e-=2)*e*e+2)},exponentialIn:function(e){return e===0?0:2**(10*(e-1))},exponentialOut:function(e){return e===1?1:1-2**(-10*e)},exponentialInOut:function(e){return e===0?0:e===1?1:e<.5?2**(10*(2*e-1))/2:(2-2**(-10*(2*e-1)))/2}};function Vn(e){return e?typeof e==`function`?e:Bn[e]:Bn.linear}function Hn(e){return X(e)===`object`&&e!==null&&`attribute`in e}function Un(e){return typeof e==`function`}function Wn(e){return X(e)===`object`&&e!==null&&`when`in e&&typeof e.when==`function`&&`then`in e}function Gn(e){return X(e)===`object`&&e!==null&&`whenState`in e&&`then`in e}function Kn(e){return X(e)===`object`&&e!==null&&`whenData`in e&&`then`in e}var qn={isHovered:!1,isLabelHovered:!1,isHidden:!1,isHighlighted:!1,isDragged:!1},Jn={isHovered:!1,isLabelHovered:!1,isHidden:!1,isHighlighted:!1,parallelIndex:0,parallelCount:1},Yn={isIdle:!0,isPanning:!1,isZooming:!1,isDragging:!1,hasHovered:!1,hasHighlighted:!1};function Xn(e){return W(W({},qn),e)}function Zn(e){return W(W({},Jn),e)}function Qn(e){return W(W({},Yn),e)}var $n={nodes:W(W({},{x:{attribute:`x`},y:{attribute:`y`},size:{whenState:`isHovered`,then:{attribute:`size`,defaultValue:12},else:{attribute:`size`,defaultValue:10}},color:{attribute:`color`,defaultValue:`#666`},label:{attribute:`label`},visibility:{whenState:`isHidden`,then:`hidden`,else:`visible`},labelVisibility:{whenState:`isHovered`,then:`visible`,else:`auto`},backdropVisibility:{whenState:`isHovered`,then:`visible`,else:`hidden`},backdropColor:`#ffffff`,backdropShadowColor:`rgba(0, 0, 0, 0.5)`,backdropShadowBlur:12,backdropPadding:6}),{},{depth:{whenState:`isHovered`,then:`topNodes`,else:`nodes`}}),edges:W(W({},{size:{attribute:`size`,defaultValue:1},color:{attribute:`color`,defaultValue:`#ccc`},label:{attribute:`label`},visibility:{whenState:`isHidden`,then:`hidden`,else:`visible`}}),{},{depth:{whenState:[`isHighlighted`,`isHovered`],then:`topEdges`,else:`edges`}})};function er(e){return`min`in e||`max`in e||`minValue`in e||`maxValue`in e||`easing`in e}function tr(e){return`dict`in e}function nr(e,t){return typeof e==`string`?t[e]===!0:Array.isArray(e)?e.every(function(e){return t[e]===!0}):X(e)===`object`&&e!==null&&Object.entries(e).every(function(e){var n=V(e,2),r=n[0],i=n[1];return t[r]===i})}function rr(e,t){var n=t[e.attribute];return n===void 0?e.defaultValue:n}function ir(e,t,n){var r=t[e.attribute];if(r===void 0)return e.defaultValue;var i=Number(r);if(isNaN(i))return e.defaultValue;if(e.min===void 0&&e.max===void 0)return i;var a=e.minValue??i,o=e.maxValue??i;if(o===a)return e.min??i;var s=(i-a)/(o-a);s=Math.max(0,Math.min(1,s)),s=Vn(e.easing)(s);var c=e.min??0,l=e.max??1;return c+s*(l-c)}function ar(e,t){var n=t[e.attribute];if(n===void 0)return e.defaultValue;var r=String(n);return r in e.dict?e.dict[r]:e.defaultValue}function or(e,t,n){return tr(e)?ar(e,t):er(e)?ir(e,t):rr(e,t)}function sr(e,t){return typeof e==`string`?!!t[e]:Array.isArray(e)?e.every(function(e){return!!t[e]}):X(e)===`object`&&e!==null&&Object.entries(e).every(function(e){var n=V(e,2),r=n[0],i=n[1];return t[r]===i})}function cr(e,t,n,r,i,a){if(e==null)return a;if(X(e)!==`object`&&typeof e!=`function`)return e;if(Wn(e)){var o=e.when(t,n,r,i)?e.then:e.else;return o===void 0?a:cr(o,t,n,r,i,a)}if(Gn(e)){var s=nr(e.whenState,n)?e.then:e.else;return s===void 0?a:cr(s,t,n,r,i,a)}if(Kn(e)){var c=sr(e.whenData,t)?e.then:e.else;return c===void 0?a:cr(c,t,n,r,i,a)}return Un(e)?e(t,n,r,i)??a:Hn(e)?or(e,t)??a:e}function lr(e){return e==null?`static`:Wn(e)?`graph-state`:Gn(e)?ur(`item-state`,ur(lr(e.then),e.else===void 0?`static`:lr(e.else))):Kn(e)?ur(lr(e.then),e.else===void 0?`static`:lr(e.else)):Un(e)?`graph-state`:(Hn(e),`static`)}function ur(e,t){return e===`graph-state`||t===`graph-state`?`graph-state`:e===`item-state`||t===`item-state`?`item-state`:`static`}function dr(e){if(!e)return{dependency:`static`,xAttribute:null,yAttribute:null};var t=Array.isArray(e)?e:[e],n=`static`,r=null,i=null,a=H(t),o;try{for(a.s();!(o=a.n()).done;){var s=o.value;if(`matchData`in s&&`cases`in s)for(var c=s.cases,l=0,u=Object.values(c);l<u.length;l++)for(var d=u[l],f=0,p=Object.values(d);f<p.length;f++){var m=p[f];n=ur(n,lr(m))}else if(`matchState`in s&&`cases`in s){n=ur(n,`item-state`);for(var h=s.cases,g=0,_=Object.values(h);g<_.length;g++)for(var v=_[g],y=0,b=Object.values(v);y<b.length;y++){var x=b[y];n=ur(n,lr(x))}}else if(`when`in s&&`then`in s)n=`graph-state`;else if(`whenState`in s){n=ur(n,`item-state`);var S=s.then;if(S&&X(S)===`object`)for(var C=0,w=Object.values(S);C<w.length;C++){var T=w[C];n=ur(n,lr(T))}var E=s.else;if(E&&X(E)===`object`)for(var D=0,O=Object.values(E);D<O.length;D++){var k=O[D];n=ur(n,lr(k))}}else if(`whenData`in s){var A=s.then;if(A&&X(A)===`object`)for(var j=0,M=Object.values(A);j<M.length;j++){var N=M[j];n=ur(n,lr(N))}var P=s.else;if(P&&X(P)===`object`)for(var F=0,I=Object.values(P);F<I.length;F++){var L=I[F];n=ur(n,lr(L))}}else for(var R=0,z=Object.entries(s);R<z.length;R++){var ee=V(z[R],2),te=ee[0],ne=ee[1];if(!mr.has(te)&&(n=ur(n,lr(ne)),(te===`x`||te===`y`)&&Hn(ne))){var re=ne.attribute;te===`x`&&!r&&(r=re),te===`y`&&!i&&(i=re)}}}}catch(e){a.e(e)}finally{a.f()}return{dependency:n,xAttribute:r,yAttribute:i}}var fr={size:10,color:`#666`,opacity:1,shape:`circle`,rotationAlignment:`viewport`,labelRotationAlignment:`viewport`,visibility:`visible`,depth:`nodes`,zIndex:0,label:``,labelColor:`#000`,labelSize:12,labelFont:`sans-serif`,labelVisibility:`auto`,labelPosition:`right`,labelAngle:0,labelDepth:`nodes`,backdropVisibility:`hidden`,backdropColor:`transparent`,backdropShadowColor:`transparent`,backdropShadowBlur:0,backdropPadding:0,backdropBorderColor:`transparent`,backdropBorderWidth:0,backdropCornerRadius:0,backdropLabelPadding:-1,backdropArea:`both`,labelAttachment:null,labelAttachmentPlacement:`below`},pr={size:1,color:`#ccc`,opacity:1,path:`straight`,selfLoopPath:`loop`,parallelSpread:.25,tail:`none`,head:`none`,visibility:`visible`,depth:`edges`,zIndex:0,label:``,labelColor:`#666`,labelVisibility:`auto`,labelDepth:`edges`},mr=new Set([`when`,`whenState`,`whenData`,`then`,`else`]),hr=Object.keys(fr),gr=Object.values(fr),_r=Object.keys(pr),vr=Object.values(pr);function yr(e,t,n,r,i,a,o){for(var s in t)if(!mr.has(s)){var c=e[s]??o[s];e[s]=cr(t[s],n,r,i,a,c)}`depth`in t&&!(`labelDepth`in t)&&(e.labelDepth=e.depth)}function br(e,t,n,r,i,a,o){var s=H(t),c;try{for(s.s();!(c=s.n()).done;){var l=c.value;if(`matchData`in l&&`cases`in l){var u=String(n[l.matchData]??``),d=l.cases;u in d&&yr(e,d[u],n,r,i,a,o)}else if(`matchState`in l&&`cases`in l){var f=String(r[l.matchState]??``),p=l.cases;f in p&&yr(e,p[f],n,r,i,a,o)}else if(`when`in l&&`then`in l){var m=l.when;if(!m(n,r,i,a))continue;yr(e,l.then,n,r,i,a,o)}else if(`whenState`in l&&`then`in l){if(!nr(l.whenState,r))continue;yr(e,l.then,n,r,i,a,o)}else if(`whenData`in l&&`then`in l){if(!sr(l.whenData,n))continue;yr(e,l.then,n,r,i,a,o)}else yr(e,l,n,r,i,a,o)}}catch(e){s.e(e)}finally{s.f()}}function xr(e,t,n,r,i,a){for(var o=a||{},s=o,c=0,l=hr.length;c<l;c++)s[hr[c]]=gr[c];return s.x=void 0,s.y=void 0,s.labelBackgroundColor=void 0,s.labelBackgroundPadding=void 0,s.labelCursor=void 0,e?(br(s,Array.isArray(e)?e:[e],t,n,r,i,fr),o):(s.x=t.x??0,s.y=t.y??0,o.size=t.size??10,o.color=t.color??`#666`,o.label=t.label??``,o)}function Sr(e,t,n,r,i,a){for(var o=a||{},s=o,c=0,l=_r.length;c<l;c++)s[_r[c]]=vr[c];return e?(br(s,Array.isArray(e)?e:[e],t,n,r,i,pr),typeof s.labelPosition==`number`&&(s.labelPosition=void 0),o):(o.size=t.size??1,o.color=t.color??`#ccc`,o.label=t.label??``,o)}function Cr(e,t,n){if(e==null)return n;if(typeof e==`function`)return e(t)??n;if(X(e)===`object`&&`when`in e){var r=e,i=r.when(t)?r.then:r.else;return i===void 0?n:typeof i==`function`?i(t)??n:i??n}if(X(e)===`object`&&`whenState`in e){var a=e,o=nr(a.whenState,t)?a.then:a.else;return o===void 0?n:typeof o==`function`?o(t)??n:o??n}return e??n}function wr(e,t){var n={};if(!e)return n;var r=H(Array.isArray(e)?e:[e]),i;try{for(r.s();!(i=r.n()).done;){var a=i.value;if(`when`in a&&`then`in a){var o=a.when(t)?a.then:a.else;o&&X(o)===`object`&&Tr(n,o,t)}else if(`whenState`in a&&`then`in a){var s=nr(a.whenState,t)?a.then:a.else;s&&X(s)===`object`&&Tr(n,s,t)}else Tr(n,a,t)}}catch(e){r.e(e)}finally{r.f()}return n}function Tr(e,t,n){for(var r=0,i=Object.entries(t);r<i.length;r++){var a=V(i[r],2),o=a[0],s=a[1];mr.has(o)||(e[o]=Cr(s,n))}}var Er=function(e){function t(){var e;return G(this,t),e=q(this,t),e.rawEmitter=e,e}return J(t,e),K(t)}(b.EventEmitter),Dr=zn;function Or(e,t){var n=t.size;if(n!==0){var r=e.length;e.length+=n;var i=0;t.forEach(function(t){e[r+i]=t,i++})}}function kr(e){e||={};for(var t=0,n=arguments.length<=1?0:arguments.length-1;t<n;t++){var r=t+1<1||arguments.length<=t+1?void 0:arguments[t+1];r&&Object.assign(e,r)}return e}function Ar(e,t){for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)&&t[n]!==e[n])return!0;return!1}function jr(e,t){var n=e,r=t;for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)&&n[i]!==r[i])return!1;for(var a in r)if(Object.prototype.hasOwnProperty.call(r,a)&&r[a]!==n[a])return!1;return!0}function Mr(e,t,n){n?e.add(t):e.delete(t)}var Nr=y(Dt()),Pr={easing:`quadraticInOut`,duration:150};function Fr(e){return e.labelVisibility===`visible`&&e.visibility!==`hidden`}function Ir(e){return e.backdropVisibility===`visible`&&e.visibility!==`hidden`}function Lr(e){return[+(e.rotationAlignment===`graph`),+(e.labelRotationAlignment===`graph`)]}function Rr(e,t,n){var r=e[t];if(r)for(var i=0;i<r.length;i++){var a=r[i];if(!(n<a.offset||n>=a.offset+a.count)){if(a.count===1)r.splice(i,1);else if(n===a.offset)a.offset++,a.count--;else if(n===a.offset+a.count-1)a.count--;else{var o=n+1,s=a.offset+a.count-o;a.count=n-a.offset,r.splice(i+1,0,{offset:o,count:s})}return}}}function zr(e,t,n){if(!e[t])e[t]=[{offset:n,count:1}];else{for(var r=e[t],i=r.length,a=0;a<r.length;a++)if(n<r[a].offset){i=a;break}var o=i>0?r[i-1]:null,s=i<r.length?r[i]:null,c=o&&o.offset+o.count===n,l=s&&n+1===s.offset;c&&l?(o.count+=1+s.count,r.splice(i,1)):c?o.count++:l?(s.offset--,s.count++):r.splice(i,0,{offset:n,count:1})}}function Br(e){if(!(0,Nr.default)(e))throw Error(`Sigma: invalid graph instance.`)}function Vr(e){var t=V(e.x,2),n=t[0],r=t[1],i=V(e.y,2),a=i[0],o=i[1],s=Math.max(r-n,o-a),c=(r+n)/2,l=(o+a)/2;(s===0||Math.abs(s)===1/0||isNaN(s))&&(s=1),isNaN(c)&&(c=0),isNaN(l)&&(l=0);var u=function(e){return{x:.5+(e.x-c)/s,y:.5+(e.y-l)/s}};return u.applyTo=function(e){e.x=.5+(e.x-c)/s,e.y=.5+(e.y-l)/s},u.inverse=function(e){return{x:c+s*(e.x-.5),y:l+s*(e.y-.5)}},u.ratio=s,u}var Hr={hideEdgesOnMove:!1,hideLabelsOnMove:!1,renderLabels:!0,renderEdgeLabels:!1,edgeLabelAnchors:`nodeLabels`,enableEdgeEvents:!1,nodeLabelEvents:!1,edgeLabelEvents:!1,pickingDownSizingRatio:2,nodePickingPadding:0,edgePickingPadding:4,labelPickingPadding:10,stagePadding:30,minEdgeThickness:1.7,antiAliasingFeather:1,antialiasEdges:!0,antialiasNodes:!0,dragTimeout:100,draggedEventsTolerance:3,inertiaDuration:200,inertiaRatio:3,zoomDuration:250,zoomingRatio:1.7,doubleClickTimeout:300,doubleClickZoomingRatio:2.2,doubleClickZoomingDuration:200,tapMoveTolerance:10,zoomToSizeRatioFunction:Math.sqrt,itemSizesReference:`positions`,autoRescale:!0,autoRescaleContent:`positions`,enableNodeDrag:!1,getDraggedNodes:function(e){return[e]},dragPositionToAttributes:null,labelDensity:1,labelGridCellSize:100,labelRenderedSizeThreshold:6,labelPixelSnapping:!0,minCameraRatio:null,maxCameraRatio:null,enableCameraZooming:!0,enableCameraPanning:!0,enableCameraRotation:!0,enableCameraMouseRotation:!0,cameraPanBoundaries:null,gestureTarget:`graph`,sharedGestureWheelMessage:`Use Ctrl + scroll to zoom the graph`,sharedGestureAppleWheelMessage:`Use ⌘ + scroll to zoom the graph`,sharedGestureTouchMessage:`Use two fingers to move the graph`,allowInvalidContainer:!1,DEBUG_displayPickingLayer:!1,DEBUG_logShaders:!1,DEBUG_logRenderStats:!1,DEBUG_gpuTimerQueries:!1};function Ur(e){if(typeof e.labelDensity!=`number`||e.labelDensity<0)throw Error("Settings: invalid `labelDensity`. Expecting a positive number.");var t=e.minCameraRatio,n=e.maxCameraRatio;if(typeof t==`number`&&typeof n==`number`&&n<t)throw Error("Settings: invalid camera ratio boundaries. Expecting `maxCameraRatio` to be greater than `minCameraRatio`.")}function Wr(e){return kr({},Hr,e)}var Gr=new Set([`italic`,`oblique`]),Kr=new Set([`bold`,`bolder`,`lighter`]);function qr(e){for(var t=`normal`,n=`normal`,r=e.trim(),i=r.split(/\s+/),a=0,o=0;o<i.length;o++){var s=i[o].toLowerCase();if(Gr.has(s))n=s,a=o+1;else if(Kr.has(s)||/^\d{3}$/.test(s))t=s,a=o+1;else if(s===`normal`)a=o+1;else break}return{family:i.slice(a).join(` `)||r,weight:t,style:n}}function Jr(e,t,n){var r=document.createElement(e);if(t)for(var i in t)r.style[i]=t[i];if(n)for(var a in n)r.setAttribute(a,n[a]);return r}function Yr(){return window.devicePixelRatio===void 0?1:window.devicePixelRatio}function Xr(e){var t=e.type===WebGL2RenderingContext.FLOAT&&!e.normalized,n=e.type===WebGL2RenderingContext.UNSIGNED_BYTE&&e.size===4&&e.normalized;if(!t&&!n)throw Error(`Attribute "${e.name}" is invalid: only non-normalized FLOAT and normalized UNSIGNED_BYTE with size 4 are supported.`);return e.normalized?1:e.size}function Zr(e){var t=0;return e.forEach(function(e){return t+=Xr(e)}),t}function Qr(e,t,n){var r=e===`VERTEX`?t.VERTEX_SHADER:t.FRAGMENT_SHADER,i=t.createShader(r);if(i===null)throw Error(`loadShader: error while creating the shader`);if(t.shaderSource(i,n),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS)){var a=t.getShaderInfoLog(i);throw t.deleteShader(i),Error(`loadShader: error while compiling the shader:
|
|
81
|
+
${a}
|
|
82
|
+
${n}`)}return i}function $r(e,t){return Qr(`VERTEX`,e,t)}function ei(e,t){return Qr(`FRAGMENT`,e,t)}function ti(e,t){var n=e.createProgram();if(n===null)throw Error(`loadProgram: error while creating the program.`);for(var r=0,i=t.length;r<i;r++)e.attachShader(n,t[r]);if(e.linkProgram(n),!e.getProgramParameter(n,e.LINK_STATUS)){var a=e.getProgramInfoLog(n);throw e.deleteProgram(n),Error(`loadProgram: error while linking the program: ${a}`)}return n}function ni(e){var t=e.gl,n=e.buffer,r=e.program,i=e.vertexShader,a=e.fragmentShader;t.deleteShader(i),t.deleteShader(a),t.deleteProgram(r),t.deleteBuffer(n)}function Z(e){return e%1==0?e.toFixed(1):e.toString()}var ri=new Map,ii=new Map,ai=0;function oi(e,t){var n,r=(n=e.variables)==null||(n=n[t.source||t.name.replace(/^a_/,``)])==null?void 0:n.default;return Z(typeof r==`number`?r:typeof t.defaultValue==`number`?t.defaultValue:0)}function si(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:function(e){return`v_${e.name.replace(/^a_/,``)}`},i=[t,n].concat(Y(e.uniforms.filter(function(e){return e.type===`float`}).map(function(e){return Z(e.value??0)})),Y((e.attributes??[]).map(r)));return`sdf_${e.name}(${i.join(`, `)})`}function ci(e){var t=e.name,n=e.uniforms.filter(function(e){return e.type===`float`&&e.value!==void 0&&e.value!==0}).map(function(e){return`${e.name.replace(`u_`,``)}=${e.value}`}).sort(),r=(e.attributes??[]).map(function(t){return`${t.name}@${t.source??``}=${oi(e,t)}`}),i=[].concat(Y(n),Y(r));return i.length>0&&(t+=`#`+i.join(`#`)),t}function li(e){var t=ci(e);if(!ri.has(t)){var n={},r=H(e.uniforms),i;try{for(r.s();!(i=r.n()).done;){var a=i.value;a.type===`float`&&a.value!==void 0&&(n[a.name]=a.value)}}catch(e){r.e(e)}finally{r.f()}ri.set(t,{shape:e,uniformValues:n,slug:t}),ii.set(t,ai++)}return t}function ui(e){return ii.get(e)??-1}function di(e){var t=[],n=new Set,r=new Set,i=/mat2 rotate2D\(float angle\)\s*\{[^}]+\}/,a=H(e),o;try{for(a.s();!(o=a.n()).done;){var s=o.value;if(!r.has(s.name)){r.add(s.name);var c=s.glsl;i.test(c)&&(n.has(`rotate2D`)?c=c.replace(i,``):n.add(`rotate2D`)),t.push(c)}}}catch(e){a.e(e)}finally{a.f()}return t.join(`
|
|
83
|
+
`)}function fi(){return di(Array.from(ri.values()).map(function(e){return e.shape}))}function pi(e){var t=Array.from(ri.entries());return t.length===0?`
|
|
84
|
+
float querySDF(int shapeId, vec2 uv, float size) {
|
|
85
|
+
return length(uv) - size;
|
|
86
|
+
}
|
|
87
|
+
`:`
|
|
88
|
+
float querySDF(int shapeId, vec2 uv, float size) {
|
|
89
|
+
switch (shapeId) {
|
|
90
|
+
${t.map(function(t,n){var r=V(t,2),i=r[0],a=r[1].shape;return` case ${n}: return ${si(a,`uv`,`size`,function(t){var n=t.name.replace(/^a_/,``);return e!=null&&e.has(n)?`g_${n}`:oi(a,t)})}; // ${i}`}).join(`
|
|
91
|
+
`)}
|
|
92
|
+
default: return length(uv) - size;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`}function mi(e){return di(e)}function hi(e){return Y(new Map(e.flatMap(function(e){return e.uniforms}).map(function(e){return[e.name,e]})).values())}function gi(e,t){if(e.length===0)return`
|
|
96
|
+
void queryNodeSDF(int shapeId, vec2 uv, float size) {
|
|
97
|
+
context.sdf = length(uv) - size;
|
|
98
|
+
context.inradiusFactor = 1.0;
|
|
99
|
+
}
|
|
100
|
+
`;var n=function(e){return si(e,`uv`,`size`)},r=function(e){return e.inradiusFactorGLSL??Z(e.inradiusFactor??1)};if(e.length===1){var i=e[0];return`
|
|
101
|
+
void queryNodeSDF(int shapeId, vec2 uv, float size) {
|
|
102
|
+
context.sdf = ${n(i)};
|
|
103
|
+
context.inradiusFactor = ${r(i)};
|
|
104
|
+
}
|
|
105
|
+
`}var a=e.map(function(e,t){return` case ${t}: // ${e.name}
|
|
106
|
+
context.sdf = ${n(e)};
|
|
107
|
+
context.inradiusFactor = ${r(e)};
|
|
108
|
+
break;`}).join(`
|
|
109
|
+
`),o=e[0],s=``,c=`shapeId`;return t&&t.length>1&&(s=`
|
|
110
|
+
int globalToLocalShapeId(int globalId) {
|
|
111
|
+
switch (globalId) {
|
|
112
|
+
${t.map(function(t,n){return` case ${t}: return ${n}; // ${e[n].name}`}).join(`
|
|
113
|
+
`)}
|
|
114
|
+
default: return 0;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
`,c=`globalToLocalShapeId(shapeId)`),`${s}
|
|
118
|
+
void queryNodeSDF(int shapeId, vec2 uv, float size) {
|
|
119
|
+
switch (${c}) {
|
|
120
|
+
${a}
|
|
121
|
+
default:
|
|
122
|
+
context.sdf = ${n(o)};
|
|
123
|
+
context.inradiusFactor = ${r(o)};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
`}var _i={right:0,left:1,above:2,below:3,over:4},vi=`
|
|
127
|
+
float matrixScaleX = length(vec2(u_matrix[0][0], u_matrix[1][0]));
|
|
128
|
+
float nodeRadiusGraphSpace = nodeSize * u_correctionRatio / u_sizeRatio * 2.0;
|
|
129
|
+
float nodeRadiusNDC = nodeRadiusGraphSpace * matrixScaleX;
|
|
130
|
+
float nodeRadiusPixels = nodeRadiusNDC * u_resolution.x / 2.0;
|
|
131
|
+
`,yi=`
|
|
132
|
+
mat2 rotate2D(float angle) {
|
|
133
|
+
float c = cos(angle);
|
|
134
|
+
float s = sin(angle);
|
|
135
|
+
return mat2(c, -s, s, c);
|
|
136
|
+
}
|
|
137
|
+
`,bi=`
|
|
138
|
+
vec2 getLabelDirection(float positionMode) {
|
|
139
|
+
if (positionMode < 0.5) return vec2(1.0, 0.0); // Right
|
|
140
|
+
if (positionMode < 1.5) return vec2(-1.0, 0.0); // Left
|
|
141
|
+
if (positionMode < 2.5) return vec2(0.0, -1.0); // Above
|
|
142
|
+
if (positionMode < 3.5) return vec2(0.0, 1.0); // Below
|
|
143
|
+
return vec2(0.0); // Over (centered)
|
|
144
|
+
}
|
|
145
|
+
`,xi=`
|
|
146
|
+
float sdfBox(vec2 p, vec2 halfSize) {
|
|
147
|
+
vec2 d = abs(p) - halfSize;
|
|
148
|
+
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
|
149
|
+
}
|
|
150
|
+
`,Si=`
|
|
151
|
+
float sdfRotatedBox(vec2 p, vec2 halfSize, float angle) {
|
|
152
|
+
float c = cos(-angle);
|
|
153
|
+
float s = sin(-angle);
|
|
154
|
+
vec2 rotatedP = mat2(c, -s, s, c) * p;
|
|
155
|
+
return sdfBox(rotatedP, halfSize);
|
|
156
|
+
}
|
|
157
|
+
`,Ci=`
|
|
158
|
+
float sdfRoundedBox(vec2 p, vec2 halfSize, float radius) {
|
|
159
|
+
vec2 d = abs(p) - halfSize + radius;
|
|
160
|
+
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - radius;
|
|
161
|
+
}
|
|
162
|
+
`,wi=`
|
|
163
|
+
float sdfRoundedRotatedBox(vec2 p, vec2 halfSize, float angle, float radius) {
|
|
164
|
+
float c = cos(-angle);
|
|
165
|
+
float s = sin(-angle);
|
|
166
|
+
vec2 rotatedP = mat2(c, -s, s, c) * p;
|
|
167
|
+
return sdfRoundedBox(rotatedP, halfSize, radius);
|
|
168
|
+
}
|
|
169
|
+
`,Ti=`
|
|
170
|
+
vec2 labelBoxCenter(float positionMode, float labelStart, vec2 halfSize, float textHalfY) {
|
|
171
|
+
if (positionMode < 0.5) return vec2(labelStart + halfSize.x, 0.0); // right
|
|
172
|
+
if (positionMode < 1.5) return vec2(-(labelStart + halfSize.x), 0.0); // left
|
|
173
|
+
if (positionMode < 2.5) return vec2(0.0, -(labelStart + textHalfY)); // above
|
|
174
|
+
if (positionMode < 3.5) return vec2(0.0, labelStart + textHalfY); // below
|
|
175
|
+
return vec2(0.0); // over
|
|
176
|
+
}
|
|
177
|
+
`,Ei=`
|
|
178
|
+
vec4 readNodeData(sampler2D nodeDataTexture, int nodeDataTextureWidth, int nodeIndex) {
|
|
179
|
+
int t = nodeIndex * 2;
|
|
180
|
+
ivec2 coord = ivec2(t % nodeDataTextureWidth, t / nodeDataTextureWidth);
|
|
181
|
+
return texelFetch(nodeDataTexture, coord, 0);
|
|
182
|
+
}
|
|
183
|
+
`,Di=`
|
|
184
|
+
vec4 readNodeFlags(sampler2D nodeDataTexture, int nodeDataTextureWidth, int nodeIndex) {
|
|
185
|
+
int t = nodeIndex * 2 + 1;
|
|
186
|
+
ivec2 coord = ivec2(t % nodeDataTextureWidth, t / nodeDataTextureWidth);
|
|
187
|
+
return texelFetch(nodeDataTexture, coord, 0);
|
|
188
|
+
}
|
|
189
|
+
`,Oi=`
|
|
190
|
+
vec4 readNodeColor(sampler2D nodeDataTexture, int nodeDataTextureWidth, int nodeIndex) {
|
|
191
|
+
int t = nodeIndex * 2 + 1;
|
|
192
|
+
ivec2 coord = ivec2(t % nodeDataTextureWidth, t / nodeDataTextureWidth);
|
|
193
|
+
vec4 texel = texelFetch(nodeDataTexture, coord, 0);
|
|
194
|
+
float r = floor(texel.b / 65536.0);
|
|
195
|
+
float g = floor(mod(texel.b, 65536.0) / 256.0);
|
|
196
|
+
float b = mod(texel.b, 256.0);
|
|
197
|
+
return vec4(r / 255.0, g / 255.0, b / 255.0, texel.a);
|
|
198
|
+
}
|
|
199
|
+
`,ki=`
|
|
200
|
+
vec4 readFrameTexel(sampler2D frameTexture, int frameTextureWidth, int index) {
|
|
201
|
+
ivec2 coord = ivec2(index % frameTextureWidth, index / frameTextureWidth);
|
|
202
|
+
return texelFetch(frameTexture, coord, 0);
|
|
203
|
+
}
|
|
204
|
+
`;function Ai(e,t){var n=function(e){return si(e,`uv`,`size`)};return e.length===1?{code:ji(n(e[0])),multiShape:!1}:{code:`
|
|
205
|
+
float queryShapeSDF(int shapeId, vec2 uv, float size) {
|
|
206
|
+
switch (shapeId) {
|
|
207
|
+
${e.map(function(e,r){return` case ${t?t[r]:r}: return ${n(e)};`}).join(`
|
|
208
|
+
`)}
|
|
209
|
+
default: return ${n(e[0])};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
int g_shapeId;
|
|
213
|
+
${ji(`queryShapeSDF(g_shapeId, uv, size)`)}
|
|
214
|
+
`,multiShape:!0}}function ji(e){return`
|
|
215
|
+
float findEdgeDistance(vec2 direction, float size) {
|
|
216
|
+
float lo = 0.0, hi = 2.0;
|
|
217
|
+
for (int i = 0; i < 8; i++) {
|
|
218
|
+
float mid = (lo + hi) * 0.5;
|
|
219
|
+
vec2 uv = direction * mid;
|
|
220
|
+
if (${e} < 0.0) lo = mid; else hi = mid;
|
|
221
|
+
}
|
|
222
|
+
return (lo + hi) * 0.5;
|
|
223
|
+
}
|
|
224
|
+
`}function Mi(e,t){for(;!{}.hasOwnProperty.call(e,t)&&(e=_n(e))!==null;);return e}function Ni(){return Ni=typeof Reflect<`u`&&Reflect.get?Reflect.get.bind():function(e,t,n){var r=Mi(e,t);if(r){var i=Object.getOwnPropertyDescriptor(r,t);return i.get?i.get.call(arguments.length<3?e:n):i.value}},Ni.apply(null,arguments)}function Q(e,t,n,r){var i=Ni(_n(1&r?e.prototype:e),t,n);return 2&r&&typeof i==`function`?function(e){return i.apply(n,e)}:i}var Pi=1024,Fi=1.5,Ii=4096,Li=-1,Ri=function(){function e(t,n){var r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:Pi;G(this,e),U(this,`texture`,null),U(this,`dirty`,!1),U(this,`dirtyRangeStart`,1/0),U(this,`dirtyRangeEnd`,-1),U(this,`indexMap`,new Map),U(this,`freeIndices`,[]),U(this,`nextIndex`,0),this.gl=t,this.TEXELS_PER_ITEM=n,this.capacity=this.roundUpToPowerOfTwo(r);var i=this.computeTextureDimensions(this.capacity);this.textureWidth=i.width,this.textureHeight=i.height,this.data=new Float32Array(this.textureWidth*this.textureHeight*4),this.createTexture()}return K(e,[{key:`computeTextureDimensions`,value:function(e){var t=e*this.TEXELS_PER_ITEM,n=Math.min(t,Ii);return{width:n,height:Math.ceil(t/n)}}},{key:`roundUpToPowerOfTwo`,value:function(e){return 2**Math.ceil(Math.log2(Math.max(1,e)))}},{key:`createTexture`,value:function(){var e=this.gl;this.texture=e.createTexture(),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.texture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA32F,this.textureWidth,this.textureHeight,0,e.RGBA,e.FLOAT,this.data),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null)}},{key:`resize`,value:function(e){if(!(e<=this.capacity)){var t=this.roundUpToPowerOfTwo(Math.ceil(e*Fi)),n=this.gl,r=this.computeTextureDimensions(t),i=new Float32Array(r.width*r.height*4);i.set(this.data),this.texture&&n.deleteTexture(this.texture),this.data=i,this.capacity=t,this.textureWidth=r.width,this.textureHeight=r.height,this.createTexture(),this.dirty=!0,this.dirtyRangeStart=0,this.dirtyRangeEnd=this.nextIndex}}},{key:`allocate`,value:function(e){var t=this.indexMap.get(e);if(t!==void 0)return t;var n;return this.freeIndices.length>0?n=this.freeIndices.pop():(n=this.nextIndex++,n>=this.capacity&&this.resize(n+1)),this.indexMap.set(e,n),n}},{key:`free`,value:function(e){var t=this.indexMap.get(e);if(t!==void 0){this.indexMap.delete(e),this.freeIndices.push(t);for(var n=t*this.TEXELS_PER_ITEM*4,r=0;r<this.TEXELS_PER_ITEM*4;r++)this.data[n+r]=0;this.markDirty(t)}}},{key:`getIndex`,value:function(e){return this.indexMap.get(e)??-1}},{key:`has`,value:function(e){return this.indexMap.has(e)}},{key:`markDirty`,value:function(e){this.dirty=!0,this.dirtyRangeStart=Math.min(this.dirtyRangeStart,e),this.dirtyRangeEnd=Math.max(this.dirtyRangeEnd,e+1)}},{key:`upload`,value:function(){if(this.dirty&&this.texture){var e=this.gl,t=this.textureWidth;e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.texture);var n=this.dirtyRangeStart*this.TEXELS_PER_ITEM,r=Math.min(this.dirtyRangeEnd*this.TEXELS_PER_ITEM,this.capacity*this.TEXELS_PER_ITEM);if(n<r)for(var i=Math.floor(n/t),a=Math.floor((r-1)/t),o=i;o<=a;o++){var s=o*t,c=Math.min(s+t,this.capacity*this.TEXELS_PER_ITEM),l=Math.max(n,s),u=Math.min(r,c);if(l<u){var d=l-s,f=u-l,p=this.data.subarray(l*4,u*4);e.texSubImage2D(e.TEXTURE_2D,0,d,o,f,1,e.RGBA,e.FLOAT,p)}}e.bindTexture(e.TEXTURE_2D,null),this.dirty=!1,this.dirtyRangeStart=1/0,this.dirtyRangeEnd=-1}}},{key:`bind`,value:function(e){var t=this.gl;t.activeTexture(t.TEXTURE0+e),t.bindTexture(t.TEXTURE_2D,this.texture)}},{key:`getTexture`,value:function(){return this.texture}},{key:`getCapacity`,value:function(){return this.capacity}},{key:`getTextureWidth`,value:function(){return this.textureWidth}},{key:`getTextureHeight`,value:function(){return this.textureHeight}},{key:`getTexelsPerItem`,value:function(){return this.TEXELS_PER_ITEM}},{key:`getCount`,value:function(){return this.indexMap.size}},{key:`getHighWaterMark`,value:function(){return this.nextIndex}},{key:`isDirty`,value:function(){return this.dirty}},{key:`clear`,value:function(){this.indexMap.clear(),this.freeIndices=[],this.nextIndex=0,this.data.fill(0),this.dirty=!0,this.dirtyRangeStart=0,this.dirtyRangeEnd=this.capacity}},{key:`restore`,value:function(){this.createTexture(),this.dirty=!1,this.dirtyRangeStart=1/0,this.dirtyRangeEnd=-1}},{key:`kill`,value:function(){this.texture&&=(this.gl.deleteTexture(this.texture),null),this.indexMap.clear(),this.freeIndices=[]}}])}();function zi(e){var t={},n={},r=0,i=H(e),a;try{for(i.s();!(a=i.n()).done;){var o=a.value,s=H(o.attributes),c;try{for(s.s();!(c=s.n()).done;){var l=c.value,u=l.name.replace(/^a_/,``);u in t||(t[u]=r,n[u]=l,r+=l.size)}}catch(e){s.e(e)}finally{s.f()}}}catch(e){i.e(e)}finally{i.f()}return{floatsPerItem:r,texelsPerItem:Math.max(1,Math.ceil(r/4)),offsets:t,specs:n}}var Bi=function(e){function t(e,n,r){var i;return G(this,t),i=q(this,t,[e,n.texelsPerItem,r]),i.floatsPerItem=n.floatsPerItem,i}return J(t,e),K(t,[{key:`updateAllAttributes`,value:function(e,t){var n=this.indexMap.get(e);n===void 0&&(n=this.allocate(e));for(var r=n*this.TEXELS_PER_ITEM*4,i=Math.min(t.length,this.floatsPerItem),a=0;a<i;a++)this.data[r+a]=t[a];this.markDirty(n)}},{key:`updateAllAttributesAtRow`,value:function(e,t){e>=this.capacity&&this.resize(e+1);for(var n=e*this.TEXELS_PER_ITEM*4,r=Math.min(t.length,this.floatsPerItem),i=0;i<r;i++)this.data[n+i]=t[i];this.markDirty(e)}}])}(Ri);function Vi(e,t,n){for(var r=[],i=new Set,a=0;a<e.length;a++){var o=e[a],s=H(o.attributes),c;try{for(s.s();!(c=s.n()).done;){var l=c.value,u=l.name.replace(/^a_/,``);if(!i.has(u)){i.add(u);var d=t.offsets[u];if(d!==void 0){var f=n?.get(a);r.push({sourceKey:l.source||u,packedOffset:d,size:l.size,isColor:l.size===4&&!!l.normalized,defaultNum:typeof l.defaultValue==`number`?l.defaultValue:+(l.defaultValue===!0),defaultColor:typeof l.defaultValue==`string`?l.defaultValue:``,sourceIndex:a,hasLifecycleHook:!!(f!=null&&f.getAttributeData)})}}}}catch(e){s.e(e)}finally{s.f()}}return r}function Hi(e,t,n,r,i,a){n.fill(0);for(var o=0,s=e.length;o<s;o++){var c=e[o],l=c.packedOffset,u=void 0;if(c.hasLifecycleHook?(u=i.get(c.sourceIndex-a).getAttributeData(t,c.sourceKey),u===null&&(u=t[c.sourceKey])):u=t[c.sourceKey],c.isColor){var d=V(cn(typeof u==`string`?u:c.defaultColor||r),4),f=d[0],p=d[1],m=d[2],h=d[3];n[l]=f/255,n[l+1]=p/255,n[l+2]=m/255,n[l+3]=h/255}else if(c.size===1)n[l]=typeof u==`number`?u:typeof u==`boolean`?+!!u:c.defaultNum;else{var g=Array.isArray(u)?u:null;if(g)for(var _=0;_<c.size;_++)n[l+_]=g[_]??0}}}var Ui=[`r`,`g`,`b`,`a`];function Wi(e,t){var n=e.offsets,r=e.specs,i=e.texelsPerItem,a=e.floatsPerItem,o=Object.keys(n);if(o.length===0||a===0)return{fetchCode:``,varyingAssignments:``};var s=t.varPrefix,c=t.baseTexelExpr,l=t.textureWidthUniform,u=t.textureSamplerUniform,d=t.outputPrefix,f=d===void 0?`v_`:d,p=[];p.push(` int ${s}BaseTexel = ${c};`),p.push(``);for(var m=0;m<i;m++)p.push(` ivec2 ${s}Coord${m} = ivec2((${s}BaseTexel + ${m}) % ${l}, (${s}BaseTexel + ${m}) / ${l});`),p.push(` vec4 ${s}Texel${m} = texelFetch(${u}, ${s}Coord${m}, 0);`);p.push(``);for(var h=[],g=function(){var e=v[_],t=r[e],i=n[e],a=Math.floor(i/4),o=i%4,c=`${s}Texel${a}`,l=`${s}Texel${a+1}`,u=`${s}Fetched_${e}`;if(t.size===1)p.push(` float ${u} = ${c}.${Ui[o]};`);else if(t.size===4&&o===0)p.push(` vec4 ${u} = ${c};`);else{var d=o+t.size;if(d<=4){var m=`vec${t.size}`,g=Ui.slice(o,d).join(``);p.push(` ${m} ${u} = ${c}.${g};`)}else{var y=t.size===4?`vec4`:`vec${t.size}`,b=Ui.slice(o).map(function(e){return`${c}.${e}`}),x=Ui.slice(0,d-4).map(function(e){return`${l}.${e}`}),S=[].concat(Y(b),Y(x)).join(`, `);p.push(` ${y} ${u} = ${y}(${S});`)}}h.push(` ${f}${e} = ${u};`)},_=0,v=o;_<v.length;_++)g();return{fetchCode:p.join(`
|
|
225
|
+
`),varyingAssignments:h.join(`
|
|
226
|
+
`)}}function Gi(e,t,n){if(t&&n.type!==`sampler2D`)switch(n.type){case`float`:e.uniform1f(t,n.value);break;case`int`:case`bool`:e.uniform1i(t,n.value);break;case`vec2`:e.uniform2fv(t,n.value);break;case`vec3`:e.uniform3fv(t,n.value);break;case`vec4`:e.uniform4fv(t,n.value);break;case`mat3`:e.uniformMatrix3fv(t,!1,n.value);break;case`mat4`:e.uniformMatrix4fv(t,!1,n.value)}}var Ki=U(U(U(U(U(U(U(U({},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);function qi(e){var t=e.match(/^(#version[^\n]*\n)/);return t?t[1]+`#define PICKING_MODE
|
|
227
|
+
`+e.slice(t[1].length):`#define PICKING_MODE
|
|
228
|
+
`+e}var Ji=function(){function e(t,n,r){G(this,e),U(this,`floats`,new Float32Array),U(this,`ints`,new Uint32Array),U(this,`constantArray`,new Float32Array),U(this,`capacity`,0),U(this,`verticesCount`,0),U(this,`bufferGeneration`,0),U(this,`uploadedGeneration`,new Map),U(this,`constantBufferGeneration`,0),U(this,`uploadedConstantGeneration`,new Map),U(this,`renderOffset`,0),U(this,`renderCount`,-1),U(this,`debugStats`,{drawCalls:0,verticesDrawn:0,bufferUploadBytes:0}),U(this,`shadersLogged`,!1),U(this,`pickProgram`,null);var i=this.getDefinition();if(this.VERTICES=i.VERTICES,this.VERTEX_SHADER_SOURCE=i.VERTEX_SHADER_SOURCE,this.FRAGMENT_SHADER_SOURCE=i.FRAGMENT_SHADER_SOURCE,this.UNIFORMS=i.UNIFORMS,this.ATTRIBUTES=i.ATTRIBUTES,this.METHOD=i.METHOD,this.CONSTANT_ATTRIBUTES=`CONSTANT_ATTRIBUTES`in i?i.CONSTANT_ATTRIBUTES:[],this.CONSTANT_DATA=`CONSTANT_DATA`in i?i.CONSTANT_DATA:[],this.isInstanced=`CONSTANT_ATTRIBUTES`in i,this.ATTRIBUTES_ITEMS_COUNT=Zr(this.ATTRIBUTES),this.STRIDE=this.VERTICES*this.ATTRIBUTES_ITEMS_COUNT,this.renderer=r,this.normalProgram=this.getProgramInfo(`normal`,t,i.VERTEX_SHADER_SOURCE,i.FRAGMENT_SHADER_SOURCE,null),this.pickProgram=this.getProgramInfo(`pick`,t,qi(i.VERTEX_SHADER_SOURCE),qi(i.FRAGMENT_SHADER_SOURCE),null),this.isInstanced){var a=Zr(this.CONSTANT_ATTRIBUTES);if(this.CONSTANT_DATA.length!==this.VERTICES)throw Error(`Program: error while getting constant data (expected ${this.VERTICES} items, received ${this.CONSTANT_DATA.length} instead)`);this.constantArray=new Float32Array(this.CONSTANT_DATA.length*a);for(var o=0;o<this.CONSTANT_DATA.length;o++){var s=this.CONSTANT_DATA[o];if(s.length!==a)throw Error(`Program: error while getting constant data (one vector has ${s.length} items instead of ${a})`);for(var c=0;c<s.length;c++)this.constantArray[o*a+c]=s[c]}this.STRIDE=this.ATTRIBUTES_ITEMS_COUNT}}return K(e,[{key:`kill`,value:function(){ni(this.normalProgram),this.pickProgram&&ni(this.pickProgram)}},{key:`resetDebugStats`,value:function(){this.debugStats.drawCalls=0,this.debugStats.verticesDrawn=0,this.debugStats.bufferUploadBytes=0}},{key:`getProgramInfo`,value:function(e,t,n,r,i){var a=t.createBuffer();if(a===null)throw Error(`Program: error while creating the WebGL buffer.`);var o=$r(t,n),s=ei(t,r),c=ti(t,[o,s]),l={};this.UNIFORMS.forEach(function(e){var n=t.getUniformLocation(c,e);n&&(l[e]=n)});var u={};this.ATTRIBUTES.forEach(function(e){u[e.name]=t.getAttribLocation(c,e.name)});var d;if(this.isInstanced&&(this.CONSTANT_ATTRIBUTES.forEach(function(e){u[e.name]=t.getAttribLocation(c,e.name)}),d=t.createBuffer(),d===null))throw Error(`Program: error while creating the WebGL constant buffer.`);return{name:e,program:c,gl:t,frameBuffer:i,buffer:a,constantBuffer:d||{},uniformLocations:l,attributeLocations:u,isPicking:e===`pick`,vertexShader:o,fragmentShader:s}}},{key:`bindProgram`,value:function(e){var t=this,n=0,r=e.gl,i=e.buffer;if(this.isInstanced){if(r.bindBuffer(r.ARRAY_BUFFER,e.constantBuffer),n=0,this.CONSTANT_ATTRIBUTES.forEach(function(r){return n+=t.bindAttribute(r,e,n,!1)}),this.uploadedConstantGeneration.get(e.constantBuffer)!==this.constantBufferGeneration){var a;r.bufferData(r.ARRAY_BUFFER,this.constantArray,r.STATIC_DRAW),this.uploadedConstantGeneration.set(e.constantBuffer,this.constantBufferGeneration),(a=this.renderer)!=null&&a.getSetting(`DEBUG_logRenderStats`)&&(this.debugStats.bufferUploadBytes+=this.constantArray.byteLength)}if(r.bindBuffer(r.ARRAY_BUFFER,e.buffer),n=this.renderOffset*this.ATTRIBUTES_ITEMS_COUNT*Float32Array.BYTES_PER_ELEMENT,this.ATTRIBUTES.forEach(function(r){return n+=t.bindAttribute(r,e,n,!0)}),this.uploadedGeneration.get(i)!==this.bufferGeneration){var o;r.bufferData(r.ARRAY_BUFFER,this.floats,r.DYNAMIC_DRAW),this.uploadedGeneration.set(i,this.bufferGeneration),(o=this.renderer)!=null&&o.getSetting(`DEBUG_logRenderStats`)&&(this.debugStats.bufferUploadBytes+=this.floats.byteLength)}}else if(r.bindBuffer(r.ARRAY_BUFFER,i),n=0,this.ATTRIBUTES.forEach(function(r){return n+=t.bindAttribute(r,e,n)}),this.uploadedGeneration.get(i)!==this.bufferGeneration){var s;r.bufferData(r.ARRAY_BUFFER,this.floats,r.DYNAMIC_DRAW),this.uploadedGeneration.set(i,this.bufferGeneration),(s=this.renderer)!=null&&s.getSetting(`DEBUG_logRenderStats`)&&(this.debugStats.bufferUploadBytes+=this.floats.byteLength)}r.bindBuffer(r.ARRAY_BUFFER,null)}},{key:`unbindProgram`,value:function(e){var t=this;this.isInstanced?(this.CONSTANT_ATTRIBUTES.forEach(function(n){return t.unbindAttribute(n,e,!1)}),this.ATTRIBUTES.forEach(function(n){return t.unbindAttribute(n,e,!0)})):this.ATTRIBUTES.forEach(function(n){return t.unbindAttribute(n,e)})}},{key:`bindAttribute`,value:function(e,t,n,r){var i=Ki[e.type];if(typeof i!=`number`)throw Error(`Program.bind: yet unsupported attribute type "${e.type}"`);var a=t.attributeLocations[e.name],o=t.gl;if(a!==-1){o.enableVertexAttribArray(a);var s=this.isInstanced?(r?this.ATTRIBUTES_ITEMS_COUNT:Zr(this.CONSTANT_ATTRIBUTES))*Float32Array.BYTES_PER_ELEMENT:this.ATTRIBUTES_ITEMS_COUNT*Float32Array.BYTES_PER_ELEMENT;o.vertexAttribPointer(a,e.size,e.type,e.normalized||!1,s,n),this.isInstanced&&r&&o.vertexAttribDivisor(a,1)}return e.size*i}},{key:`unbindAttribute`,value:function(e,t,n){var r=t.attributeLocations[e.name],i=t.gl;r!==-1&&(i.disableVertexAttribArray(r),this.isInstanced&&n&&i.vertexAttribDivisor(r,0))}},{key:`reallocate`,value:function(e){e!==this.capacity&&(this.capacity=e,this.verticesCount=this.VERTICES*e,this.floats=new Float32Array(this.isInstanced?this.capacity*this.ATTRIBUTES_ITEMS_COUNT:this.verticesCount*this.ATTRIBUTES_ITEMS_COUNT),this.ints=new Uint32Array(this.floats.buffer),this.invalidateBuffers())}},{key:`invalidateBuffers`,value:function(){this.bufferGeneration++,this.constantBufferGeneration++}},{key:`hasNothingToRender`,value:function(){return this.verticesCount===0}},{key:`setTypedUniform`,value:function(e,t){Gi(t.gl,t.uniformLocations[e.name]??null,e)}},{key:`renderProgram`,value:function(e,t){var n=t.gl,r=t.program;t.isPicking?n.disable(n.BLEND):n.enable(n.BLEND),n.useProgram(r),this.setUniforms(e,t),this.drawWebGL(this.METHOD,t)}},{key:`render`,value:function(e,t,n){var r;if(!this.shadersLogged&&(r=this.renderer)!=null&&r.getSetting(`DEBUG_logShaders`)&&(this.shadersLogged=!0,console.log(`[sigma] DEBUG_logShaders: ${this.constructor.name}`,{normal:{vertexShaderSource:this.VERTEX_SHADER_SOURCE,fragmentShaderSource:this.FRAGMENT_SHADER_SOURCE},pick:{vertexShaderSource:qi(this.VERTEX_SHADER_SOURCE),fragmentShaderSource:qi(this.FRAGMENT_SHADER_SOURCE)}})),!this.hasNothingToRender()){this.renderOffset=t??0,this.renderCount=n??-1;var i=this.normalProgram.gl;if(i.bindFramebuffer(i.FRAMEBUFFER,null),i.viewport(0,0,e.width*e.pixelRatio,e.height*e.pixelRatio),this.bindProgram(this.normalProgram),this.renderProgram(e,this.normalProgram),this.unbindProgram(this.normalProgram),this.pickProgram&&e.pickingFrameBuffer){var a=Math.ceil(e.width*e.pixelRatio/e.downSizingRatio),o=Math.ceil(e.height*e.pixelRatio/e.downSizingRatio);i.bindFramebuffer(i.FRAMEBUFFER,e.pickingFrameBuffer),i.viewport(0,0,a,o),this.bindProgram(this.pickProgram),this.renderProgram(e,this.pickProgram),this.unbindProgram(this.pickProgram),i.bindFramebuffer(i.FRAMEBUFFER,null),i.viewport(0,0,e.width*e.pixelRatio,e.height*e.pixelRatio)}}}},{key:`drawWebGL`,value:function(e,t){var n,r=t.gl,i=this.renderCount>=0?this.renderCount:this.capacity;(n=this.renderer)!=null&&n.getSetting(`DEBUG_logRenderStats`)&&(this.debugStats.drawCalls++,this.debugStats.verticesDrawn+=i*this.VERTICES),this.isInstanced?r.drawArraysInstanced(e,0,this.VERTICES,i):r.drawArrays(e,this.renderOffset*this.VERTICES,i*this.VERTICES)}}])}(),Yi={below:0,above:1,left:2,right:3};function Xi(){return`#version 300 es
|
|
229
|
+
precision highp float;
|
|
230
|
+
|
|
231
|
+
uniform mat3 u_matrix;
|
|
232
|
+
uniform vec2 u_resolution;
|
|
233
|
+
uniform float u_labelPixelSnapping;
|
|
234
|
+
uniform float u_sizeRatio;
|
|
235
|
+
uniform float u_correctionRatio;
|
|
236
|
+
uniform float u_cameraAngle;
|
|
237
|
+
uniform float u_pixelRatio;
|
|
238
|
+
uniform float u_labelMargin;
|
|
239
|
+
uniform float u_zoomLabelSizeRatio;
|
|
240
|
+
|
|
241
|
+
uniform sampler2D u_nodeDataTexture;
|
|
242
|
+
uniform int u_nodeDataTextureWidth;
|
|
243
|
+
uniform sampler2D u_nodeFrameTexture;
|
|
244
|
+
uniform int u_nodeFrameTextureWidth;
|
|
245
|
+
|
|
246
|
+
// Atlas size is fixed at 2048×2048 — matches AttachmentManager.ATLAS_SIZE.
|
|
247
|
+
uniform sampler2D u_atlasTexture;
|
|
248
|
+
const vec2 u_atlasSize = vec2(2048.0);
|
|
249
|
+
|
|
250
|
+
// Per-instance
|
|
251
|
+
in float a_nodeIndex; // node-data texture index
|
|
252
|
+
in vec4 a_atlasRect; // x, y, width, height in atlas pixels
|
|
253
|
+
in vec2 a_attachmentSize; // attachment dimensions (CSS px)
|
|
254
|
+
in float a_positionMode; // label position: 0=right 1=left 2=above 3=below 4=over
|
|
255
|
+
in float a_attachmentPlacement; // 0=below 1=above 2=left 3=right (relative to label)
|
|
256
|
+
in float a_labelWidth; // label width (CSS px)
|
|
257
|
+
in float a_labelHeight; // label height: font line box (CSS px)
|
|
258
|
+
in float a_textHeight; // actual glyph height (CSS px)
|
|
259
|
+
in float a_labelAngle; // label rotation angle (radians)
|
|
260
|
+
|
|
261
|
+
// Per-vertex (constant)
|
|
262
|
+
in vec2 a_quadCorner; // [-1,-1], [1,-1], [-1,1], [1,1]
|
|
263
|
+
|
|
264
|
+
out vec2 v_texCoord;
|
|
265
|
+
|
|
266
|
+
${Ei}
|
|
267
|
+
${Di}
|
|
268
|
+
${ki}
|
|
269
|
+
${Ti}
|
|
270
|
+
${yi}
|
|
271
|
+
|
|
272
|
+
void main() {
|
|
273
|
+
int nodeIdx = int(a_nodeIndex);
|
|
274
|
+
|
|
275
|
+
// Node data: (x, y, size, shapeId).
|
|
276
|
+
vec4 nodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx);
|
|
277
|
+
vec2 nodePos = nodeData.xy;
|
|
278
|
+
float nodeSize = nodeData.z;
|
|
279
|
+
|
|
280
|
+
// Normalized edge distance from the shared frame texture (the frame-pass ran
|
|
281
|
+
// the SDF search once; we just read the result).
|
|
282
|
+
float edgeDist = readFrameTexel(u_nodeFrameTexture, u_nodeFrameTextureWidth, nodeIdx).r;
|
|
283
|
+
|
|
284
|
+
// Per-node label rotation alignment: 0 = viewport, 1 = label turns with camera.
|
|
285
|
+
float labelRotation = readNodeFlags(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx).g;
|
|
286
|
+
|
|
287
|
+
vec3 nodeClip = u_matrix * vec3(nodePos, 1.0);
|
|
288
|
+
|
|
289
|
+
// Node radius in physical pixels (matches label/background).
|
|
290
|
+
float matrixScaleX = length(vec2(u_matrix[0][0], u_matrix[1][0]));
|
|
291
|
+
float nodeRadiusGraphSpace = nodeSize * u_correctionRatio / u_sizeRatio * 2.0;
|
|
292
|
+
float nodeRadiusPixels = nodeRadiusGraphSpace * matrixScaleX * u_resolution.x / 2.0;
|
|
293
|
+
|
|
294
|
+
// CSS-px inputs -> physical px, scaled by the zoom-dependent label ratio, so
|
|
295
|
+
// the attachment stays glued to the label box exactly as the label scales.
|
|
296
|
+
float zoomScale = u_zoomLabelSizeRatio;
|
|
297
|
+
vec2 labelHalf = vec2(a_labelWidth, a_labelHeight) * 0.5 * zoomScale * u_pixelRatio;
|
|
298
|
+
vec2 attachHalf = a_attachmentSize * 0.5 * zoomScale * u_pixelRatio;
|
|
299
|
+
float gap = ${2 .toFixed(1)} * zoomScale * u_pixelRatio;
|
|
300
|
+
float labelMargin = u_labelMargin * zoomScale * u_pixelRatio;
|
|
301
|
+
|
|
302
|
+
// Graph-aligned labels add the camera angle so the attachment orbits with the box.
|
|
303
|
+
mat2 labelRotMat = rotate2D(a_labelAngle - labelRotation * u_cameraAngle);
|
|
304
|
+
|
|
305
|
+
// Label box center relative to the node center (pre-rotation). The shape-aware
|
|
306
|
+
// edge distance comes from the frame texture, so placement matches the label.
|
|
307
|
+
vec2 boxCenter = vec2(0.0);
|
|
308
|
+
if (a_positionMode < 4.0) {
|
|
309
|
+
float labelStart = nodeRadiusPixels * edgeDist + labelMargin;
|
|
310
|
+
float textHalf = a_textHeight * 0.5 * zoomScale * u_pixelRatio;
|
|
311
|
+
boxCenter = labelBoxCenter(a_positionMode, labelStart, labelHalf, textHalf);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Horizontal anchor of below/above attachments tracks the label position, so
|
|
315
|
+
// the attachment hangs from the label edge nearest the node (or is centered
|
|
316
|
+
// when the label itself is node-centered): right->left, left->right, else center.
|
|
317
|
+
float anchorX = 0.0;
|
|
318
|
+
if (a_positionMode < 0.5) anchorX = -labelHalf.x + attachHalf.x; // right label
|
|
319
|
+
else if (a_positionMode < 1.5) anchorX = labelHalf.x - attachHalf.x; // left label
|
|
320
|
+
|
|
321
|
+
// Attachment center relative to the box (pre-rotation, Y-down). This offset
|
|
322
|
+
// depends only on the box, the gap and the attachment size — never the shape.
|
|
323
|
+
vec2 attachCenter;
|
|
324
|
+
if (a_attachmentPlacement < 0.5) {
|
|
325
|
+
// below
|
|
326
|
+
attachCenter = boxCenter + vec2(anchorX, labelHalf.y + gap + attachHalf.y);
|
|
327
|
+
} else if (a_attachmentPlacement < 1.5) {
|
|
328
|
+
// above
|
|
329
|
+
attachCenter = boxCenter + vec2(anchorX, -(labelHalf.y + gap + attachHalf.y));
|
|
330
|
+
} else if (a_attachmentPlacement < 2.5) {
|
|
331
|
+
// left, top-aligned
|
|
332
|
+
attachCenter = boxCenter + vec2(-(labelHalf.x + gap + attachHalf.x), -labelHalf.y + attachHalf.y);
|
|
333
|
+
} else {
|
|
334
|
+
// right, top-aligned
|
|
335
|
+
attachCenter = boxCenter + vec2(labelHalf.x + gap + attachHalf.x, -labelHalf.y + attachHalf.y);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Rotate the whole assembly by the label angle, around the node center.
|
|
339
|
+
vec2 rotatedCenter = labelRotMat * attachCenter;
|
|
340
|
+
vec2 cornerOffset = labelRotMat * (a_quadCorner * attachHalf);
|
|
341
|
+
|
|
342
|
+
// Node center in screen px (Y-down).
|
|
343
|
+
vec2 nodeScreen = vec2(
|
|
344
|
+
(nodeClip.x + 1.0) * u_resolution.x,
|
|
345
|
+
(1.0 - nodeClip.y) * u_resolution.y
|
|
346
|
+
) * 0.5;
|
|
347
|
+
|
|
348
|
+
// Snap node center to the pixel grid so label/backdrop/attachment move as one.
|
|
349
|
+
vec2 snapDelta = (round(nodeScreen) - nodeScreen) * u_labelPixelSnapping;
|
|
350
|
+
|
|
351
|
+
// Snap the quad's top-left to integer pixels so atlas texels map 1:1.
|
|
352
|
+
vec2 centerScreen = nodeScreen + rotatedCenter + snapDelta;
|
|
353
|
+
vec2 topLeft = centerScreen - attachHalf;
|
|
354
|
+
topLeft = mix(topLeft, round(topLeft), u_labelPixelSnapping);
|
|
355
|
+
centerScreen = topLeft + attachHalf;
|
|
356
|
+
|
|
357
|
+
vec2 vertexScreen = centerScreen + cornerOffset;
|
|
358
|
+
gl_Position = vec4(
|
|
359
|
+
vertexScreen.x * 2.0 / u_resolution.x - 1.0,
|
|
360
|
+
1.0 - vertexScreen.y * 2.0 / u_resolution.y,
|
|
361
|
+
0.0, 1.0
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
vec2 texOrigin = a_atlasRect.xy / u_atlasSize;
|
|
365
|
+
vec2 texSize = a_atlasRect.zw / u_atlasSize;
|
|
366
|
+
vec2 uv = (a_quadCorner + 1.0) / 2.0;
|
|
367
|
+
v_texCoord = texOrigin + uv * texSize;
|
|
368
|
+
}
|
|
369
|
+
`}var Zi=`#version 300 es
|
|
370
|
+
precision highp float;
|
|
371
|
+
|
|
372
|
+
uniform sampler2D u_atlasTexture;
|
|
373
|
+
|
|
374
|
+
in vec2 v_texCoord;
|
|
375
|
+
|
|
376
|
+
layout(location = 0) out vec4 fragColor;
|
|
377
|
+
#ifdef PICKING_MODE
|
|
378
|
+
layout(location = 1) out vec4 pickColor;
|
|
379
|
+
#endif
|
|
380
|
+
|
|
381
|
+
void main() {
|
|
382
|
+
// Canvas textures are premultiplied; output directly for (ONE, 1-SRC_ALPHA) blending
|
|
383
|
+
vec4 color = texture(u_atlasTexture, v_texCoord);
|
|
384
|
+
if (color.a < 0.01) discard;
|
|
385
|
+
fragColor = color;
|
|
386
|
+
#ifdef PICKING_MODE
|
|
387
|
+
pickColor = vec4(0.0); // Attachments are not pickable
|
|
388
|
+
#endif
|
|
389
|
+
}
|
|
390
|
+
`;function Qi(e,t,n,r){var i=r.label,a=i===void 0?{}:i,o=a.margin??5,s=a.zoomToLabelSizeRatioFunction??function(){return 1},c=Xi(),l=Zi,u=function(e){function t(){var e;G(this,t);var n=[...arguments];return e=q(this,t,[].concat(n)),U(e,`totalCount`,0),U(e,`bufferCapacity`,0),e}return J(t,e),K(t,[{key:`getDefinition`,value:function(){var e=WebGL2RenderingContext,t=e.FLOAT;return{VERTICES:4,VERTEX_SHADER_SOURCE:c,FRAGMENT_SHADER_SOURCE:l,METHOD:e.TRIANGLE_STRIP,UNIFORMS:[`u_matrix`,`u_resolution`,`u_labelPixelSnapping`,`u_sizeRatio`,`u_correctionRatio`,`u_cameraAngle`,`u_pixelRatio`,`u_labelMargin`,`u_zoomLabelSizeRatio`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_nodeFrameTexture`,`u_nodeFrameTextureWidth`,`u_atlasTexture`],ATTRIBUTES:[{name:`a_nodeIndex`,size:1,type:t},{name:`a_atlasRect`,size:4,type:t},{name:`a_attachmentSize`,size:2,type:t},{name:`a_positionMode`,size:1,type:t},{name:`a_attachmentPlacement`,size:1,type:t},{name:`a_labelWidth`,size:1,type:t},{name:`a_labelHeight`,size:1,type:t},{name:`a_textHeight`,size:1,type:t},{name:`a_labelAngle`,size:1,type:t}],CONSTANT_ATTRIBUTES:[{name:`a_quadCorner`,size:2,type:t}],CONSTANT_DATA:[[-1,-1],[1,-1],[-1,1],[1,1]]}}},{key:`processAttachment`,value:function(e,t){var n=this.floats,r=e*this.STRIDE;n[r++]=t.nodeIndex,n[r++]=t.atlasX,n[r++]=t.atlasY,n[r++]=t.atlasW,n[r++]=t.atlasH,n[r++]=t.attachWidth,n[r++]=t.attachHeight,n[r++]=t.positionMode,n[r++]=t.attachmentPlacement,n[r++]=t.labelWidth,n[r++]=t.labelHeight,n[r++]=t.textHeight,n[r++]=t.labelAngle}},{key:`setUniforms`,value:function(e,n){var r=n.gl,i=n.uniformLocations;r.uniformMatrix3fv(i.u_matrix,!1,e.matrix),r.uniform2f(i.u_resolution,e.width*e.pixelRatio,e.height*e.pixelRatio),r.uniform1f(i.u_labelPixelSnapping,e.labelPixelSnapping),r.uniform1f(i.u_sizeRatio,e.sizeRatio),r.uniform1f(i.u_correctionRatio,e.correctionRatio),r.uniform1f(i.u_cameraAngle,e.cameraAngle),r.uniform1f(i.u_pixelRatio,e.pixelRatio),r.uniform1f(i.u_labelMargin,t.labelMargin),r.uniform1f(i.u_zoomLabelSizeRatio,1/s(e.zoomRatio)),r.uniform1i(i.u_nodeDataTexture,e.nodeDataTextureUnit),r.uniform1i(i.u_nodeDataTextureWidth,e.nodeDataTextureWidth),r.uniform1i(i.u_nodeFrameTexture,e.nodeFrameTextureUnit),r.uniform1i(i.u_nodeFrameTextureWidth,e.nodeFrameTextureWidth),r.uniform1i(i.u_atlasTexture,7)}},{key:`reallocateAttachments`,value:function(e){this.totalCount=e,e>this.bufferCapacity&&(this.bufferCapacity=Math.max(e,Math.ceil(this.bufferCapacity*1.5)||10),Q(t,`reallocate`,this,3)([this.bufferCapacity]))}},{key:`hasNothingToRender`,value:function(){return this.totalCount===0}},{key:`drawWebGL`,value:function(e,t){var n=t.gl;this.totalCount!==0&&n.drawArraysInstanced(e,0,this.VERTICES,this.totalCount)}}])}(Ji);return U(u,`labelMargin`,o),new u(e,t,n)}var $i=5;function ea(e,t){return[].concat(Y(t),Y(e.map(function(e){return{attributes:e.attributes??[]}})))}function ta(e,t){var n=zi(ea(e,t)),r=new Set(e.flatMap(function(e){return e.attributes??[]}).map(function(e){return e.name.replace(/^a_/,``)})),i={},a={},o=H(r),s;try{for(o.s();!(s=o.n()).done;){var c=s.value;i[c]=n.offsets[c],a[c]=n.specs[c]}}catch(e){o.e(e)}finally{o.f()}return W(W({},n),{},{offsets:i,specs:a})}function na(e,t){var n=new Set([`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_cameraAngle`,`u_pickingPadding`,`u_nodeDataTexture`,`u_layerAttributeTexture`]),r=new Set,i=e.flatMap(function(e){return e.uniforms}).filter(function(e){return n.has(e.name)||r.has(e.name)?!1:(r.add(e.name),!0)}).map(function(e){return`uniform ${e.type} ${e.name};`}).join(`
|
|
391
|
+
`),a=t.flatMap(function(e){return e.uniforms}).filter(function(e){return n.has(e.name)||r.has(e.name)?!1:(r.add(e.name),!0)}).map(function(e){return`uniform ${e.type} ${e.name};`}).join(`
|
|
392
|
+
`),o=ea(e,t),s=new Set,c=o.flatMap(function(e){return e.attributes}).filter(function(e){var t=e.name.replace(/^a_/,``);return!s.has(t)&&(s.add(t),!0)}).map(function(e){var t=e.name.replace(/^a_/,``);return`out ${e.size===1?`float`:`vec${e.size}`} v_${t};`}).join(`
|
|
393
|
+
`),l=Wi(zi(o),{varPrefix:`layer`,baseTexelExpr:`nodeIdx * u_layerAttributeTexelsPerNode`,textureWidthUniform:`u_layerAttributeTextureWidth`,textureSamplerUniform:`u_layerAttributeTexture`});return`#version 300 es
|
|
394
|
+
|
|
395
|
+
// Standard node attributes (per instance) - minimal buffer usage
|
|
396
|
+
in float a_nodeIndex; // Index into node data texture AND layer attribute texture
|
|
397
|
+
in vec4 a_id; // Node ID for picking
|
|
398
|
+
in float a_opacity; // Node opacity, applied once to the final fragment
|
|
399
|
+
|
|
400
|
+
// Constant attributes (per vertex, same for all instances)
|
|
401
|
+
in vec2 a_quadCorner; // (-1,-1), (1,-1), (1,1), (-1,1) for quad corners
|
|
402
|
+
|
|
403
|
+
// Standard uniforms
|
|
404
|
+
uniform mat3 u_matrix;
|
|
405
|
+
uniform float u_sizeRatio;
|
|
406
|
+
uniform float u_correctionRatio;
|
|
407
|
+
uniform float u_cameraAngle;
|
|
408
|
+
#ifdef PICKING_MODE
|
|
409
|
+
uniform float u_pickingPadding;
|
|
410
|
+
#endif
|
|
411
|
+
uniform sampler2D u_nodeDataTexture;
|
|
412
|
+
uniform int u_nodeDataTextureWidth;
|
|
413
|
+
|
|
414
|
+
// Layer attribute texture uniforms
|
|
415
|
+
uniform sampler2D u_layerAttributeTexture;
|
|
416
|
+
uniform int u_layerAttributeTextureWidth;
|
|
417
|
+
uniform int u_layerAttributeTexelsPerNode;
|
|
418
|
+
|
|
419
|
+
${i}
|
|
420
|
+
${a}
|
|
421
|
+
|
|
422
|
+
// Standard varyings
|
|
423
|
+
out vec2 v_uv; // Normalized coordinates [-1, 1]
|
|
424
|
+
out vec4 v_id;
|
|
425
|
+
out float v_opacity;
|
|
426
|
+
out float v_antialiasingWidth; // Width for antialiasing in UV space
|
|
427
|
+
out float v_pixelSize; // Node size in pixels (for pixel-mode borders)
|
|
428
|
+
out float v_pixelToUV; // Conversion factor: multiply by this to convert screen pixels to UV units
|
|
429
|
+
out float v_shapeId; // Shape ID for multi-shape programs
|
|
430
|
+
|
|
431
|
+
// Layer varyings
|
|
432
|
+
${c}
|
|
433
|
+
|
|
434
|
+
// Node-data fetch helpers (geometry texel + rotation-flags texel)
|
|
435
|
+
${Ei}
|
|
436
|
+
${Di}
|
|
437
|
+
|
|
438
|
+
void main() {
|
|
439
|
+
// Fetch node geometry: vec4(x, y, size, shapeId).
|
|
440
|
+
int nodeIdx = int(a_nodeIndex);
|
|
441
|
+
|
|
442
|
+
// Hidden nodes are flagged with a negative row by NodeProgram.process(). Push
|
|
443
|
+
// the whole quad outside the clip volume: every vertex lands at the same
|
|
444
|
+
// out-of-range position, so the primitive is fully clipped and rasterizes
|
|
445
|
+
// nothing — neither to the frame buffer nor to the picking buffer.
|
|
446
|
+
if (nodeIdx < 0) {
|
|
447
|
+
gl_Position = vec4(2.0, 0.0, 0.0, 1.0);
|
|
448
|
+
v_id = vec4(0.0);
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
vec4 nodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx);
|
|
453
|
+
vec2 a_position = nodeData.xy;
|
|
454
|
+
float a_size = nodeData.z;
|
|
455
|
+
v_shapeId = nodeData.w; // Pass shape ID to fragment shader
|
|
456
|
+
|
|
457
|
+
// Per-node rotation alignment: 0 = viewport (screen-upright), 1 = graph.
|
|
458
|
+
float nodeRotation = readNodeFlags(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx).r;
|
|
459
|
+
|
|
460
|
+
${l.fetchCode}
|
|
461
|
+
|
|
462
|
+
// Calculate the actual size in pixels
|
|
463
|
+
float size = a_size * u_correctionRatio / u_sizeRatio * 2.0;
|
|
464
|
+
|
|
465
|
+
// In PICKING_MODE, inflate the quad by nodePickingPadding pixels on each side
|
|
466
|
+
#ifdef PICKING_MODE
|
|
467
|
+
float paddedSize = size + u_pickingPadding * u_correctionRatio;
|
|
468
|
+
vec2 offset = a_quadCorner * paddedSize;
|
|
469
|
+
#else
|
|
470
|
+
vec2 offset = a_quadCorner * size;
|
|
471
|
+
#endif
|
|
472
|
+
// Counter-rotate the quad offset so viewport-aligned nodes stay upright as the
|
|
473
|
+
// camera turns. Graph-aligned nodes (nodeRotation=1) skip it and turn with the
|
|
474
|
+
// camera. The angle scales by (1 - nodeRotation) so both fall out of one path.
|
|
475
|
+
{
|
|
476
|
+
float ca = u_cameraAngle * (1.0 - nodeRotation);
|
|
477
|
+
float c = cos(ca);
|
|
478
|
+
float s = sin(ca);
|
|
479
|
+
offset = mat2(c, s, -s, c) * offset;
|
|
480
|
+
}
|
|
481
|
+
vec2 position = a_position + offset;
|
|
482
|
+
|
|
483
|
+
gl_Position = vec4(
|
|
484
|
+
(u_matrix * vec3(position, 1)).xy,
|
|
485
|
+
0,
|
|
486
|
+
1
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
// In PICKING_MODE, UV is scaled beyond [-1, 1] to match the inflated quad
|
|
490
|
+
#ifdef PICKING_MODE
|
|
491
|
+
v_uv = a_quadCorner * (paddedSize / size);
|
|
492
|
+
#else
|
|
493
|
+
v_uv = a_quadCorner;
|
|
494
|
+
#endif
|
|
495
|
+
|
|
496
|
+
// Pass ID to fragment shader
|
|
497
|
+
v_id = a_id;
|
|
498
|
+
v_opacity = a_opacity;
|
|
499
|
+
|
|
500
|
+
// Pass pixel size for layers that need pixel-mode calculations
|
|
501
|
+
// Multiply by 2 because 'size' is half-width (offset from center), not full diameter
|
|
502
|
+
v_pixelSize = size * 2.0;
|
|
503
|
+
|
|
504
|
+
// Conversion factor from screen pixels to UV units
|
|
505
|
+
// Same derivation as v_antialiasingWidth which represents ~1 pixel in UV space
|
|
506
|
+
// P pixels in UV space = P * u_correctionRatio / size
|
|
507
|
+
v_pixelToUV = u_correctionRatio / size;
|
|
508
|
+
|
|
509
|
+
// We use an antialiasing width of 1px (so v_pixelToUV)
|
|
510
|
+
v_antialiasingWidth = v_pixelToUV;
|
|
511
|
+
|
|
512
|
+
// Pass layer attributes to fragment shader (fetched from texture)
|
|
513
|
+
${l.varyingAssignments}
|
|
514
|
+
}
|
|
515
|
+
`}function ra(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=t.map(function(e,t){var n=`layer_${e.name}`,r=[].concat(Y(e.attributes.map(function(e){return`v_${e.name.replace(/^a_/,``)}`})),Y(e.uniforms.map(function(e){return e.name}))).join(`, `);return` // Layer ${t+1}: ${e.name}
|
|
516
|
+
color = blendOver(color, ${n}(${r}));`}).join(`
|
|
517
|
+
|
|
518
|
+
`),a=new Set([`u_correctionRatio`]),o=new Set,s=e.flatMap(function(e){return e.uniforms}).filter(function(e){return a.has(e.name)||o.has(e.name)?!1:(o.add(e.name),!0)}).map(function(e){return`uniform ${e.type} ${e.name};`}).join(`
|
|
519
|
+
`),c=t.flatMap(function(e){return e.uniforms}).filter(function(e){return a.has(e.name)||o.has(e.name)?!1:(o.add(e.name),!0)}).map(function(e){return`uniform ${e.type} ${e.name};`}).join(`
|
|
520
|
+
`),l=new Set;return`#version 300 es
|
|
521
|
+
precision highp float;
|
|
522
|
+
|
|
523
|
+
// Standard varyings
|
|
524
|
+
in vec2 v_uv;
|
|
525
|
+
in vec4 v_id;
|
|
526
|
+
in float v_opacity;
|
|
527
|
+
in float v_antialiasingWidth;
|
|
528
|
+
in float v_pixelSize;
|
|
529
|
+
in float v_pixelToUV;
|
|
530
|
+
in float v_shapeId; // Shape ID for multi-shape programs
|
|
531
|
+
|
|
532
|
+
// Standard uniforms (needed for some layer calculations like pixel-mode borders)
|
|
533
|
+
uniform float u_correctionRatio;
|
|
534
|
+
#ifdef PICKING_MODE
|
|
535
|
+
uniform float u_pickingPadding;
|
|
536
|
+
#endif
|
|
537
|
+
|
|
538
|
+
// Shape uniforms
|
|
539
|
+
${s}
|
|
540
|
+
|
|
541
|
+
// Layer uniforms
|
|
542
|
+
${c}
|
|
543
|
+
|
|
544
|
+
// Layer varyings
|
|
545
|
+
${ea(e,t).flatMap(function(e){return e.attributes}).filter(function(e){var t=e.name.replace(/^a_/,``);return!l.has(t)&&(l.add(t),!0)}).map(function(e){var t=e.name.replace(/^a_/,``);return`in ${e.size===1?`float`:`vec${e.size}`} v_${t};`}).join(`
|
|
546
|
+
`)}
|
|
547
|
+
|
|
548
|
+
// Fragment output (single target - picking handled via separate pass)
|
|
549
|
+
out vec4 fragColor;
|
|
550
|
+
|
|
551
|
+
// LayerContext struct - provides rendering context to all layers
|
|
552
|
+
struct LayerContext {
|
|
553
|
+
float sdf; // Signed distance from shape boundary (negative inside)
|
|
554
|
+
vec2 uv; // UV coordinates [-1, 1], center at (0,0)
|
|
555
|
+
float shapeSize; // Effective shape size (~diameter) in UV space (1.0 - aaWidth)
|
|
556
|
+
float shapeHalfSize; // Effective shape half size (~radius) in UV space
|
|
557
|
+
float pixelSize; // Node full size (~diameter) in screen pixels
|
|
558
|
+
float aaWidth; // Anti-aliasing width for smooth transitions
|
|
559
|
+
float correctionRatio; // Scaling factor for consistent rendering across zoom levels
|
|
560
|
+
float pixelToUV; // Conversion factor: multiply screen pixels by this to get UV units
|
|
561
|
+
float inradiusFactor; // Ratio of inradius to circumradius (shape depth factor)
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
LayerContext context; // Global instance, populated before layer calls
|
|
565
|
+
|
|
566
|
+
// Alpha "over" compositing for layer blending
|
|
567
|
+
vec4 blendOver(vec4 bg, vec4 fg) {
|
|
568
|
+
float a = fg.a;
|
|
569
|
+
return vec4(mix(bg.rgb, fg.rgb, a), bg.a + a * (1.0 - bg.a));
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// SDF shape functions
|
|
573
|
+
${mi(e)}
|
|
574
|
+
|
|
575
|
+
// Shape selector function (sets context.sdf and context.inradiusFactor)
|
|
576
|
+
${gi(e,n)}
|
|
577
|
+
|
|
578
|
+
// Layer functions
|
|
579
|
+
${t.map(function(e){return e.glsl}).join(`
|
|
580
|
+
|
|
581
|
+
`)}
|
|
582
|
+
|
|
583
|
+
void main() {
|
|
584
|
+
// 1. Setup LayerContext (available to all layer functions)
|
|
585
|
+
context.shapeSize = 1.0 - v_antialiasingWidth;
|
|
586
|
+
context.shapeHalfSize = context.shapeSize * 0.5;
|
|
587
|
+
context.pixelSize = v_pixelSize;
|
|
588
|
+
context.uv = v_uv;
|
|
589
|
+
context.aaWidth = v_antialiasingWidth;
|
|
590
|
+
context.correctionRatio = u_correctionRatio;
|
|
591
|
+
context.pixelToUV = v_pixelToUV;
|
|
592
|
+
|
|
593
|
+
// Query shape SDF based on shapeId (sets context.sdf and context.inradiusFactor)
|
|
594
|
+
queryNodeSDF(int(v_shapeId), v_uv, context.shapeSize);
|
|
595
|
+
|
|
596
|
+
// 2. Early discard for pixels fully outside the shape (with AA margin)
|
|
597
|
+
// In PICKING_MODE, allow extra fragments up to the picking padding distance
|
|
598
|
+
#ifdef PICKING_MODE
|
|
599
|
+
if (context.sdf > u_pickingPadding * v_pixelToUV + context.aaWidth) discard;
|
|
600
|
+
#else
|
|
601
|
+
if (context.sdf > context.aaWidth) discard;
|
|
602
|
+
#endif
|
|
603
|
+
|
|
604
|
+
// 3. Apply layers sequentially with "over" compositing
|
|
605
|
+
vec4 color = vec4(0.0);
|
|
606
|
+
|
|
607
|
+
${i}
|
|
608
|
+
|
|
609
|
+
#ifdef PICKING_MODE
|
|
610
|
+
// Picking pass: output node ID for pixels within the picking area.
|
|
611
|
+
if (context.sdf > u_pickingPadding * v_pixelToUV) discard;
|
|
612
|
+
fragColor = v_id;
|
|
613
|
+
#else
|
|
614
|
+
${r?` // Visual pass: apply antialiasing at shape boundary, node opacity once
|
|
615
|
+
// smoothstep provides smooth transition from opaque to transparent
|
|
616
|
+
float alpha = smoothstep(context.aaWidth, -context.aaWidth, context.sdf) * v_opacity;`:` // Visual pass: hard-edged (no anti-aliasing gradient) shape boundary, node opacity applied once
|
|
617
|
+
float alpha = (context.sdf < 0.0 ? 1.0 : 0.0) * v_opacity;`}
|
|
618
|
+
// Mix with transparent to fade both color AND alpha together (avoids bright halo)
|
|
619
|
+
fragColor = mix(vec4(0.0), color, alpha);
|
|
620
|
+
#endif
|
|
621
|
+
}
|
|
622
|
+
`}function ia(e,t){var n=new Set;return n.add(`u_matrix`),n.add(`u_sizeRatio`),n.add(`u_correctionRatio`),n.add(`u_cameraAngle`),n.add(`u_pickingPadding`),n.add(`u_nodeDataTexture`),n.add(`u_nodeDataTextureWidth`),n.add(`u_layerAttributeTexture`),n.add(`u_layerAttributeTextureWidth`),n.add(`u_layerAttributeTexelsPerNode`),e.forEach(function(e){e.uniforms.forEach(function(e){return n.add(e.name)})}),t.forEach(function(e){e.uniforms.forEach(function(e){return n.add(e.name)})}),Array.from(n)}function aa(e){var t=WebGL2RenderingContext,n=t.UNSIGNED_BYTE,r=t.FLOAT;return[{name:`a_nodeIndex`,size:1,type:r},{name:`a_id`,size:4,type:n,normalized:!0},{name:`a_opacity`,size:1,type:r}]}function oa(e){var t=e.shapes,n=e.layers,r=e.shapeGlobalIds,i=e.antialias,a=i===void 0||i;return{vertexShader:na(t,n),fragmentShader:ra(t,n,r,a),uniforms:ia(t,n),attributes:aa()}}function sa(e,t,n){var r=ta(e,t).specs;return Object.keys(r).map(function(e){return`flat ${n} ${r[e].size===1?`float`:`vec${r[e].size}`} v_${e};`}).join(`
|
|
623
|
+
`)}function ca(e){var t=e.shapes,n=e.layers,r=e.shapeGlobalIds,i=Wi(ta(t,n),{varPrefix:`nodeAttr`,baseTexelExpr:`nodeIdx * u_layerAttributeTexelsPerNode`,textureWidthUniform:`u_layerAttributeTextureWidth`,textureSamplerUniform:`u_layerAttributeTexture`}),a=t.length===1?`float inradiusFactor = ${Z(t[0].inradiusFactor??1)};`:`float inradiusFactor = ${Z(t[0].inradiusFactor??1)};
|
|
624
|
+
switch (int(shapeId)) {
|
|
625
|
+
${t.map(function(e,t){return` case ${r?r[t]:t}: inradiusFactor = ${Z(e.inradiusFactor??1)}; break;`}).join(`
|
|
626
|
+
`)}
|
|
627
|
+
default: break;
|
|
628
|
+
}`;return`#version 300 es
|
|
629
|
+
|
|
630
|
+
in float a_nodeIndex;
|
|
631
|
+
in float a_labelWidth;
|
|
632
|
+
in float a_labelHeight;
|
|
633
|
+
in float a_textHeight;
|
|
634
|
+
in float a_positionMode;
|
|
635
|
+
in float a_labelAngle;
|
|
636
|
+
in vec4 a_backdropColor;
|
|
637
|
+
in vec4 a_backdropShadowColor;
|
|
638
|
+
in float a_backdropShadowBlur;
|
|
639
|
+
in float a_backdropPadding;
|
|
640
|
+
in vec4 a_backdropBorderColor;
|
|
641
|
+
in vec4 a_backdropExtra; // [borderWidth, cornerRadius, labelPadding, area]
|
|
642
|
+
in vec2 a_labelBoxOffset;
|
|
643
|
+
in vec2 a_quadCorner;
|
|
644
|
+
|
|
645
|
+
uniform mat3 u_matrix;
|
|
646
|
+
uniform float u_sizeRatio;
|
|
647
|
+
uniform float u_correctionRatio;
|
|
648
|
+
uniform float u_cameraAngle;
|
|
649
|
+
uniform vec2 u_resolution;
|
|
650
|
+
uniform float u_pixelRatio;
|
|
651
|
+
uniform float u_labelMargin;
|
|
652
|
+
uniform float u_zoomLabelSizeRatio;
|
|
653
|
+
uniform float u_labelPixelSnapping;
|
|
654
|
+
uniform sampler2D u_nodeDataTexture;
|
|
655
|
+
uniform int u_nodeDataTextureWidth;
|
|
656
|
+
uniform sampler2D u_nodeFrameTexture;
|
|
657
|
+
uniform int u_nodeFrameTextureWidth;
|
|
658
|
+
uniform sampler2D u_layerAttributeTexture;
|
|
659
|
+
uniform int u_layerAttributeTextureWidth;
|
|
660
|
+
uniform int u_layerAttributeTexelsPerNode;
|
|
661
|
+
|
|
662
|
+
out vec2 v_uv;
|
|
663
|
+
out vec2 v_nodeCenter;
|
|
664
|
+
out float v_nodeRadius;
|
|
665
|
+
out vec2 v_labelCenter;
|
|
666
|
+
out vec2 v_labelHalfSize;
|
|
667
|
+
out float v_aaWidth;
|
|
668
|
+
out float v_shapeId;
|
|
669
|
+
out float v_nodeRotation;
|
|
670
|
+
out float v_labelAngle;
|
|
671
|
+
out vec4 v_backdropColor;
|
|
672
|
+
out vec4 v_backdropShadowColor;
|
|
673
|
+
out float v_backdropShadowBlur;
|
|
674
|
+
out float v_backdropPadding;
|
|
675
|
+
out vec4 v_backdropBorderColor;
|
|
676
|
+
out float v_backdropBorderWidth;
|
|
677
|
+
out float v_backdropCornerRadius;
|
|
678
|
+
out float v_backdropArea;
|
|
679
|
+
${sa(t,n,`out`)}
|
|
680
|
+
|
|
681
|
+
${Ei}
|
|
682
|
+
${Di}
|
|
683
|
+
${ki}
|
|
684
|
+
|
|
685
|
+
void main() {
|
|
686
|
+
int nodeIdx = int(a_nodeIndex);
|
|
687
|
+
${i.fetchCode}
|
|
688
|
+
${i.varyingAssignments}
|
|
689
|
+
|
|
690
|
+
// Node data: (x, y, size, shapeId). shapeId (global) is forwarded to the
|
|
691
|
+
// fragment shader, which keeps the shape SDF for the outline.
|
|
692
|
+
vec4 nodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx);
|
|
693
|
+
vec2 nodePosition = nodeData.xy;
|
|
694
|
+
float nodeSize = nodeData.z;
|
|
695
|
+
float shapeId = nodeData.w;
|
|
696
|
+
|
|
697
|
+
// Per-node rotation alignment (0 = viewport, 1 = graph). nodeRotation drives
|
|
698
|
+
// the fragment's shape outline; labelRotation turns the label box with camera.
|
|
699
|
+
vec4 nodeFlags = readNodeFlags(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx);
|
|
700
|
+
float nodeRotation = nodeFlags.r;
|
|
701
|
+
float labelRotation = nodeFlags.g;
|
|
702
|
+
v_nodeRotation = nodeRotation;
|
|
703
|
+
|
|
704
|
+
${vi}
|
|
705
|
+
// CSS pixel attributes are multiplied by u_pixelRatio to match nodeRadiusPixels,
|
|
706
|
+
// which is already in physical pixels (nodeRadiusNDC * u_resolution.x / 2.0).
|
|
707
|
+
float padding = a_backdropPadding * u_pixelRatio;
|
|
708
|
+
float shadowBlur = a_backdropShadowBlur * u_pixelRatio;
|
|
709
|
+
// Unpack a_backdropExtra: [borderWidth, cornerRadius, labelPadding, area]
|
|
710
|
+
float borderWidth = a_backdropExtra.x * u_pixelRatio;
|
|
711
|
+
float cornerRadius = a_backdropExtra.y * u_pixelRatio;
|
|
712
|
+
float labelPad = a_backdropExtra.z * u_pixelRatio;
|
|
713
|
+
float backdropArea = a_backdropExtra.w;
|
|
714
|
+
// Use 2x shadowBlur so the Gaussian fully decays before the quad edge
|
|
715
|
+
float totalExpansion = shadowBlur * 2.0 + borderWidth;
|
|
716
|
+
float enlargedRadius = nodeRadiusPixels + padding;
|
|
717
|
+
|
|
718
|
+
// Circumscribed radius for the quad bounds. Non-circular shapes reach past
|
|
719
|
+
// their inradius out to their circumradius (= enlargedRadius / inradiusFactor),
|
|
720
|
+
// in any direction once rotated. The axis-aligned quad must contain that, or
|
|
721
|
+
// the fill/shadow gets clipped (square corners, triangle tip, etc.).
|
|
722
|
+
${a}
|
|
723
|
+
float boundRadius = enlargedRadius / inradiusFactor;
|
|
724
|
+
|
|
725
|
+
// Apply zoom-dependent label size scaling
|
|
726
|
+
float zoomScale = u_zoomLabelSizeRatio;
|
|
727
|
+
float labelW = a_labelWidth * zoomScale * u_pixelRatio;
|
|
728
|
+
float labelH = a_labelHeight * zoomScale * u_pixelRatio;
|
|
729
|
+
float labelMargin = u_labelMargin * zoomScale * u_pixelRatio;
|
|
730
|
+
|
|
731
|
+
// Only apply labelPad when a label is actually present
|
|
732
|
+
float effectiveLabelPad = labelW > 0.0 ? labelPad : 0.0;
|
|
733
|
+
vec2 labelHalfSize = vec2(labelW * 0.5 + effectiveLabelPad, labelH * 0.5 + effectiveLabelPad);
|
|
734
|
+
vec2 labelOffset = vec2(0.0);
|
|
735
|
+
|
|
736
|
+
// Effective label angle: intrinsic angle plus the camera angle when the label
|
|
737
|
+
// is graph-aligned, so the box orbits the node in lockstep with the frame-pass.
|
|
738
|
+
float labelAngle = a_labelAngle - labelRotation * u_cameraAngle;
|
|
739
|
+
float la_c = cos(labelAngle);
|
|
740
|
+
float la_s = sin(labelAngle);
|
|
741
|
+
mat2 labelRotMat = mat2(la_c, -la_s, la_s, la_c);
|
|
742
|
+
|
|
743
|
+
vec3 nodeClip = u_matrix * vec3(nodePosition, 1.0);
|
|
744
|
+
vec2 snapDelta = vec2(0.0);
|
|
745
|
+
|
|
746
|
+
if (labelW > 0.0) {
|
|
747
|
+
// labelW > 0.0 means this node's label is displayed, so the frame-pass wrote
|
|
748
|
+
// its edge distance this frame.
|
|
749
|
+
float edgeDistPixels = nodeRadiusPixels * readFrameTexel(u_nodeFrameTexture, u_nodeFrameTextureWidth, nodeIdx).r;
|
|
750
|
+
// labelMargin matches the label shader's margin (gap from node edge to text)
|
|
751
|
+
float labelStart = edgeDistPixels + labelMargin;
|
|
752
|
+
// Above/below center on the actual glyph height, not the font line box, so
|
|
753
|
+
// the box stays aligned with the rendered text (matches labelBoxCenter()).
|
|
754
|
+
float textHalf = a_textHeight * zoomScale * u_pixelRatio * 0.5;
|
|
755
|
+
|
|
756
|
+
// Snap node center to pixel grid so label/backdrop/attachment move as a unit
|
|
757
|
+
vec2 nodeScreen = vec2(
|
|
758
|
+
(nodeClip.x + 1.0) * u_resolution.x,
|
|
759
|
+
(1.0 - nodeClip.y) * u_resolution.y
|
|
760
|
+
) * 0.5;
|
|
761
|
+
snapDelta = (round(nodeScreen) - nodeScreen) * u_labelPixelSnapping;
|
|
762
|
+
|
|
763
|
+
if (a_positionMode < 0.5) {
|
|
764
|
+
// Right: box spans from node center to text end + padding
|
|
765
|
+
float boxRightEdge = labelStart + labelW + labelPad;
|
|
766
|
+
labelOffset = vec2(boxRightEdge * 0.5, 0.0);
|
|
767
|
+
labelHalfSize.x = boxRightEdge * 0.5;
|
|
768
|
+
} else if (a_positionMode < 1.5) {
|
|
769
|
+
// Left: mirror of right
|
|
770
|
+
float boxLeftEdge = labelStart + labelW + labelPad;
|
|
771
|
+
labelOffset = vec2(-boxLeftEdge * 0.5, 0.0);
|
|
772
|
+
labelHalfSize.x = boxLeftEdge * 0.5;
|
|
773
|
+
} else if (a_positionMode < 2.5) {
|
|
774
|
+
// Above: text bottom at labelStart, centered horizontally
|
|
775
|
+
labelOffset = vec2(0.0, -(labelStart + textHalf));
|
|
776
|
+
} else if (a_positionMode < 3.5) {
|
|
777
|
+
// Below: text top at labelStart, centered horizontally
|
|
778
|
+
labelOffset = vec2(0.0, labelStart + textHalf);
|
|
779
|
+
}
|
|
780
|
+
// over (>=4): labelOffset stays (0,0) — text centered on the node.
|
|
781
|
+
|
|
782
|
+
// The attachment-cover shift is in label space (like the attachment itself),
|
|
783
|
+
// so rotate it together with the position offset — otherwise the box drifts
|
|
784
|
+
// off the attachment as the label angle grows.
|
|
785
|
+
labelOffset = labelRotMat * (labelOffset + a_labelBoxOffset * zoomScale * u_pixelRatio);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// For node-only mode, zero out label dimensions
|
|
789
|
+
if (backdropArea > 0.5 && backdropArea < 1.5) {
|
|
790
|
+
labelHalfSize = vec2(0.0);
|
|
791
|
+
labelOffset = vec2(0.0);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
vec2 minBound, maxBound;
|
|
795
|
+
|
|
796
|
+
bool hasLabelBounds = labelW > 0.0 && (backdropArea > 1.5 || backdropArea < 0.5);
|
|
797
|
+
|
|
798
|
+
if (hasLabelBounds) {
|
|
799
|
+
// Union with label bounds (area=both) or label-only bounds (area=label)
|
|
800
|
+
vec2 labelMin, labelMax;
|
|
801
|
+
|
|
802
|
+
if (a_labelAngle != 0.0) {
|
|
803
|
+
vec2 corner1 = labelOffset + labelRotMat * vec2(-labelHalfSize.x, -labelHalfSize.y);
|
|
804
|
+
vec2 corner2 = labelOffset + labelRotMat * vec2(labelHalfSize.x, -labelHalfSize.y);
|
|
805
|
+
vec2 corner3 = labelOffset + labelRotMat * vec2(labelHalfSize.x, labelHalfSize.y);
|
|
806
|
+
vec2 corner4 = labelOffset + labelRotMat * vec2(-labelHalfSize.x, labelHalfSize.y);
|
|
807
|
+
labelMin = min(min(corner1, corner2), min(corner3, corner4));
|
|
808
|
+
labelMax = max(max(corner1, corner2), max(corner3, corner4));
|
|
809
|
+
} else {
|
|
810
|
+
labelMin = labelOffset - labelHalfSize;
|
|
811
|
+
labelMax = labelOffset + labelHalfSize;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
if (backdropArea > 1.5) {
|
|
815
|
+
// Label-only: bounds from label rect only
|
|
816
|
+
minBound = labelMin - totalExpansion;
|
|
817
|
+
maxBound = labelMax + totalExpansion;
|
|
818
|
+
} else {
|
|
819
|
+
// Both: union of node + label
|
|
820
|
+
minBound = min(-vec2(boundRadius), labelMin) - totalExpansion;
|
|
821
|
+
maxBound = max(vec2(boundRadius), labelMax) + totalExpansion;
|
|
822
|
+
}
|
|
823
|
+
} else {
|
|
824
|
+
// Node-only or no visible label
|
|
825
|
+
float totalRadius = boundRadius + totalExpansion;
|
|
826
|
+
minBound = -vec2(totalRadius);
|
|
827
|
+
maxBound = vec2(totalRadius);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
vec2 quadSize = maxBound - minBound;
|
|
831
|
+
vec2 quadCenter = (minBound + maxBound) * 0.5;
|
|
832
|
+
|
|
833
|
+
vec2 localPos = quadCenter + a_quadCorner * quadSize * 0.5 + snapDelta;
|
|
834
|
+
vec2 ndcOffset = localPos * 2.0 / u_resolution;
|
|
835
|
+
ndcOffset.y = -ndcOffset.y;
|
|
836
|
+
|
|
837
|
+
gl_Position = vec4(nodeClip.xy + ndcOffset, 0.0, 1.0);
|
|
838
|
+
|
|
839
|
+
v_uv = localPos;
|
|
840
|
+
v_nodeCenter = vec2(0.0);
|
|
841
|
+
v_nodeRadius = nodeRadiusPixels;
|
|
842
|
+
v_labelCenter = labelOffset;
|
|
843
|
+
v_labelHalfSize = labelHalfSize;
|
|
844
|
+
v_aaWidth = 1.0;
|
|
845
|
+
v_shapeId = shapeId;
|
|
846
|
+
v_labelAngle = labelAngle;
|
|
847
|
+
v_backdropColor = a_backdropColor;
|
|
848
|
+
v_backdropShadowColor = a_backdropShadowColor;
|
|
849
|
+
v_backdropShadowBlur = a_backdropShadowBlur;
|
|
850
|
+
v_backdropPadding = a_backdropPadding;
|
|
851
|
+
v_backdropBorderColor = a_backdropBorderColor;
|
|
852
|
+
v_backdropBorderWidth = borderWidth;
|
|
853
|
+
v_backdropCornerRadius = cornerRadius;
|
|
854
|
+
v_backdropArea = backdropArea;
|
|
855
|
+
}
|
|
856
|
+
`}function la(e){var t=e.shapes,n=e.layers,r=e.shapeGlobalIds,i=mi(t),a=hi(t).map(function(e){return`uniform ${e.type} ${e.name};`}).join(`
|
|
857
|
+
`),o=function(e){return si(e,`nodeUV`,`1.0`)},s=t.length===1?`float nodeSdfNormalized = ${o(t[0])};`:`float nodeSdfNormalized;
|
|
858
|
+
int shapeId = int(v_shapeId);
|
|
859
|
+
switch (shapeId) {
|
|
860
|
+
${t.map(function(e,t){return` case ${r?r[t]:t}: nodeSdfNormalized = ${o(e)}; break;`}).join(`
|
|
861
|
+
`)}
|
|
862
|
+
default: nodeSdfNormalized = ${o(t[0])};
|
|
863
|
+
}`;return`#version 300 es
|
|
864
|
+
precision highp float;
|
|
865
|
+
|
|
866
|
+
in vec2 v_uv;
|
|
867
|
+
in vec2 v_nodeCenter;
|
|
868
|
+
in float v_nodeRadius;
|
|
869
|
+
in vec2 v_labelCenter;
|
|
870
|
+
in vec2 v_labelHalfSize;
|
|
871
|
+
in float v_aaWidth;
|
|
872
|
+
in float v_shapeId;
|
|
873
|
+
in float v_nodeRotation;
|
|
874
|
+
in float v_labelAngle;
|
|
875
|
+
in vec4 v_backdropColor;
|
|
876
|
+
in vec4 v_backdropShadowColor;
|
|
877
|
+
in float v_backdropShadowBlur;
|
|
878
|
+
in float v_backdropPadding;
|
|
879
|
+
in vec4 v_backdropBorderColor;
|
|
880
|
+
in float v_backdropBorderWidth;
|
|
881
|
+
in float v_backdropCornerRadius;
|
|
882
|
+
in float v_backdropArea;
|
|
883
|
+
${sa(t,n,`in`)}
|
|
884
|
+
|
|
885
|
+
uniform float u_cameraAngle;
|
|
886
|
+
${a}
|
|
887
|
+
|
|
888
|
+
layout(location = 0) out vec4 fragColor;
|
|
889
|
+
layout(location = 1) out vec4 fragPicking;
|
|
890
|
+
|
|
891
|
+
${i}
|
|
892
|
+
${xi}
|
|
893
|
+
${Si}
|
|
894
|
+
${Ci}
|
|
895
|
+
${wi}
|
|
896
|
+
|
|
897
|
+
void main() {
|
|
898
|
+
vec4 backdropColor = v_backdropColor;
|
|
899
|
+
vec4 shadowColor = v_backdropShadowColor;
|
|
900
|
+
float shadowBlur = v_backdropShadowBlur;
|
|
901
|
+
float padding = v_backdropPadding;
|
|
902
|
+
vec4 borderColor = v_backdropBorderColor;
|
|
903
|
+
float borderWidth = v_backdropBorderWidth;
|
|
904
|
+
float cornerRadius = v_backdropCornerRadius;
|
|
905
|
+
|
|
906
|
+
float enlargedRadius = v_nodeRadius + padding;
|
|
907
|
+
vec2 screenUV = v_uv - v_nodeCenter;
|
|
908
|
+
float effectiveRadius = max(enlargedRadius - cornerRadius, 0.01);
|
|
909
|
+
float ca = u_cameraAngle * v_nodeRotation;
|
|
910
|
+
float ca_c = cos(ca);
|
|
911
|
+
float ca_s = sin(ca);
|
|
912
|
+
vec2 rotatedScreenUV = mat2(ca_c, -ca_s, ca_s, ca_c) * screenUV;
|
|
913
|
+
vec2 nodeUV = vec2(rotatedScreenUV.x, -rotatedScreenUV.y) / effectiveRadius;
|
|
914
|
+
|
|
915
|
+
// Query the correct shape SDF based on shapeId
|
|
916
|
+
${s}
|
|
917
|
+
float nodeSdfPixels = nodeSdfNormalized * effectiveRadius - cornerRadius;
|
|
918
|
+
|
|
919
|
+
// Label SDF with optional corner radius and rotation
|
|
920
|
+
float labelSdfPixels;
|
|
921
|
+
if (v_labelHalfSize.x > 0.0) {
|
|
922
|
+
vec2 labelP = v_uv - v_labelCenter;
|
|
923
|
+
labelSdfPixels = sdfRoundedRotatedBox(labelP, v_labelHalfSize, v_labelAngle, cornerRadius);
|
|
924
|
+
} else {
|
|
925
|
+
labelSdfPixels = 10000.0;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
// Select area: 0=both, 1=node, 2=label
|
|
929
|
+
float combinedSdf;
|
|
930
|
+
if (v_backdropArea > 1.5) {
|
|
931
|
+
combinedSdf = labelSdfPixels;
|
|
932
|
+
} else if (v_backdropArea > 0.5) {
|
|
933
|
+
combinedSdf = nodeSdfPixels;
|
|
934
|
+
} else {
|
|
935
|
+
combinedSdf = min(nodeSdfPixels, labelSdfPixels);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Fill + border composite
|
|
939
|
+
float outerEdge = smoothstep(v_aaWidth, -v_aaWidth, combinedSdf);
|
|
940
|
+
vec4 background;
|
|
941
|
+
if (borderWidth > 0.5) {
|
|
942
|
+
float innerEdge = smoothstep(v_aaWidth, -v_aaWidth, combinedSdf + borderWidth);
|
|
943
|
+
float fillAlpha = innerEdge * backdropColor.a;
|
|
944
|
+
vec4 fill = vec4(backdropColor.rgb * fillAlpha, fillAlpha);
|
|
945
|
+
float borderAlpha = (outerEdge - innerEdge) * borderColor.a;
|
|
946
|
+
vec4 border = vec4(borderColor.rgb * borderAlpha, borderAlpha);
|
|
947
|
+
background = fill + border * (1.0 - fill.a);
|
|
948
|
+
} else {
|
|
949
|
+
float fillAlpha = outerEdge * backdropColor.a;
|
|
950
|
+
background = vec4(backdropColor.rgb * fillAlpha, fillAlpha);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
// Gaussian-like shadow falloff (mimics canvas shadowBlur)
|
|
954
|
+
vec4 shadow = vec4(0.0);
|
|
955
|
+
float sigma = shadowBlur / 2.5;
|
|
956
|
+
if (sigma > 0.001) {
|
|
957
|
+
float shadowDist = max(0.0, combinedSdf);
|
|
958
|
+
float shadowAlpha = exp(-(shadowDist * shadowDist) / (2.0 * sigma * sigma)) * shadowColor.a;
|
|
959
|
+
shadow = vec4(shadowColor.rgb * shadowAlpha, shadowAlpha);
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
fragColor = background + shadow * (1.0 - background.a);
|
|
963
|
+
fragPicking = vec4(0.0);
|
|
964
|
+
}
|
|
965
|
+
`}function ua(e){var t=[`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_cameraAngle`,`u_resolution`,`u_pixelRatio`,`u_labelMargin`,`u_zoomLabelSizeRatio`,`u_labelPixelSnapping`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_nodeFrameTexture`,`u_nodeFrameTextureWidth`,`u_layerAttributeTexture`,`u_layerAttributeTextureWidth`,`u_layerAttributeTexelsPerNode`],n=H(hi(e)),r;try{for(n.s();!(r=n.n()).done;){var i=r.value;t.includes(i.name)||t.push(i.name)}}catch(e){n.e(e)}finally{n.f()}return t}function da(e){return{vertexShader:ca(e),fragmentShader:la(e),uniforms:ua(e.shapes)}}function fa(e,t,n,r){var i=r.label,a=i===void 0?{}:i,o=r.shapes,s=r.layers,c=r.getAttributeTexture,l=r.shapeGlobalIds;if(o.length===0)throw Error(`createBackdropProgram: at least one shape must be provided in 'shapes'`);var u=a.margin??5,d=a.zoomToLabelSizeRatioFunction??function(){return 1},f=da({shapes:o,layers:s,shapeGlobalIds:l}),p=function(e){function t(){var e;G(this,t);var n=[...arguments];return e=q(this,t,[].concat(n)),U(e,`totalBackdropCount`,0),U(e,`bufferCapacity`,0),e}return J(t,e),K(t,[{key:`getDefinition`,value:function(){var e=WebGL2RenderingContext,t=e.FLOAT,n=e.TRIANGLE_STRIP;return{VERTICES:4,VERTEX_SHADER_SOURCE:f.vertexShader,FRAGMENT_SHADER_SOURCE:f.fragmentShader,METHOD:n,UNIFORMS:f.uniforms,ATTRIBUTES:[{name:`a_nodeIndex`,size:1,type:t},{name:`a_labelWidth`,size:1,type:t},{name:`a_labelHeight`,size:1,type:t},{name:`a_textHeight`,size:1,type:t},{name:`a_positionMode`,size:1,type:t},{name:`a_labelAngle`,size:1,type:t},{name:`a_backdropColor`,size:4,type:t},{name:`a_backdropShadowColor`,size:4,type:t},{name:`a_backdropShadowBlur`,size:1,type:t},{name:`a_backdropPadding`,size:1,type:t},{name:`a_backdropBorderColor`,size:4,type:t},{name:`a_backdropExtra`,size:4,type:t},{name:`a_labelBoxOffset`,size:2,type:t}],CONSTANT_ATTRIBUTES:[{name:`a_quadCorner`,size:2,type:t}],CONSTANT_DATA:[[-1,-1],[1,-1],[-1,1],[1,1]]}}},{key:`processBackdrop`,value:function(e,t){var n=this.floats,r=e*this.STRIDE;n[r++]=t.nodeIndex,n[r++]=t.labelWidth,n[r++]=t.labelHeight,n[r++]=t.textHeight,n[r++]=_i[t.position],n[r++]=t.labelAngle,n[r++]=t.backdropColor[0],n[r++]=t.backdropColor[1],n[r++]=t.backdropColor[2],n[r++]=t.backdropColor[3],n[r++]=t.backdropShadowColor[0],n[r++]=t.backdropShadowColor[1],n[r++]=t.backdropShadowColor[2],n[r++]=t.backdropShadowColor[3],n[r++]=t.backdropShadowBlur,n[r++]=t.backdropPadding,n[r++]=t.backdropBorderColor[0],n[r++]=t.backdropBorderColor[1],n[r++]=t.backdropBorderColor[2],n[r++]=t.backdropBorderColor[3],n[r++]=t.backdropBorderWidth,n[r++]=t.backdropCornerRadius,n[r++]=t.backdropLabelPadding,n[r++]=t.backdropArea,n[r++]=t.labelBoxOffset[0],n[r++]=t.labelBoxOffset[1]}},{key:`setUniforms`,value:function(e,n){var r=n.gl,i=n.uniformLocations;r.uniformMatrix3fv(i.u_matrix,!1,e.matrix),r.uniform1f(i.u_sizeRatio,e.sizeRatio),r.uniform1f(i.u_correctionRatio,e.correctionRatio),r.uniform1f(i.u_cameraAngle,e.cameraAngle),r.uniform2f(i.u_resolution,e.width*e.pixelRatio,e.height*e.pixelRatio),r.uniform1f(i.u_pixelRatio,e.pixelRatio),r.uniform1f(i.u_labelMargin,t.labelMargin),r.uniform1f(i.u_zoomLabelSizeRatio,1/d(e.zoomRatio)),r.uniform1f(i.u_labelPixelSnapping,e.labelPixelSnapping),r.uniform1i(i.u_nodeDataTexture,e.nodeDataTextureUnit),r.uniform1i(i.u_nodeDataTextureWidth,e.nodeDataTextureWidth),r.uniform1i(i.u_nodeFrameTexture,e.nodeFrameTextureUnit),r.uniform1i(i.u_nodeFrameTextureWidth,e.nodeFrameTextureWidth);var a=c();i.u_layerAttributeTexture&&a&&(a.bind($i),r.uniform1i(i.u_layerAttributeTexture,$i),r.uniform1i(i.u_layerAttributeTextureWidth,a.getTextureWidth()),r.uniform1i(i.u_layerAttributeTexelsPerNode,a.getTexelsPerItem()));var s=H(hi(o)),l;try{for(s.s();!(l=s.n()).done;){var u=l.value;this.setTypedUniform(u,n)}}catch(e){s.e(e)}finally{s.f()}}},{key:`hasNothingToRender`,value:function(){return this.totalBackdropCount===0}},{key:`drawWebGL`,value:function(e,t){var n=t.gl;this.totalBackdropCount!==0&&(this.isInstanced?n.drawArraysInstanced(e,0,this.VERTICES,this.totalBackdropCount):n.drawArrays(e,0,this.totalBackdropCount*this.VERTICES))}},{key:`reallocate`,value:function(e){this.totalBackdropCount=e,e>this.bufferCapacity&&(this.bufferCapacity=Math.max(e,Math.ceil(this.bufferCapacity*1.5)||10),Q(t,`reallocate`,this,3)([this.bufferCapacity]))}}])}(Ji);return U(p,`labelMargin`,u),new p(e,t,n)}var pa=function(e){function t(){var e;G(this,t);var n=[...arguments];return e=q(this,t,[].concat(n)),U(e,`totalCharacterCount`,0),U(e,`bufferCapacity`,0),e}return J(t,e),K(t,[{key:`processLabel`,value:function(e,t,n){if(n.hidden||!n.text)return 0;for(var r=n.text,i=r.length,a=0;a<i;a++){var o=r[a];this.processCharacter(t+a,n,o,a)}return i}},{key:`hasNothingToRender`,value:function(){return this.totalCharacterCount===0}},{key:`drawWebGL`,value:function(e,t){var n=t.gl;this.totalCharacterCount!==0&&(this.isInstanced?n.drawArraysInstanced(e,0,this.VERTICES,this.totalCharacterCount):n.drawArrays(e,0,this.totalCharacterCount*this.VERTICES))}},{key:`reallocate`,value:function(e){this.totalCharacterCount=e,e>this.bufferCapacity&&(this.bufferCapacity=Math.max(e,Math.ceil(this.bufferCapacity*1.5)||1e3),Q(t,`reallocate`,this,3)([this.bufferCapacity]))}}])}(Ji);function ma(){return`#version 300 es
|
|
966
|
+
|
|
967
|
+
in float a_nodeIndex;
|
|
968
|
+
in vec4 a_id;
|
|
969
|
+
in vec4 a_color;
|
|
970
|
+
in float a_labelWidth;
|
|
971
|
+
in float a_labelHeight;
|
|
972
|
+
in float a_textHeight;
|
|
973
|
+
in float a_positionMode;
|
|
974
|
+
in float a_labelAngle;
|
|
975
|
+
in float a_padding;
|
|
976
|
+
in vec2 a_quadCorner;
|
|
977
|
+
|
|
978
|
+
uniform mat3 u_matrix;
|
|
979
|
+
uniform float u_sizeRatio;
|
|
980
|
+
uniform float u_correctionRatio;
|
|
981
|
+
uniform float u_cameraAngle;
|
|
982
|
+
uniform vec2 u_resolution;
|
|
983
|
+
uniform float u_pixelRatio;
|
|
984
|
+
uniform float u_labelMargin;
|
|
985
|
+
uniform float u_zoomLabelSizeRatio;
|
|
986
|
+
uniform float u_labelPixelSnapping;
|
|
987
|
+
uniform float u_pickingPadding;
|
|
988
|
+
uniform sampler2D u_nodeDataTexture;
|
|
989
|
+
uniform int u_nodeDataTextureWidth;
|
|
990
|
+
uniform sampler2D u_nodeFrameTexture;
|
|
991
|
+
uniform int u_nodeFrameTextureWidth;
|
|
992
|
+
|
|
993
|
+
out vec4 v_id;
|
|
994
|
+
out vec4 v_color;
|
|
995
|
+
|
|
996
|
+
${Ei}
|
|
997
|
+
${Di}
|
|
998
|
+
${ki}
|
|
999
|
+
${Ti}
|
|
1000
|
+
|
|
1001
|
+
void main() {
|
|
1002
|
+
int nodeIdx = int(a_nodeIndex);
|
|
1003
|
+
|
|
1004
|
+
// Node data: (x, y, size, shapeId).
|
|
1005
|
+
vec4 nodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx);
|
|
1006
|
+
vec2 nodePosition = nodeData.xy;
|
|
1007
|
+
float nodeSize = nodeData.z;
|
|
1008
|
+
|
|
1009
|
+
// Shape-aware edge distance, read once from the shared frame texture.
|
|
1010
|
+
float edgeDist = readFrameTexel(u_nodeFrameTexture, u_nodeFrameTextureWidth, nodeIdx).r;
|
|
1011
|
+
|
|
1012
|
+
// Per-node label rotation alignment: 0 = viewport, 1 = label turns with camera.
|
|
1013
|
+
float labelRotation = readNodeFlags(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx).g;
|
|
1014
|
+
|
|
1015
|
+
${vi}
|
|
1016
|
+
|
|
1017
|
+
float zoomScale = u_zoomLabelSizeRatio;
|
|
1018
|
+
float labelW = a_labelWidth * zoomScale * u_pixelRatio;
|
|
1019
|
+
float labelH = a_labelHeight * zoomScale * u_pixelRatio;
|
|
1020
|
+
float labelMargin = u_labelMargin * zoomScale * u_pixelRatio;
|
|
1021
|
+
#ifdef PICKING_MODE
|
|
1022
|
+
float padding = u_pickingPadding * u_pixelRatio;
|
|
1023
|
+
#else
|
|
1024
|
+
float padding = a_padding * u_pixelRatio;
|
|
1025
|
+
#endif
|
|
1026
|
+
|
|
1027
|
+
if (labelW <= 0.0) {
|
|
1028
|
+
gl_Position = vec4(2.0, 0.0, 0.0, 1.0);
|
|
1029
|
+
v_id = vec4(0.0);
|
|
1030
|
+
v_color = vec4(0.0);
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
vec2 labelHalfSize = vec2(labelW * 0.5 + padding, labelH * 0.5 + padding);
|
|
1035
|
+
vec2 labelOffset = vec2(0.0);
|
|
1036
|
+
|
|
1037
|
+
// Graph-aligned labels add the camera angle so the rect orbits with the text.
|
|
1038
|
+
float labelAngle = a_labelAngle - labelRotation * u_cameraAngle;
|
|
1039
|
+
float la_c = cos(labelAngle);
|
|
1040
|
+
float la_s = sin(labelAngle);
|
|
1041
|
+
mat2 labelRotMat = mat2(la_c, -la_s, la_s, la_c);
|
|
1042
|
+
|
|
1043
|
+
vec3 nodeClip = u_matrix * vec3(nodePosition, 1.0);
|
|
1044
|
+
vec2 nodeScreen = vec2(
|
|
1045
|
+
(nodeClip.x + 1.0) * u_resolution.x,
|
|
1046
|
+
(1.0 - nodeClip.y) * u_resolution.y
|
|
1047
|
+
) * 0.5;
|
|
1048
|
+
vec2 snapDelta = (round(nodeScreen) - nodeScreen) * u_labelPixelSnapping;
|
|
1049
|
+
|
|
1050
|
+
if (a_positionMode < 4.0) {
|
|
1051
|
+
float labelStart = nodeRadiusPixels * edgeDist + labelMargin;
|
|
1052
|
+
float textHalf = a_textHeight * zoomScale * u_pixelRatio * 0.5;
|
|
1053
|
+
// Box center uses the text half-size; the padding expands the quad below.
|
|
1054
|
+
labelOffset = labelRotMat * labelBoxCenter(a_positionMode, labelStart, vec2(labelW * 0.5, labelH * 0.5), textHalf);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// Rotate the rect with the label so it stays aligned with the (rotated) text.
|
|
1058
|
+
vec2 localPos = labelOffset + labelRotMat * (a_quadCorner * labelHalfSize);
|
|
1059
|
+
vec2 ndcOffset = (localPos + snapDelta) * 2.0 / u_resolution;
|
|
1060
|
+
ndcOffset.y = -ndcOffset.y;
|
|
1061
|
+
|
|
1062
|
+
gl_Position = vec4(nodeClip.xy + ndcOffset, 0.0, 1.0);
|
|
1063
|
+
v_id = a_id;
|
|
1064
|
+
v_color = a_color;
|
|
1065
|
+
}
|
|
1066
|
+
`}var ha=`#version 300 es
|
|
1067
|
+
precision highp float;
|
|
1068
|
+
|
|
1069
|
+
in vec4 v_id;
|
|
1070
|
+
in vec4 v_color;
|
|
1071
|
+
|
|
1072
|
+
out vec4 fragColor;
|
|
1073
|
+
|
|
1074
|
+
void main() {
|
|
1075
|
+
#ifdef PICKING_MODE
|
|
1076
|
+
fragColor = v_id;
|
|
1077
|
+
#else
|
|
1078
|
+
if (v_color.a <= 0.0) discard;
|
|
1079
|
+
// v_color is non-premultiplied RGBA (0-1); convert to premultiplied for blending
|
|
1080
|
+
fragColor = vec4(v_color.rgb * v_color.a, v_color.a);
|
|
1081
|
+
#endif
|
|
1082
|
+
}
|
|
1083
|
+
`;function ga(e,t,n,r){var i=r.label,a=i===void 0?{}:i,o=a.margin??5,s=a.zoomToLabelSizeRatioFunction??function(){return 1},c=ma(),l=function(e){function t(){var e;G(this,t);var n=[...arguments];return e=q(this,t,[].concat(n)),U(e,`totalCount`,0),U(e,`bufferCapacity`,0),e}return J(t,e),K(t,[{key:`getDefinition`,value:function(){var e=WebGL2RenderingContext,t=e.FLOAT,n=e.UNSIGNED_BYTE;return{VERTICES:4,VERTEX_SHADER_SOURCE:c,FRAGMENT_SHADER_SOURCE:ha,METHOD:e.TRIANGLE_STRIP,UNIFORMS:[`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_cameraAngle`,`u_resolution`,`u_pixelRatio`,`u_labelMargin`,`u_zoomLabelSizeRatio`,`u_labelPixelSnapping`,`u_pickingPadding`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_nodeFrameTexture`,`u_nodeFrameTextureWidth`],ATTRIBUTES:[{name:`a_nodeIndex`,size:1,type:t},{name:`a_id`,size:4,type:n,normalized:!0},{name:`a_color`,size:4,type:n,normalized:!0},{name:`a_labelWidth`,size:1,type:t},{name:`a_labelHeight`,size:1,type:t},{name:`a_textHeight`,size:1,type:t},{name:`a_positionMode`,size:1,type:t},{name:`a_labelAngle`,size:1,type:t},{name:`a_padding`,size:1,type:t}],CONSTANT_ATTRIBUTES:[{name:`a_quadCorner`,size:2,type:t}],CONSTANT_DATA:[[-1,-1],[1,-1],[-1,1],[1,1]]}}},{key:`processLabelBackground`,value:function(e,t){var n=this.floats,r=this.ints,i=e*this.STRIDE;n[i++]=t.nodeIndex,r[i++]=t.id,n[i++]=t.color,n[i++]=t.labelWidth,n[i++]=t.labelHeight,n[i++]=t.textHeight,n[i++]=t.positionMode,n[i++]=t.labelAngle,n[i++]=t.padding}},{key:`setUniforms`,value:function(e,n){var r=n.gl,i=n.uniformLocations;r.uniformMatrix3fv(i.u_matrix,!1,e.matrix),r.uniform1f(i.u_sizeRatio,e.sizeRatio),r.uniform1f(i.u_correctionRatio,e.correctionRatio),r.uniform1f(i.u_cameraAngle,e.cameraAngle),r.uniform2f(i.u_resolution,e.width*e.pixelRatio,e.height*e.pixelRatio),r.uniform1f(i.u_pixelRatio,e.pixelRatio),r.uniform1f(i.u_labelMargin,t.labelMargin),r.uniform1f(i.u_zoomLabelSizeRatio,1/s(e.zoomRatio)),r.uniform1f(i.u_labelPixelSnapping,e.labelPixelSnapping),r.uniform1f(i.u_pickingPadding,e.labelPickingPadding),r.uniform1i(i.u_nodeDataTexture,e.nodeDataTextureUnit),r.uniform1i(i.u_nodeDataTextureWidth,e.nodeDataTextureWidth),r.uniform1i(i.u_nodeFrameTexture,e.nodeFrameTextureUnit),r.uniform1i(i.u_nodeFrameTextureWidth,e.nodeFrameTextureWidth)}},{key:`hasNothingToRender`,value:function(){return this.totalCount===0}},{key:`drawWebGL`,value:function(e,t){var n=t.gl;this.totalCount!==0&&n.drawArraysInstanced(n.TRIANGLE_STRIP,0,this.VERTICES,this.totalCount)}},{key:`reallocate`,value:function(e){this.totalCount=e,e>this.bufferCapacity&&(this.bufferCapacity=Math.max(e,Math.ceil(this.bufferCapacity*1.5)||10),Q(t,`reallocate`,this,3)([this.bufferCapacity]))}}])}(Ji);return U(l,`labelMargin`,o),new l(e,t,n)}var _a={fontSize:64,buffer:8,radius:24,cutoff:.25,maxTextureSize:2048,debounceTimeout:100},va=2,ya=0x56bc75e2d63100000;function ba(e,t,n,r,i){var a=e+i*4,o=document.createElement(`canvas`);o.width=a,o.height=a;var s=o.getContext(`2d`,{willReadFrequently:!0});return s.font=`${r} ${n} ${e}px ${t}`,s.textBaseline=`alphabetic`,s.textAlign=`left`,s.fillStyle=`black`,{ctx:s,canvasSize:a,gridOuter:new Float64Array(a*a),gridInner:new Float64Array(a*a),f:new Float64Array(a),z:new Float64Array(a+1),v:new Uint16Array(a)}}function xa(e,t,n,r,i){var a=e.ctx,o=e.canvasSize,s=a.measureText(t),c=s.width,l=s.actualBoundingBoxAscent,u=s.actualBoundingBoxDescent,d=s.actualBoundingBoxLeft,f=s.actualBoundingBoxRight,p=Math.ceil(l),m=Math.ceil(d),h=Math.max(0,Math.min(o-n,Math.ceil(d)+Math.ceil(f))),g=Math.min(o-n,p+Math.ceil(u)),_=h+2*n,v=g+2*n,y=Math.max(_*v,0),b=new Uint8ClampedArray(y),x={data:b,width:_,height:v,glyphWidth:h,glyphHeight:g,glyphTop:p,glyphLeft:m,glyphAdvance:c};if(h===0||g===0)return x;var S=e.gridInner,C=e.gridOuter;a.clearRect(n,n,h,g),a.fillText(t,n+m,n+p);var w=a.getImageData(n,n,h,g);C.fill(ya,0,y),S.fill(0,0,y);for(var T=0;T<g;T++)for(var E=0;E<h;E++){var D=w.data[4*(T*h+E)+3]/255;if(D!==0){var O=(T+n)*_+E+n;if(D===1)C[O]=0,S[O]=ya;else{var k=.5-D;C[O]=k>0?k*k:0,S[O]=k<0?k*k:0}}}Sa(C,0,0,_,v,_,e.f,e.v,e.z),Sa(S,n,n,h,g,_,e.f,e.v,e.z);for(var A=0;A<y;A++){var j=Math.sqrt(C[A])-Math.sqrt(S[A]);b[A]=Math.round(255-255*(j/r+i))}return x}function Sa(e,t,n,r,i,a,o,s,c){for(var l=t;l<t+r;l++)Ca(e,n*a+l,a,i,o,s,c);for(var u=n;u<n+i;u++)Ca(e,u*a+t,1,r,o,s,c)}function Ca(e,t,n,r,i,a,o){a[0]=0,o[0]=-ya,o[1]=ya,i[0]=e[t];for(var s=1,c=0,l=0;s<r;s++){i[s]=e[t+s*n];var u=s*s;do{var d=a[c];l=(i[s]-i[d]+u-d*d)/(s-d)/2}while(l<=o[c]&&--c>-1);c++,a[c]=s,o[c]=l,o[c+1]=ya}for(var f=0,p=0;f<r;f++){for(;o[p+1]<f;)p++;var m=a[p],h=f-m;e[t+f*n]=i[m]+h*h}}var wa=function(e){function t(){var e,n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};return G(this,t),e=q(this,t),U(e,`fonts`,new Map),U(e,`textures`,[]),U(e,`cursor`,{x:0,y:0,rowHeight:0,atlasIndex:0}),U(e,`pendingGlyphs`,[]),U(e,`debounceTimer`,null),e.options=W(W({},_a),n),e.canvas=document.createElement(`canvas`),e.canvas.width=e.options.maxTextureSize,e.canvas.height=e.options.maxTextureSize,e.ctx=e.canvas.getContext(`2d`,{willReadFrequently:!0}),e.measureCanvas=document.createElement(`canvas`),e.measureCtx=e.measureCanvas.getContext(`2d`),e.textures.push(e.ctx.getImageData(0,0,1,1)),e}return J(t,e),K(t,[{key:`getFontKey`,value:function(e){return`${e.family}-${e.weight}-${e.style}`}},{key:`registerFont`,value:function(e){var t=this.getFontKey(e);if(this.fonts.has(t))return t;var n=ba(this.options.fontSize,e.family,e.weight,e.style,this.options.buffer);return this.fonts.set(t,{descriptor:e,generator:n,glyphs:new Map}),t}},{key:`ensureGlyphs`,value:function(e,t){var n=this.fonts.get(t);if(!n)throw Error(`Font "${t}" is not registered. Call registerFont() first.`);var r=!1,i=H(e),a;try{for(i.s();!(a=i.n()).done;){var o=a.value.codePointAt(0);o!==void 0&&(n.glyphs.has(o)||(this.pendingGlyphs.push({fontKey:t,charCode:o}),r=!0))}}catch(e){i.e(e)}finally{i.f()}r&&this.scheduleTextureGeneration()}},{key:`measureText`,value:function(e,t){var n=this.fonts.get(t);if(!n)throw Error(`Font "${t}" is not registered.`);var r=n.descriptor,i=r.family,a=r.weight,o=r.style;return this.measureCtx.font=`${o} ${a} ${this.options.fontSize}px ${i}`,this.measureCtx.measureText(e).width}},{key:`getGlyph`,value:function(e,t){var n=this.fonts.get(t);if(n)return n.glyphs.get(e)}},{key:`getTextures`,value:function(){return this.textures}},{key:`getFontCount`,value:function(){return this.fonts.size}},{key:`getGlyphCount`,value:function(){var e=0,t=H(this.fonts.values()),n;try{for(t.s();!(n=t.n()).done;){var r=n.value;e+=r.glyphs.size}}catch(e){t.e(e)}finally{t.f()}return e}},{key:`hasPendingGlyphs`,value:function(){return this.pendingGlyphs.length>0}},{key:`flush`,value:function(){this.debounceTimer&&=(clearTimeout(this.debounceTimer),null),this.generateTextures()}},{key:`destroy`,value:function(){this.debounceTimer&&clearTimeout(this.debounceTimer),this.fonts.clear(),this.textures=[],this.pendingGlyphs=[],this.removeAllListeners()}},{key:`scheduleTextureGeneration`,value:function(){var e=this;this.debounceTimer===null&&(this.options.debounceTimeout===null?this.generateTextures():this.debounceTimer=setTimeout(function(){e.debounceTimer=null,e.generateTextures()},this.options.debounceTimeout))}},{key:`generateTextures`,value:function(){if(this.pendingGlyphs.length!==0){var e=this.options,n=e.maxTextureSize,r=e.buffer,i=e.radius,a=e.cutoff,o=H(this.pendingGlyphs),s;try{for(o.s();!(s=o.n()).done;){var c=s.value,l=c.fontKey,u=c.charCode,d=this.fonts.get(l);if(d&&!d.glyphs.has(u)){var f=String.fromCodePoint(u),p=xa(d.generator,f,r,i,a),m=p.width,h=p.height;this.cursor.x+m+va>n&&(this.cursor.x=0,this.cursor.y+=this.cursor.rowHeight+va,this.cursor.rowHeight=0),this.cursor.y+h+va>n&&(this.finalizeCurrentTexture(),this.cursor={x:0,y:0,rowHeight:0,atlasIndex:this.cursor.atlasIndex+1},this.ctx.clearRect(0,0,n,n));for(var g=p.data,_=new Uint8ClampedArray(m*h*4),v=0;v<g.length;v++){var y=v*4;_[y]=255,_[y+1]=255,_[y+2]=255,_[y+3]=g[v]}var b=new ImageData(_,m,h);this.ctx.putImageData(b,this.cursor.x,this.cursor.y);var x={charCode:u,width:p.glyphWidth,height:p.glyphHeight,bearingX:-p.glyphLeft-r,bearingY:p.glyphTop+r,advance:p.glyphAdvance,atlasX:this.cursor.x,atlasY:this.cursor.y,atlasWidth:m,atlasHeight:h,atlasIndex:this.cursor.atlasIndex};d.glyphs.set(u,x),this.cursor.x+=m+va,this.cursor.rowHeight=Math.max(this.cursor.rowHeight,h)}}}catch(e){o.e(e)}finally{o.f()}this.finalizeCurrentTexture(),this.pendingGlyphs=[],this.emit(t.ATLAS_UPDATED_EVENT,{textures:this.textures,glyphCount:this.getGlyphCount()})}}},{key:`finalizeCurrentTexture`,value:function(){var e=this.options.maxTextureSize,t=this.cursor.y>0||this.cursor.rowHeight>0,n=Math.min(e,Math.max(this.cursor.x,t?e:1)),r=Math.min(e,this.cursor.y+this.cursor.rowHeight+va),i=this.ctx.getImageData(0,0,n,r);this.cursor.atlasIndex>=this.textures.length?this.textures.push(i):this.textures[this.cursor.atlasIndex]=i}}])}(b.EventEmitter);U(wa,`ATLAS_UPDATED_EVENT`,`atlasUpdated`);var Ta=_a.fontSize;function Ea(){return`#version 300 es
|
|
1084
|
+
|
|
1085
|
+
// ============================================================================
|
|
1086
|
+
// Attributes
|
|
1087
|
+
// ============================================================================
|
|
1088
|
+
|
|
1089
|
+
// Per-character (instanced)
|
|
1090
|
+
in float a_nodeIndex; // Index into node data texture
|
|
1091
|
+
in vec2 a_charOffset; // Character offset from label origin (pixels)
|
|
1092
|
+
in vec2 a_charSize; // Character dimensions (pixels)
|
|
1093
|
+
in vec4 a_texCoords; // Atlas coords: (x, y, width, height) in pixels
|
|
1094
|
+
in vec4 a_color; // Text color (RGBA)
|
|
1095
|
+
in float a_margin; // Gap between node edge and label (pixels)
|
|
1096
|
+
in float a_positionMode; // Position: 0=right, 1=left, 2=above, 3=below, 4=over
|
|
1097
|
+
in float a_labelWidth; // Total label width (pixels)
|
|
1098
|
+
in float a_labelHeight; // Label height (pixels)
|
|
1099
|
+
in float a_verticalCenter; // Vertical center offset from baseline (pixels)
|
|
1100
|
+
in float a_textHeight; // Actual text height: maxAscent + maxDescent (pixels)
|
|
1101
|
+
in float a_labelAngle; // Label rotation angle (radians)
|
|
1102
|
+
|
|
1103
|
+
// Per-vertex (constant quad corners)
|
|
1104
|
+
in vec2 a_quadCorner; // Quad corner: [-1,-1], [1,-1], [-1,1], [1,1]
|
|
1105
|
+
|
|
1106
|
+
// ============================================================================
|
|
1107
|
+
// Uniforms
|
|
1108
|
+
// ============================================================================
|
|
1109
|
+
|
|
1110
|
+
uniform mat3 u_matrix;
|
|
1111
|
+
uniform float u_sizeRatio;
|
|
1112
|
+
uniform float u_correctionRatio;
|
|
1113
|
+
uniform float u_cameraAngle;
|
|
1114
|
+
uniform vec2 u_resolution;
|
|
1115
|
+
uniform vec2 u_atlasSize;
|
|
1116
|
+
uniform sampler2D u_nodeDataTexture;
|
|
1117
|
+
uniform int u_nodeDataTextureWidth;
|
|
1118
|
+
uniform sampler2D u_nodeFrameTexture;
|
|
1119
|
+
uniform int u_nodeFrameTextureWidth;
|
|
1120
|
+
uniform float u_zoomLabelSizeRatio;
|
|
1121
|
+
uniform float u_labelPixelSnapping;
|
|
1122
|
+
uniform float u_pixelRatio;
|
|
1123
|
+
|
|
1124
|
+
// ============================================================================
|
|
1125
|
+
// Varyings
|
|
1126
|
+
// ============================================================================
|
|
1127
|
+
|
|
1128
|
+
out vec2 v_texCoord;
|
|
1129
|
+
out vec4 v_color;
|
|
1130
|
+
out float v_fontScale;
|
|
1131
|
+
|
|
1132
|
+
// ============================================================================
|
|
1133
|
+
// Constants
|
|
1134
|
+
// ============================================================================
|
|
1135
|
+
|
|
1136
|
+
const float bias = 255.0 / 254.0;
|
|
1137
|
+
const float ATLAS_FONT_SIZE = ${Z(Ta)};
|
|
1138
|
+
|
|
1139
|
+
// ============================================================================
|
|
1140
|
+
// Helper Functions
|
|
1141
|
+
// ============================================================================
|
|
1142
|
+
|
|
1143
|
+
${Ei}
|
|
1144
|
+
${Di}
|
|
1145
|
+
${ki}
|
|
1146
|
+
${bi}
|
|
1147
|
+
|
|
1148
|
+
// ============================================================================
|
|
1149
|
+
// Main
|
|
1150
|
+
// ============================================================================
|
|
1151
|
+
|
|
1152
|
+
void main() {
|
|
1153
|
+
// -------------------------------------------------------------------------
|
|
1154
|
+
// Step 0: Fetch node data + shared edge distance from textures
|
|
1155
|
+
// -------------------------------------------------------------------------
|
|
1156
|
+
// Node-data texture format: vec4(x, y, size, shapeId)
|
|
1157
|
+
// 2D texture layout: texCoord = (index % width, index / width)
|
|
1158
|
+
int nodeIdx = int(a_nodeIndex);
|
|
1159
|
+
vec4 nodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx);
|
|
1160
|
+
vec2 a_anchorPosition = nodeData.xy;
|
|
1161
|
+
float a_nodeSize = nodeData.z;
|
|
1162
|
+
|
|
1163
|
+
// Normalized edge distance from the shared frame texture (the frame-pass ran
|
|
1164
|
+
// the SDF search once; the label just reads the result).
|
|
1165
|
+
float edgeDist = readFrameTexel(u_nodeFrameTexture, u_nodeFrameTextureWidth, nodeIdx).r;
|
|
1166
|
+
|
|
1167
|
+
// Per-node label rotation alignment: 0 = viewport, 1 = label turns with camera.
|
|
1168
|
+
float labelRotation = readNodeFlags(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx).g;
|
|
1169
|
+
|
|
1170
|
+
// Apply zoom-dependent label size scaling
|
|
1171
|
+
// Positional values are in CSS pixels; multiply by u_pixelRatio to convert to
|
|
1172
|
+
// physical pixels, which is what the NDC conversion (/ u_resolution) expects.
|
|
1173
|
+
float zoomScale = u_zoomLabelSizeRatio;
|
|
1174
|
+
float margin = a_margin * zoomScale * u_pixelRatio;
|
|
1175
|
+
vec2 charOffset = a_charOffset * zoomScale * u_pixelRatio;
|
|
1176
|
+
vec2 charSize = a_charSize * zoomScale * u_pixelRatio;
|
|
1177
|
+
float labelWidth = a_labelWidth * zoomScale * u_pixelRatio;
|
|
1178
|
+
float labelHeight = a_labelHeight * zoomScale;
|
|
1179
|
+
|
|
1180
|
+
// Font scale: ratio of CSS label size to the base atlas font size.
|
|
1181
|
+
// Divided by u_pixelRatio because the atlas is generated at ATLAS_FONT_SIZE * pixelRatio,
|
|
1182
|
+
// which cancels out the u_pixelRatio in the fragment shader's gamma formula and keeps
|
|
1183
|
+
// the anti-aliasing band width consistent across pixel densities.
|
|
1184
|
+
v_fontScale = a_labelHeight * zoomScale / (ATLAS_FONT_SIZE * u_pixelRatio);
|
|
1185
|
+
|
|
1186
|
+
// -------------------------------------------------------------------------
|
|
1187
|
+
// Step 1: Transform node position to clip space
|
|
1188
|
+
// -------------------------------------------------------------------------
|
|
1189
|
+
vec3 anchorClip = u_matrix * vec3(a_anchorPosition, 1.0);
|
|
1190
|
+
|
|
1191
|
+
// -------------------------------------------------------------------------
|
|
1192
|
+
// Step 2: Convert node size to screen pixels
|
|
1193
|
+
// -------------------------------------------------------------------------
|
|
1194
|
+
float matrixScaleX = length(vec2(u_matrix[0][0], u_matrix[1][0]));
|
|
1195
|
+
float nodeRadiusGraphSpace = a_nodeSize * u_correctionRatio / u_sizeRatio * 2.0;
|
|
1196
|
+
float nodeRadiusNDC = nodeRadiusGraphSpace * matrixScaleX;
|
|
1197
|
+
float nodeRadiusPixels = nodeRadiusNDC * u_resolution.x / 2.0;
|
|
1198
|
+
|
|
1199
|
+
// -------------------------------------------------------------------------
|
|
1200
|
+
// Step 3: Calculate position offset from the shared edge distance
|
|
1201
|
+
// -------------------------------------------------------------------------
|
|
1202
|
+
vec2 positionOffset = vec2(0.0);
|
|
1203
|
+
|
|
1204
|
+
if (a_positionMode < 4.0) {
|
|
1205
|
+
vec2 screenDir = getLabelDirection(a_positionMode);
|
|
1206
|
+
float boundaryDistPixels = nodeRadiusPixels * edgeDist;
|
|
1207
|
+
positionOffset = screenDir * (boundaryDistPixels + margin);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// -------------------------------------------------------------------------
|
|
1211
|
+
// Step 4: Calculate final vertex position
|
|
1212
|
+
// -------------------------------------------------------------------------
|
|
1213
|
+
vec2 cornerOffset = (a_quadCorner + 1.0) * 0.5;
|
|
1214
|
+
vec2 charPixelPos = positionOffset + charOffset + cornerOffset * charSize;
|
|
1215
|
+
|
|
1216
|
+
// Apply text alignment based on position mode
|
|
1217
|
+
float verticalCenter = a_verticalCenter * zoomScale * u_pixelRatio;
|
|
1218
|
+
float textHeight = a_textHeight * zoomScale * u_pixelRatio;
|
|
1219
|
+
float baselineToDescent = textHeight / 2.0 - verticalCenter;
|
|
1220
|
+
float baselineToAscent = textHeight / 2.0 + verticalCenter;
|
|
1221
|
+
|
|
1222
|
+
if (a_positionMode < 0.5) {
|
|
1223
|
+
// Right: vertically center
|
|
1224
|
+
charPixelPos.y += verticalCenter;
|
|
1225
|
+
} else if (a_positionMode < 1.5) {
|
|
1226
|
+
// Left: right-align and vertically center
|
|
1227
|
+
charPixelPos.x -= labelWidth;
|
|
1228
|
+
charPixelPos.y += verticalCenter;
|
|
1229
|
+
} else if (a_positionMode < 2.5) {
|
|
1230
|
+
// Above: center horizontally, bottom of text at anchor
|
|
1231
|
+
charPixelPos.x -= labelWidth * 0.5;
|
|
1232
|
+
charPixelPos.y -= baselineToDescent;
|
|
1233
|
+
} else if (a_positionMode < 3.5) {
|
|
1234
|
+
// Below: center horizontally, top of text at anchor
|
|
1235
|
+
charPixelPos.x -= labelWidth * 0.5;
|
|
1236
|
+
charPixelPos.y += baselineToAscent;
|
|
1237
|
+
} else {
|
|
1238
|
+
// Over: center both
|
|
1239
|
+
charPixelPos.x -= labelWidth * 0.5;
|
|
1240
|
+
charPixelPos.y += verticalCenter;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// Apply label angle rotation. Graph-aligned labels add the camera angle so the
|
|
1244
|
+
// whole label orbits the node in lockstep with the frame-pass edge distance.
|
|
1245
|
+
float labelAngle = a_labelAngle - labelRotation * u_cameraAngle;
|
|
1246
|
+
float la_c = cos(labelAngle);
|
|
1247
|
+
float la_s = sin(labelAngle);
|
|
1248
|
+
mat2 labelRotMat = mat2(la_c, -la_s, la_s, la_c);
|
|
1249
|
+
charPixelPos = labelRotMat * charPixelPos;
|
|
1250
|
+
|
|
1251
|
+
// Snap node center to pixel grid so label/backdrop/attachment move as a unit
|
|
1252
|
+
vec2 nodeScreen = vec2(
|
|
1253
|
+
(anchorClip.x + 1.0) * u_resolution.x,
|
|
1254
|
+
(1.0 - anchorClip.y) * u_resolution.y
|
|
1255
|
+
) * 0.5;
|
|
1256
|
+
charPixelPos += (round(nodeScreen) - nodeScreen) * u_labelPixelSnapping;
|
|
1257
|
+
|
|
1258
|
+
// Convert to NDC (flip Y: screen Y-down -> clip Y-up)
|
|
1259
|
+
vec2 ndcOffset = vec2(charPixelPos.x, -charPixelPos.y) * 2.0 / u_resolution;
|
|
1260
|
+
gl_Position = vec4(anchorClip.xy + ndcOffset, 0.0, 1.0);
|
|
1261
|
+
|
|
1262
|
+
// -------------------------------------------------------------------------
|
|
1263
|
+
// Step 5: Texture coordinates
|
|
1264
|
+
// -------------------------------------------------------------------------
|
|
1265
|
+
v_texCoord = (a_texCoords.xy + cornerOffset * a_texCoords.zw) / u_atlasSize;
|
|
1266
|
+
|
|
1267
|
+
// -------------------------------------------------------------------------
|
|
1268
|
+
// Step 6: Pass color
|
|
1269
|
+
// -------------------------------------------------------------------------
|
|
1270
|
+
v_color = a_color;
|
|
1271
|
+
v_color.a *= bias;
|
|
1272
|
+
}
|
|
1273
|
+
`}function Da(){return`#version 300 es
|
|
1274
|
+
precision highp float;
|
|
1275
|
+
|
|
1276
|
+
in vec2 v_texCoord;
|
|
1277
|
+
in vec4 v_color;
|
|
1278
|
+
in float v_fontScale;
|
|
1279
|
+
|
|
1280
|
+
uniform sampler2D u_atlas;
|
|
1281
|
+
uniform float u_gamma;
|
|
1282
|
+
uniform float u_sdfBuffer;
|
|
1283
|
+
uniform float u_pixelRatio;
|
|
1284
|
+
|
|
1285
|
+
// Fragment output (single target - picking handled via separate pass)
|
|
1286
|
+
out vec4 fragColor;
|
|
1287
|
+
|
|
1288
|
+
void main() {
|
|
1289
|
+
#ifdef PICKING_MODE
|
|
1290
|
+
// Labels are not pickable - discard all fragments in picking mode
|
|
1291
|
+
discard;
|
|
1292
|
+
#else
|
|
1293
|
+
// Sample SDF value from atlas (high = inside glyph, low = outside)
|
|
1294
|
+
float sdfValue = texture(u_atlas, v_texCoord).a;
|
|
1295
|
+
|
|
1296
|
+
// Edge threshold: 1.0 - cutoff = 0.75 for default cutoff=0.25
|
|
1297
|
+
// This is where the glyph edge is located in the SDF
|
|
1298
|
+
float edgeThreshold = 1.0 - u_sdfBuffer;
|
|
1299
|
+
|
|
1300
|
+
// Gamma controls the anti-aliasing band width.
|
|
1301
|
+
// Scale inversely with font scale so small labels get a wider AA band
|
|
1302
|
+
// (smoother) and large labels get a tighter band (sharper).
|
|
1303
|
+
float gamma = u_gamma / (u_pixelRatio * v_fontScale);
|
|
1304
|
+
|
|
1305
|
+
// Pure gamma-based anti-aliasing using smoothstep
|
|
1306
|
+
// The AA band extends from (threshold - gamma) to (threshold + gamma)
|
|
1307
|
+
float alpha = smoothstep(edgeThreshold - gamma, edgeThreshold + gamma, sdfValue);
|
|
1308
|
+
|
|
1309
|
+
// Premultiplied alpha output for correct blending
|
|
1310
|
+
float finalAlpha = v_color.a * alpha;
|
|
1311
|
+
fragColor = vec4(v_color.rgb * finalAlpha, finalAlpha);
|
|
1312
|
+
#endif
|
|
1313
|
+
}
|
|
1314
|
+
`}function Oa(){return[`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_cameraAngle`,`u_resolution`,`u_atlasSize`,`u_atlas`,`u_gamma`,`u_sdfBuffer`,`u_pixelRatio`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_nodeFrameTexture`,`u_nodeFrameTextureWidth`,`u_zoomLabelSizeRatio`,`u_labelPixelSnapping`]}function ka(){return{vertexShader:Ea(),fragmentShader:Da(),uniforms:Oa()}}function Aa(e,t,n,r){var i=r.label,a=i===void 0?{}:i,o=a.margin??5,s=a.zoomToLabelSizeRatioFunction??function(){return 1},c=ka(),l=function(e){function t(e,n,r){var i;if(G(this,t),i=q(this,t,[e,n,r]),U(i,`atlasTexture`,null),U(i,`atlasNeedsUpdate`,!1),U(i,`labelGlyphCache`,new Map),i.atlasFontSize=_a.fontSize*Yr(),i.atlasManager=new wa({fontSize:i.atlasFontSize}),i.gamma=.025,i.sdfBuffer=_a.cutoff,i.atlasTexture=e.createTexture(),!i.atlasTexture)throw Error(`NodeLabelProgram: failed to create atlas texture`);e.bindTexture(e.TEXTURE_2D,i.atlasTexture),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.bindTexture(e.TEXTURE_2D,null),i.atlasManager.on(wa.ATLAS_UPDATED_EVENT,function(){i.atlasNeedsUpdate=!0});var o={family:a.font?.family||`sans-serif`,weight:a.font?.weight||`normal`,style:a.font?.style||`normal`};return i.defaultFontKey=i.atlasManager.registerFont(o),i}return J(t,e),K(t,[{key:`getDefinition`,value:function(){var e=WebGL2RenderingContext,t=e.FLOAT,n=e.UNSIGNED_BYTE,r=e.TRIANGLE_STRIP;return{VERTICES:4,VERTEX_SHADER_SOURCE:c.vertexShader,FRAGMENT_SHADER_SOURCE:c.fragmentShader,METHOD:r,UNIFORMS:c.uniforms,ATTRIBUTES:[{name:`a_nodeIndex`,size:1,type:t},{name:`a_charOffset`,size:2,type:t},{name:`a_charSize`,size:2,type:t},{name:`a_texCoords`,size:4,type:t},{name:`a_color`,size:4,type:n,normalized:!0},{name:`a_margin`,size:1,type:t},{name:`a_positionMode`,size:1,type:t},{name:`a_labelWidth`,size:1,type:t},{name:`a_labelHeight`,size:1,type:t},{name:`a_verticalCenter`,size:1,type:t},{name:`a_textHeight`,size:1,type:t},{name:`a_labelAngle`,size:1,type:t}],CONSTANT_ATTRIBUTES:[{name:`a_quadCorner`,size:2,type:t}],CONSTANT_DATA:[[-1,-1],[1,-1],[-1,1],[1,1]]}}},{key:`prepareLabelGlyphs`,value:function(e,t){if(t.hidden||!t.text)this.labelGlyphCache.delete(e);else{var n=t.text,r=t.fontKey||this.defaultFontKey;this.atlasManager.ensureGlyphs(n,r);var i=[],a=[],o=0,s=0,c=0,l=H(n),u;try{for(l.s();!(u=l.n()).done;){var d=u.value.codePointAt(0);if(d===void 0)i.push(void 0),a.push(o);else{var f=this.atlasManager.getGlyph(d,r);i.push(f),a.push(o),f&&(o+=f.advance,s=Math.max(s,f.bearingY),c=Math.max(c,f.atlasHeight-f.bearingY))}}}catch(e){l.e(e)}finally{l.f()}this.labelGlyphCache.set(e,{glyphs:i,xOffsets:a,totalWidth:o,totalHeight:s+c,verticalCenterOffset:(s-c)/2})}}},{key:`processCharacter`,value:function(e,t,n,r){var i=this.floats,a=this.STRIDE,o=e*a,s=this.labelGlyphCache.get(t.parentKey);if(!s||!s.glyphs[r])for(var c=0;c<a;c++)i[o+c]=0;else{var l=s.glyphs[r],u=s.xOffsets[r],d=t.size/this.atlasFontSize,f=sn(t.color),p=o;i[p++]=t.nodeIndex,i[p++]=(u+l.bearingX)*d,i[p++]=-l.bearingY*d,i[p++]=l.atlasWidth*d,i[p++]=l.atlasHeight*d,i[p++]=l.atlasX,i[p++]=l.atlasY,i[p++]=l.atlasWidth,i[p++]=l.atlasHeight,i[p++]=f,i[p++]=t.margin,i[p++]=_i[t.position],i[p++]=s.totalWidth*d,i[p++]=t.size,i[p++]=s.verticalCenterOffset*d,i[p++]=s.totalHeight*d,i[p++]=t.labelAngle}}},{key:`processLabel`,value:function(e,n,r){return this.prepareLabelGlyphs(e,r),Q(t,`processLabel`,this,3)([e,n,r])}},{key:`updateAtlasTexture`,value:function(){if(this.atlasNeedsUpdate){var e=this.normalProgram.gl,t=this.atlasManager.getTextures();if(t.length!==0){var n=t[0];e.bindTexture(e.TEXTURE_2D,this.atlasTexture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,n.width,n.height,0,e.RGBA,e.UNSIGNED_BYTE,n.data),e.bindTexture(e.TEXTURE_2D,null),this.atlasNeedsUpdate=!1}}}},{key:`setUniforms`,value:function(e,n){var r=n.gl,i=n.uniformLocations;r.uniformMatrix3fv(i.u_matrix,!1,e.matrix),r.uniform1f(i.u_sizeRatio,e.sizeRatio),r.uniform1f(i.u_correctionRatio,e.correctionRatio),r.uniform1f(i.u_cameraAngle,e.cameraAngle),r.uniform2f(i.u_resolution,e.width*e.pixelRatio,e.height*e.pixelRatio);var a=this.atlasManager.getTextures();a.length>0?r.uniform2f(i.u_atlasSize,a[0].width,a[0].height):r.uniform2f(i.u_atlasSize,1,1),r.activeTexture(r.TEXTURE0),r.bindTexture(r.TEXTURE_2D,this.atlasTexture),r.uniform1i(i.u_atlas,0),i.u_nodeDataTexture!==void 0&&r.uniform1i(i.u_nodeDataTexture,e.nodeDataTextureUnit),i.u_nodeDataTextureWidth!==void 0&&r.uniform1i(i.u_nodeDataTextureWidth,e.nodeDataTextureWidth),r.uniform1i(i.u_nodeFrameTexture,e.nodeFrameTextureUnit),r.uniform1i(i.u_nodeFrameTextureWidth,e.nodeFrameTextureWidth),r.uniform1f(i.u_gamma,this.gamma),r.uniform1f(i.u_sdfBuffer,this.sdfBuffer),r.uniform1f(i.u_pixelRatio,e.pixelRatio),r.uniform1f(i.u_zoomLabelSizeRatio,1/t.zoomToLabelSizeRatioFunction(e.zoomRatio)),r.uniform1f(i.u_labelPixelSnapping,e.labelPixelSnapping)}},{key:`renderProgram`,value:function(e,n){this.updateAtlasTexture(),this.atlasManager.hasPendingGlyphs()&&(this.atlasManager.flush(),this.updateAtlasTexture()),Q(t,`renderProgram`,this,3)([e,n])}},{key:`registerFont`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:`normal`,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:`normal`;return this.atlasManager.registerFont({family:e,weight:t,style:n})}},{key:`getAtlasManager`,value:function(){return this.atlasManager}},{key:`measureLabel`,value:function(e,t,n){var r=n||this.defaultFontKey;this.atlasManager.ensureGlyphs(e,r),this.atlasManager.hasPendingGlyphs()&&this.atlasManager.flush();var i=0,a=0,o=0,s=H(e),c;try{for(s.s();!(c=s.n()).done;){var l=c.value.codePointAt(0);if(l!==void 0){var u=this.atlasManager.getGlyph(l,r);u&&(i+=u.advance,a=Math.max(a,u.bearingY),o=Math.max(o,u.atlasHeight-u.bearingY))}}}catch(e){s.e(e)}finally{s.f()}var d=t/this.atlasFontSize;return{width:i*d,height:t,textHeight:(a+o)*d}}},{key:`ensureGlyphsReady`,value:function(e,t){var n=t||this.defaultFontKey,r=H(e),i;try{for(r.s();!(i=r.n()).done;){var a=i.value;this.atlasManager.ensureGlyphs(a,n)}}catch(e){r.e(e)}finally{r.f()}this.atlasManager.flush()}},{key:`kill`,value:function(){var e=this.normalProgram.gl;this.atlasTexture&&=(e.deleteTexture(this.atlasTexture),null),this.atlasManager.destroy(),this.labelGlyphCache.clear(),Q(t,`kill`,this,3)([])}}])}(pa);return U(l,`labelMargin`,o),U(l,`zoomToLabelSizeRatioFunction`,s),new l(e,t,n)}var ja=`#version 300 es
|
|
1315
|
+
precision highp float;
|
|
1316
|
+
|
|
1317
|
+
in float v_edgeDist;
|
|
1318
|
+
|
|
1319
|
+
// R32F target: only the .r channel is stored.
|
|
1320
|
+
out vec4 fragColor;
|
|
1321
|
+
|
|
1322
|
+
void main() {
|
|
1323
|
+
fragColor = vec4(v_edgeDist, 0.0, 0.0, 0.0);
|
|
1324
|
+
}
|
|
1325
|
+
`;function Ma(e,t,n){var r=mi(e),i=hi(e).map(function(e){return`uniform ${e.type} ${e.name};`}).join(`
|
|
1326
|
+
`),a=Ai(e,n),o=a.code,s=a.multiShape,c=ta(e,t),l=Object.keys(c.specs).map(function(e){return`float v_${e};`}).join(`
|
|
1327
|
+
`),u=Wi(c,{varPrefix:`nodeAttr`,baseTexelExpr:`nodeIdx * u_layerAttributeTexelsPerNode`,textureWidthUniform:`u_layerAttributeTextureWidth`,textureSamplerUniform:`u_layerAttributeTexture`});return`#version 300 es
|
|
1328
|
+
precision highp float;
|
|
1329
|
+
|
|
1330
|
+
uniform float u_cameraAngle;
|
|
1331
|
+
uniform sampler2D u_nodeDataTexture;
|
|
1332
|
+
uniform int u_nodeDataTextureWidth;
|
|
1333
|
+
uniform float u_frameTextureWidth;
|
|
1334
|
+
uniform float u_frameTextureHeight;
|
|
1335
|
+
uniform sampler2D u_layerAttributeTexture;
|
|
1336
|
+
uniform int u_layerAttributeTextureWidth;
|
|
1337
|
+
uniform int u_layerAttributeTexelsPerNode;
|
|
1338
|
+
${i}
|
|
1339
|
+
|
|
1340
|
+
in float a_nodeIndex; // node-data texture index (also the target frame texel)
|
|
1341
|
+
in float a_positionMode; // 0=right 1=left 2=above 3=below 4=over
|
|
1342
|
+
in float a_labelAngle; // intrinsic label angle (radians)
|
|
1343
|
+
|
|
1344
|
+
out float v_edgeDist;
|
|
1345
|
+
|
|
1346
|
+
// Shape attributes (plain globals: this pass is vertex-only)
|
|
1347
|
+
${l}
|
|
1348
|
+
|
|
1349
|
+
${Ei}
|
|
1350
|
+
${Di}
|
|
1351
|
+
${r}
|
|
1352
|
+
${o}
|
|
1353
|
+
${bi}
|
|
1354
|
+
|
|
1355
|
+
void main() {
|
|
1356
|
+
int nodeIdx = int(a_nodeIndex);
|
|
1357
|
+
${u.fetchCode}
|
|
1358
|
+
${u.varyingAssignments}
|
|
1359
|
+
${s?`// Multi-shape: the shape id lives in the node-data texture's .w channel:
|
|
1360
|
+
g_shapeId = int(readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx).w);`:`// Single-shape mode, shape id not needed`}
|
|
1361
|
+
|
|
1362
|
+
// Per-node rotation alignment (0 = viewport, 1 = graph).
|
|
1363
|
+
vec4 nodeFlags = readNodeFlags(u_nodeDataTexture, u_nodeDataTextureWidth, nodeIdx);
|
|
1364
|
+
float nodeRotation = nodeFlags.r;
|
|
1365
|
+
float labelRotation = nodeFlags.g;
|
|
1366
|
+
|
|
1367
|
+
// Effective angle: intrinsic (style-given) plus the camera angle when the label
|
|
1368
|
+
// is graph-aligned. The companions place the box at this same angle.
|
|
1369
|
+
float effectiveAngle = a_labelAngle - labelRotation * u_cameraAngle;
|
|
1370
|
+
|
|
1371
|
+
// The "over" mode (4) sits on the node center, so it has no edge distance.
|
|
1372
|
+
float edgeDist = 0.0;
|
|
1373
|
+
if (a_positionMode < 4.0) {
|
|
1374
|
+
vec2 screenDir = getLabelDirection(a_positionMode);
|
|
1375
|
+
// Rotate by the effective label angle. Inlined rather than via rotate2D()
|
|
1376
|
+
// because the shape SDFs (getShapeGLSLForShapes) already define that helper
|
|
1377
|
+
// for multi-shape programs, and redefining it would be a GLSL error.
|
|
1378
|
+
float ea_c = cos(effectiveAngle);
|
|
1379
|
+
float ea_s = sin(effectiveAngle);
|
|
1380
|
+
vec2 rotatedScreenDir = mat2(ea_c, -ea_s, ea_s, ea_c) * screenDir;
|
|
1381
|
+
// Screen (Y-down) -> SDF (Y-up).
|
|
1382
|
+
vec2 sdfDir = vec2(rotatedScreenDir.x, -rotatedScreenDir.y);
|
|
1383
|
+
// Counter-rotate into the shape's local frame for graph-aligned nodes, so the
|
|
1384
|
+
// boundary is queried against the shape's actual on-screen orientation.
|
|
1385
|
+
float nodeCa = -u_cameraAngle * nodeRotation;
|
|
1386
|
+
float nc = cos(nodeCa), ns = sin(nodeCa);
|
|
1387
|
+
sdfDir = mat2(nc, -ns, ns, nc) * sdfDir;
|
|
1388
|
+
edgeDist = findEdgeDistance(sdfDir, 1.0);
|
|
1389
|
+
}
|
|
1390
|
+
v_edgeDist = edgeDist;
|
|
1391
|
+
|
|
1392
|
+
// Scatter to this node's texel center in the frame texture.
|
|
1393
|
+
float x = mod(a_nodeIndex, u_frameTextureWidth);
|
|
1394
|
+
float y = floor(a_nodeIndex / u_frameTextureWidth);
|
|
1395
|
+
vec2 ndc = (vec2(x, y) + 0.5) / vec2(u_frameTextureWidth, u_frameTextureHeight) * 2.0 - 1.0;
|
|
1396
|
+
gl_Position = vec4(ndc, 0.0, 1.0);
|
|
1397
|
+
gl_PointSize = 1.0;
|
|
1398
|
+
}
|
|
1399
|
+
`}var Na=function(){function e(t,n){G(this,e),U(this,`uniformLocations`,{});var r=n.shapes,i=n.layers,a=n.shapeGlobalIds;if(r.length===0)throw Error(`NodeLabelFramePass: at least one shape must be provided`);this.gl=t,this.shapeUniforms=hi(r),this.hasAttributeData=Object.keys(ta(r,i).offsets).length>0,this.vertexShader=$r(t,Ma(r,i,a)),this.fragmentShader=ei(t,ja),this.program=ti(t,[this.vertexShader,this.fragmentShader]);var o=H([`u_cameraAngle`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_frameTextureWidth`,`u_frameTextureHeight`,`u_layerAttributeTexture`,`u_layerAttributeTextureWidth`,`u_layerAttributeTexelsPerNode`].concat(Y(this.shapeUniforms.map(function(e){return e.name})))),s;try{for(o.s();!(s=o.n()).done;){var c=s.value;this.uniformLocations[c]=t.getUniformLocation(this.program,c)}}catch(e){o.e(e)}finally{o.f()}var l=e.FLOATS_PER_POINT*4;this.vao=t.createVertexArray(),this.buffer=t.createBuffer(),t.bindVertexArray(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.buffer);var u=H([[`a_nodeIndex`,0],[`a_positionMode`,4],[`a_labelAngle`,8]]),d;try{for(u.s();!(d=u.n()).done;){var f=V(d.value,2),p=f[0],m=f[1],h=t.getAttribLocation(this.program,p);h>=0&&(t.enableVertexAttribArray(h),t.vertexAttribPointer(h,1,t.FLOAT,!1,l,m))}}catch(e){u.e(e)}finally{u.f()}t.bindVertexArray(null)}return K(e,[{key:`run`,value:function(t,n,r,i,a){if(n!==0){var o=this.gl;o.useProgram(this.program),o.bindVertexArray(this.vao),o.bindBuffer(o.ARRAY_BUFFER,this.buffer),o.bufferData(o.ARRAY_BUFFER,t.subarray(0,n*e.FLOATS_PER_POINT),o.DYNAMIC_DRAW);var s=this.uniformLocations;o.uniform1f(s.u_cameraAngle,i.cameraAngle),o.uniform1i(s.u_nodeDataTexture,i.nodeDataTextureUnit),o.uniform1i(s.u_nodeDataTextureWidth,i.nodeDataTextureWidth),o.uniform1f(s.u_frameTextureWidth,r.getTextureWidth()),o.uniform1f(s.u_frameTextureHeight,r.getTextureHeight()),this.hasAttributeData&&a&&(a.bind($i),s.u_layerAttributeTexture&&o.uniform1i(s.u_layerAttributeTexture,$i),s.u_layerAttributeTextureWidth&&o.uniform1i(s.u_layerAttributeTextureWidth,a.getTextureWidth()),s.u_layerAttributeTexelsPerNode&&o.uniform1i(s.u_layerAttributeTexelsPerNode,a.getTexelsPerItem()));var c=H(this.shapeUniforms),l;try{for(c.s();!(l=c.n()).done;){var u=l.value;Gi(o,this.uniformLocations[u.name],u)}}catch(e){c.e(e)}finally{c.f()}r.bindAsRenderTarget(),o.disable(o.BLEND),o.disable(o.DEPTH_TEST),o.drawArrays(o.POINTS,0,n),o.bindFramebuffer(o.FRAMEBUFFER,null),o.bindVertexArray(null)}}},{key:`kill`,value:function(){var e=this.gl;e.deleteProgram(this.program),e.deleteShader(this.vertexShader),e.deleteShader(this.fragmentShader),e.deleteBuffer(this.buffer),e.deleteVertexArray(this.vao)}}])}();U(Na,`FLOATS_PER_POINT`,3);function Pa(e,t,n,r,i){var a,o=r.label,s=o===void 0?{}:o,c=r.shapes;if(c.length===0)throw Error(`createNodeProgram: at least one shape must be provided in 'shapes'`);var l={},u=[],d;c.forEach(function(e,t){var n=li(e);t===0&&(d=n),l[e.name]=t,u[t]=ui(n)});var f=Y(r.layers),p=oa({shapes:c,layers:f,shapeGlobalIds:c.length>1?u:void 0,antialias:i}),m=Aa(e,null,n,{label:s}),h=fa(e,null,n,{shapes:c,layers:f,getAttributeTexture:function(){return S.getAttributeTexture()},label:s,shapeGlobalIds:c.length>1?u:void 0}),g=ga(e,t,n,{label:s}),_=r.labelAttachments&&Object.keys(r.labelAttachments).length>0?Qi(e,null,n,{label:s}):null,v=new Na(e,{shapes:c,layers:f,shapeGlobalIds:c.length>1?u:void 0}),y=ea(c,f),b=zi(y),x=(a=function(e){function t(e,n,r){var i;G(this,t),i=q(this,t,[e,n,r]),U(i,`layerLifecycles`,new Map),U(i,`layersNeedingRegeneration`,new Set),U(i,`attrDescriptors`,[]),i._pickingBuffer=n;var a=x.layerTextures.get(e);a||(a=new Bi(e,b),x.layerTextures.set(e,a)),i.layerAttributeTexture=a;var o=x.textureRefCounts.get(e)||0;x.textureRefCounts.set(e,o+1),i.packedAttributeData=new Float32Array(b.floatsPerItem),f.forEach(function(t,n){if(t.lifecycle){var a={gl:e,renderer:{refresh:function(){return r.refresh()}},getUniformLocation:function(t){return e.getUniformLocation(i.normalProgram.program,t)},requestShaderRegeneration:function(){i.layersNeedingRegeneration.add(n)},requestRefresh:function(){r.refresh()}},o=t.lifecycle(a);i.layerLifecycles.set(n,o)}}),i.layerLifecycles.forEach(function(e){var t;(t=e.init)==null||t.call(e)});var s=new Map;return i.layerLifecycles.forEach(function(e,t){e.getAttributeData&&s.set(t,e)}),i.attrDescriptors=Vi(y,b,s),i}return J(t,e),K(t,[{key:`getDefinition`,value:function(){var e=WebGL2RenderingContext,t=e.FLOAT,n=e.TRIANGLE_STRIP;return{VERTICES:4,VERTEX_SHADER_SOURCE:p.vertexShader,FRAGMENT_SHADER_SOURCE:p.fragmentShader,METHOD:n,UNIFORMS:p.uniforms,ATTRIBUTES:p.attributes,CONSTANT_ATTRIBUTES:[{name:`a_quadCorner`,size:2,type:t}],CONSTANT_DATA:[[-1,-1],[1,-1],[-1,1],[1,1]]}}},{key:`maybeRegenerateShaders`,value:function(){var e=this;if(this.layersNeedingRegeneration.size!==0){f=f.map(function(t,n){if(e.layersNeedingRegeneration.has(n)){var r=e.layerLifecycles.get(n);if(r!=null&&r.regenerate)return W(W({},r.regenerate()),{},{lifecycle:t.lifecycle})}return t}),this.layersNeedingRegeneration.clear(),p=oa({shapes:c,layers:f,shapeGlobalIds:c.length>1?u:void 0,antialias:this.renderer.getSetting(`antialiasNodes`)});var t=this.normalProgram.gl,n=this.normalProgram,r=n.program,i=n.buffer,a=n.vertexShader,o=n.fragmentShader;t.deleteProgram(r),t.deleteBuffer(i),t.deleteShader(a),t.deleteShader(o),this.normalProgram=this.getProgramInfo(`normal`,t,p.vertexShader,p.fragmentShader,this._pickingBuffer)}}},{key:`allocateNode`,value:function(e){this.layerAttributeTexture.allocate(e)}},{key:`freeNode`,value:function(e){this.layerAttributeTexture.free(e)}},{key:`getAttributeTexture`,value:function(){return this.layerAttributeTexture}},{key:`uploadLayerTexture`,value:function(){this.layerAttributeTexture.upload()}},{key:`process`,value:function(e,t,n,r,i){var a=t*this.STRIDE;if(n.visibility===`hidden`){for(var o=a+this.STRIDE;a<o;a++)this.floats[a]=0;this.floats[t*this.STRIDE]=Li}else this.processVisibleItem(ln(e),a,n,r,i)}},{key:`processVisibleItem`,value:function(e,t,n,r,i){var a=this.floats,o=this.ints;if(a[t++]=r,o[t++]=e,a[t++]=n.opacity??1,b.floatsPerItem!==0){var s=this.packedAttributeData;Hi(this.attrDescriptors,n,s,n.color,this.layerLifecycles,0),this.layerAttributeTexture.updateAllAttributes(i,s)}}},{key:`setUniforms`,value:function(e,t){var n=this,r=t.gl,i=t.uniformLocations;i.u_matrix&&r.uniformMatrix3fv(i.u_matrix,!1,e.matrix),i.u_sizeRatio&&r.uniform1f(i.u_sizeRatio,e.sizeRatio),i.u_correctionRatio&&r.uniform1f(i.u_correctionRatio,e.correctionRatio),i.u_pickingPadding&&r.uniform1f(i.u_pickingPadding,e.nodePickingPadding),i.u_cameraAngle&&r.uniform1f(i.u_cameraAngle,e.cameraAngle),i.u_nodeDataTexture&&r.uniform1i(i.u_nodeDataTexture,e.nodeDataTextureUnit),i.u_nodeDataTextureWidth&&r.uniform1i(i.u_nodeDataTextureWidth,e.nodeDataTextureWidth),i.u_layerAttributeTexture&&(this.layerAttributeTexture.bind($i),r.uniform1i(i.u_layerAttributeTexture,$i)),i.u_layerAttributeTextureWidth&&r.uniform1i(i.u_layerAttributeTextureWidth,this.layerAttributeTexture.getTextureWidth()),i.u_layerAttributeTexelsPerNode&&r.uniform1i(i.u_layerAttributeTexelsPerNode,this.layerAttributeTexture.getTexelsPerItem()),c.forEach(function(e){e.uniforms.forEach(function(e){n.setTypedUniform(e,t)})}),f.forEach(function(e){e.uniforms.forEach(function(e){n.setTypedUniform(e,t)})})}},{key:`render`,value:function(e,n,r){this.maybeRegenerateShaders(),Q(t,`render`,this,3)([e,n,r])}},{key:`renderProgram`,value:function(e,n){var r=n.gl,i=n.program;r.useProgram(i),n===this.normalProgram&&this.layerLifecycles.forEach(function(e){var t;(t=e.beforeRender)==null||t.call(e)}),Q(t,`renderProgram`,this,3)([e,n])}},{key:`kill`,value:function(){this.layerLifecycles.forEach(function(e){var t;(t=e.kill)==null||t.call(e)}),this.layerLifecycles.clear();var e=this.normalProgram.gl,n=(x.textureRefCounts.get(e)||1)-1;n<=0?(this.layerAttributeTexture.kill(),x.layerTextures.delete(e),x.textureRefCounts.delete(e)):x.textureRefCounts.set(e,n),Q(t,`kill`,this,3)([])}}])}(Ji),U(a,`layerTextures`,new WeakMap),U(a,`textureRefCounts`,new WeakMap),a),S=new x(e,null,n);return{nodeProgram:S,labelProgram:m,backdropProgram:h,labelBackgroundProgram:g,attachmentProgram:_,framePass:v,shapeSlug:d,shapeNameToIndex:c.length>1?l:void 0,shapeGlobalIds:c.length>1?u:void 0}}var Fa=6;function Ia(e){var t=e.offsets,n=e.specs,r=e.floatsPerItem,i=Object.keys(t);if(i.length===0||r===0)return{uniformDeclarations:``,uniformNames:[],vertexVaryingDeclarations:``,fragmentVaryingDeclarations:``,fetchCode:``,varyingAssignments:``};var a=`
|
|
1400
|
+
uniform sampler2D u_edgeAttributeTexture;
|
|
1401
|
+
uniform int u_edgeAttributeTextureWidth;
|
|
1402
|
+
uniform int u_edgeAttributeTexelsPerEdge;`,o=[`u_edgeAttributeTexture`,`u_edgeAttributeTextureWidth`,`u_edgeAttributeTexelsPerEdge`],s=i.map(function(e){return`${n[e].size===1?`float`:`vec${n[e].size}`} v_${e};`}),c=s.map(function(e){return`out ${e}`}).join(`
|
|
1403
|
+
`),l=s.map(function(e){return`in ${e}`}).join(`
|
|
1404
|
+
`),u=Wi(e,{varPrefix:`attr`,baseTexelExpr:`edgeIdx * u_edgeAttributeTexelsPerEdge`,textureWidthUniform:`u_edgeAttributeTextureWidth`,textureSamplerUniform:`u_edgeAttributeTexture`});return{uniformDeclarations:a,uniformNames:o,vertexVaryingDeclarations:c,fragmentVaryingDeclarations:l,fetchCode:u.fetchCode,varyingAssignments:u.varyingAssignments}}function La(e){return`
|
|
1405
|
+
float findSourceClampT_${e}(vec2 source, float sourceSize, int sourceShapeId, float sourceRotateAlign, vec2 target, float margin) {
|
|
1406
|
+
float lo = 0.0, hi = 0.5;
|
|
1407
|
+
float nodeExtent = sourceSize * u_correctionRatio / u_sizeRatio * 2.0;
|
|
1408
|
+
float effectiveSize = 1.0 - u_correctionRatio / nodeExtent;
|
|
1409
|
+
|
|
1410
|
+
// Counter-rotate the query point so viewport-aligned nodes (rotateAlign=0) are
|
|
1411
|
+
// clamped against their on-screen orientation; graph-aligned nodes skip it.
|
|
1412
|
+
float ca = u_cameraAngle * (1.0 - sourceRotateAlign);
|
|
1413
|
+
float rc = cos(ca), rs = sin(ca);
|
|
1414
|
+
mat2 rot = mat2(rc, -rs, rs, rc);
|
|
1415
|
+
|
|
1416
|
+
for (int i = 0; i < 12; i++) {
|
|
1417
|
+
float mid = (lo + hi) * 0.5;
|
|
1418
|
+
vec2 pos = path_${e}_position(mid, source, target);
|
|
1419
|
+
vec2 localPos = rot * ((pos - source) / nodeExtent);
|
|
1420
|
+
float sdf = querySDF(sourceShapeId, localPos, effectiveSize);
|
|
1421
|
+
if (sdf < 0.0) lo = mid;
|
|
1422
|
+
else hi = mid;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
float pathLen = path_${e}_length(source, target);
|
|
1426
|
+
float marginT = (margin * u_correctionRatio / u_sizeRatio) / pathLen;
|
|
1427
|
+
return (lo + hi) * 0.5 + marginT;
|
|
1428
|
+
}
|
|
1429
|
+
`}function Ra(e){return`
|
|
1430
|
+
float findTargetClampT_${e}(vec2 source, vec2 target, float targetSize, int targetShapeId, float targetRotateAlign, float margin) {
|
|
1431
|
+
float lo = 0.5, hi = 1.0;
|
|
1432
|
+
float nodeExtent = targetSize * u_correctionRatio / u_sizeRatio * 2.0;
|
|
1433
|
+
float effectiveSize = 1.0 - u_correctionRatio / nodeExtent;
|
|
1434
|
+
|
|
1435
|
+
// See findSourceClampT_ for the rotation rationale.
|
|
1436
|
+
float ca = u_cameraAngle * (1.0 - targetRotateAlign);
|
|
1437
|
+
float rc = cos(ca), rs = sin(ca);
|
|
1438
|
+
mat2 rot = mat2(rc, -rs, rs, rc);
|
|
1439
|
+
|
|
1440
|
+
for (int i = 0; i < 12; i++) {
|
|
1441
|
+
float mid = (lo + hi) * 0.5;
|
|
1442
|
+
vec2 pos = path_${e}_position(mid, source, target);
|
|
1443
|
+
vec2 localPos = rot * ((pos - target) / nodeExtent);
|
|
1444
|
+
float sdf = querySDF(targetShapeId, localPos, effectiveSize);
|
|
1445
|
+
if (sdf < 0.0) hi = mid;
|
|
1446
|
+
else lo = mid;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
float pathLen = path_${e}_length(source, target);
|
|
1450
|
+
float marginT = (margin * u_correctionRatio / u_sizeRatio) / pathLen;
|
|
1451
|
+
return (lo + hi) * 0.5 - marginT;
|
|
1452
|
+
}
|
|
1453
|
+
`}function za(e){return`
|
|
1454
|
+
// Auto-generated numerical tangent (from position via finite differences)
|
|
1455
|
+
vec2 path_${e}_tangent(float t, vec2 source, vec2 target) {
|
|
1456
|
+
float epsilon = 0.001;
|
|
1457
|
+
float t1 = max(0.0, t - epsilon);
|
|
1458
|
+
float t2 = min(1.0, t + epsilon);
|
|
1459
|
+
vec2 p1 = path_${e}_position(t1, source, target);
|
|
1460
|
+
vec2 p2 = path_${e}_position(t2, source, target);
|
|
1461
|
+
return normalize(p2 - p1);
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
// Auto-generated normal (perpendicular to tangent)
|
|
1465
|
+
vec2 path_${e}_normal(float t, vec2 source, vec2 target) {
|
|
1466
|
+
vec2 tangent = path_${e}_tangent(t, source, target);
|
|
1467
|
+
return vec2(-tangent.y, tangent.x);
|
|
1468
|
+
}
|
|
1469
|
+
`}function Ba(e){return`
|
|
1470
|
+
// Auto-generated path length (samples position 16 times)
|
|
1471
|
+
float path_${e}_length(vec2 source, vec2 target) {
|
|
1472
|
+
float len = 0.0;
|
|
1473
|
+
vec2 prev = path_${e}_position(0.0, source, target);
|
|
1474
|
+
for (int i = 1; i <= 16; i++) {
|
|
1475
|
+
float t = float(i) / 16.0;
|
|
1476
|
+
vec2 curr = path_${e}_position(t, source, target);
|
|
1477
|
+
len += length(curr - prev);
|
|
1478
|
+
prev = curr;
|
|
1479
|
+
}
|
|
1480
|
+
return len;
|
|
1481
|
+
}
|
|
1482
|
+
`}function Va(e){return`
|
|
1483
|
+
// Auto-generated closest_t (coarse sample + ternary search)
|
|
1484
|
+
float path_${e}_closest_t(vec2 p, vec2 source, vec2 target) {
|
|
1485
|
+
// Coarse search: find best among 10 samples
|
|
1486
|
+
float bestT = 0.0;
|
|
1487
|
+
float bestDist = 1e10;
|
|
1488
|
+
for (int i = 0; i <= 10; i++) {
|
|
1489
|
+
float t = float(i) / 10.0;
|
|
1490
|
+
vec2 pos = path_${e}_position(t, source, target);
|
|
1491
|
+
float d = length(p - pos);
|
|
1492
|
+
if (d < bestDist) {
|
|
1493
|
+
bestDist = d;
|
|
1494
|
+
bestT = t;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
// Refine with ternary search
|
|
1499
|
+
float lo = max(0.0, bestT - 0.1);
|
|
1500
|
+
float hi = min(1.0, bestT + 0.1);
|
|
1501
|
+
for (int i = 0; i < 10; i++) {
|
|
1502
|
+
float mid1 = lo + (hi - lo) / 3.0;
|
|
1503
|
+
float mid2 = hi - (hi - lo) / 3.0;
|
|
1504
|
+
float d1 = length(p - path_${e}_position(mid1, source, target));
|
|
1505
|
+
float d2 = length(p - path_${e}_position(mid2, source, target));
|
|
1506
|
+
if (d1 < d2) {
|
|
1507
|
+
hi = mid2;
|
|
1508
|
+
} else {
|
|
1509
|
+
lo = mid1;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
return (lo + hi) * 0.5;
|
|
1513
|
+
}
|
|
1514
|
+
`}function Ha(e){return`
|
|
1515
|
+
// Auto-generated signed distance (via closest_t + normal)
|
|
1516
|
+
float path_${e}_distance(vec2 p, vec2 source, vec2 target) {
|
|
1517
|
+
float closestT = path_${e}_closest_t(p, source, target);
|
|
1518
|
+
vec2 closest = path_${e}_position(closestT, source, target);
|
|
1519
|
+
vec2 diff = p - closest;
|
|
1520
|
+
float dist = length(diff);
|
|
1521
|
+
if (dist < 0.0001) return 0.0;
|
|
1522
|
+
|
|
1523
|
+
// Get normal at closest point
|
|
1524
|
+
vec2 normal = path_${e}_normal(closestT, source, target);
|
|
1525
|
+
return dist * sign(dot(diff, normal));
|
|
1526
|
+
}
|
|
1527
|
+
`}function Ua(e){return`
|
|
1528
|
+
// Auto-generated t_at_distance (binary search)
|
|
1529
|
+
float path_${e}_t_at_distance(float targetDist, vec2 source, vec2 target) {
|
|
1530
|
+
if (targetDist <= 0.0) return 0.0;
|
|
1531
|
+
|
|
1532
|
+
float totalLen = path_${e}_length(source, target);
|
|
1533
|
+
if (targetDist >= totalLen) return 1.0;
|
|
1534
|
+
|
|
1535
|
+
// Binary search for t
|
|
1536
|
+
float lo = 0.0, hi = 1.0;
|
|
1537
|
+
for (int i = 0; i < 12; i++) {
|
|
1538
|
+
float mid = (lo + hi) * 0.5;
|
|
1539
|
+
|
|
1540
|
+
// Compute arc length from 0 to mid
|
|
1541
|
+
float arcLen = 0.0;
|
|
1542
|
+
vec2 prev = path_${e}_position(0.0, source, target);
|
|
1543
|
+
for (int j = 1; j <= 8; j++) {
|
|
1544
|
+
float t = mid * float(j) / 8.0;
|
|
1545
|
+
vec2 curr = path_${e}_position(t, source, target);
|
|
1546
|
+
arcLen += length(curr - prev);
|
|
1547
|
+
prev = curr;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
if (arcLen < targetDist) {
|
|
1551
|
+
lo = mid;
|
|
1552
|
+
} else {
|
|
1553
|
+
hi = mid;
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
return (lo + hi) * 0.5;
|
|
1557
|
+
}
|
|
1558
|
+
`}function Wa(e,t){return RegExp(`\\b(float|vec[234]|void|int|bool)\\s+${t}\\s*\\(`).test(e)}function Ga(e,t){var n=[];return Wa(t,`path_${e}_length`)||n.push(Ba(e)),Wa(t,`path_${e}_closest_t`)||n.push(Va(e)),Wa(t,`path_${e}_distance`)||n.push(Ha(e)),Wa(t,`path_${e}_t_at_distance`)||n.push(Ua(e)),n.length>0?`
|
|
1559
|
+
// ============================================================================
|
|
1560
|
+
// Auto-generated fallback functions (path only provided position)
|
|
1561
|
+
// ============================================================================
|
|
1562
|
+
${n.join(`
|
|
1563
|
+
`)}`:``}function Ka(e){var t=e.paths,n=e.layers,r=e.extremities??[];if(t.length===0)throw Error(`At least one path is required in 'paths'`);if(n.length===0)throw Error(`At least one layer is required in 'layers'`);var i=e.defaultHead??`none`,a=e.defaultTail??`none`;return{paths:t,extremities:r,layers:n,path:t[0],layer:n[0],defaultHead:i,defaultTail:a}}var qa=WebGL2RenderingContext,Ja=qa.FLOAT,Ya=qa.UNSIGNED_BYTE;function Xa(e,t,n){var r=new Set(new Set([`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_zoomRatio`,`u_pixelRatio`,`u_cameraAngle`,`u_minEdgeThickness`,`u_pickingPadding`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_edgeDataTexture`,`u_edgeDataTextureWidth`,`u_edgeFrameTexture`,`u_edgeFrameTextureWidth`,`u_edgeAttributeTexture`,`u_edgeAttributeTextureWidth`,`u_edgeAttributeTexelsPerEdge`]));return e.forEach(function(e){return e.uniforms.forEach(function(e){return r.add(e.name)})}),t.forEach(function(e){return e.uniforms.forEach(function(e){return r.add(e.name)})}),n.forEach(function(e){return e.uniforms.forEach(function(e){return r.add(e.name)})}),Array.from(r)}function Za(e){var t=new Set,n=[],r=H(e),i;try{for(r.s();!(i=r.n()).done;){var a=i.value;t.has(a.name)||(t.add(a.name),n.push(`// Path: ${a.name}`),n.push(a.glsl),n.push(za(a.name)),n.push(Ga(a.name,a.glsl)))}}catch(e){r.e(e)}finally{r.f()}return n.join(`
|
|
1564
|
+
|
|
1565
|
+
`)}function Qa(e){var t=[],n=H(e),r;try{for(n.s();!(r=n.n()).done;){var i=r.value;t.push(`// Extremity: ${i.name}`),t.push(i.glsl)}}catch(e){n.e(e)}finally{n.f()}return t.join(`
|
|
1566
|
+
|
|
1567
|
+
`)}var $a=[{queryName:`queryPathPosition`,pathFunc:`position`,returnType:`vec2`,params:`float t, vec2 source, vec2 target`,args:`t, source, target`},{queryName:`queryPathTangent`,pathFunc:`tangent`,returnType:`vec2`,params:`float t, vec2 source, vec2 target`,args:`t, source, target`},{queryName:`queryPathNormal`,pathFunc:`normal`,returnType:`vec2`,params:`float t, vec2 source, vec2 target`,args:`t, source, target`},{queryName:`queryPathLength`,pathFunc:`length`,returnType:`float`,params:`vec2 source, vec2 target`,args:`source, target`},{queryName:`queryPathClosestT`,pathFunc:`closest_t`,returnType:`float`,params:`vec2 p, vec2 source, vec2 target`,args:`p, source, target`}];function eo(e,t){var n=t.queryName,r=t.pathFunc,i=t.returnType,a=t.params,o=t.args;return e.length===1?`${i} ${n}(int pathId, ${a}) {
|
|
1568
|
+
return path_${e[0].name}_${r}(${o});
|
|
1569
|
+
}`:`${i} ${n}(int pathId, ${a}) {
|
|
1570
|
+
switch (pathId) {
|
|
1571
|
+
${e.map(function(e,t){return` case ${t}: return path_${e.name}_${r}(${o});`}).join(`
|
|
1572
|
+
`)}
|
|
1573
|
+
default: return path_${e[0].name}_${r}(${o});
|
|
1574
|
+
}
|
|
1575
|
+
}`}function to(e){return $a.map(function(t){return eo(e,t)}).join(`
|
|
1576
|
+
|
|
1577
|
+
`)}function no(e){return e.length===1?`float queryExtremitySDF(int extremityId, vec2 uv, float lengthRatio, float widthRatio) {
|
|
1578
|
+
return extremity_${e[0].name}(uv, lengthRatio, widthRatio);
|
|
1579
|
+
}`:`float queryExtremitySDF(int extremityId, vec2 uv, float lengthRatio, float widthRatio) {
|
|
1580
|
+
switch (extremityId) {
|
|
1581
|
+
${e.map(function(e,t){return` case ${t}: return extremity_${e.name}(uv, lengthRatio, widthRatio);`}).join(`
|
|
1582
|
+
`)}
|
|
1583
|
+
default: return extremity_${e[0].name}(uv, lengthRatio, widthRatio);
|
|
1584
|
+
}
|
|
1585
|
+
}`}function ro(e){var t=[],n=H(e),r;try{for(n.s();!(r=n.n()).done;){var i=r.value;t.push(La(i.name)),t.push(Ra(i.name))}}catch(e){n.e(e)}finally{n.f()}if(e.length===1)t.push(`
|
|
1586
|
+
float queryFindSourceClampT(int pathId, vec2 source, float sourceSize, int sourceShapeId, float sourceRotateAlign, vec2 target, float margin) {
|
|
1587
|
+
return findSourceClampT_${e[0].name}(source, sourceSize, sourceShapeId, sourceRotateAlign, target, margin);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
float queryFindTargetClampT(int pathId, vec2 source, vec2 target, float targetSize, int targetShapeId, float targetRotateAlign, float margin) {
|
|
1591
|
+
return findTargetClampT_${e[0].name}(source, target, targetSize, targetShapeId, targetRotateAlign, margin);
|
|
1592
|
+
}`);else{var a=e.map(function(e,t){return` case ${t}: return findSourceClampT_${e.name}(source, sourceSize, sourceShapeId, sourceRotateAlign, target, margin);`}).join(`
|
|
1593
|
+
`),o=e.map(function(e,t){return` case ${t}: return findTargetClampT_${e.name}(source, target, targetSize, targetShapeId, targetRotateAlign, margin);`}).join(`
|
|
1594
|
+
`);t.push(`
|
|
1595
|
+
float queryFindSourceClampT(int pathId, vec2 source, float sourceSize, int sourceShapeId, float sourceRotateAlign, vec2 target, float margin) {
|
|
1596
|
+
switch (pathId) {
|
|
1597
|
+
${a}
|
|
1598
|
+
default: return findSourceClampT_${e[0].name}(source, sourceSize, sourceShapeId, sourceRotateAlign, target, margin);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
float queryFindTargetClampT(int pathId, vec2 source, vec2 target, float targetSize, int targetShapeId, float targetRotateAlign, float margin) {
|
|
1603
|
+
switch (pathId) {
|
|
1604
|
+
${o}
|
|
1605
|
+
default: return findTargetClampT_${e[0].name}(source, target, targetSize, targetShapeId, targetRotateAlign, margin);
|
|
1606
|
+
}
|
|
1607
|
+
}`)}return t.join(`
|
|
1608
|
+
|
|
1609
|
+
`)}function io(e,t,n,r,i){var a=Ia(zi([].concat(Y(e),Y(n)))),o=ta(r,i),s=Object.keys(o.offsets),c=function(e){var t=o.specs[e].size;return t===1?`float`:`vec${t}`},l=s.map(function(e){return`${c(e)} v_source_${e};
|
|
1610
|
+
${c(e)} v_target_${e};`}).join(`
|
|
1611
|
+
`),u=Wi(o,{varPrefix:`srcNodeAttr`,baseTexelExpr:`srcIdx * u_layerAttributeTexelsPerNode`,textureWidthUniform:`u_layerAttributeTextureWidth`,textureSamplerUniform:`u_layerAttributeTexture`,outputPrefix:`v_source_`}),d=Wi(o,{varPrefix:`tgtNodeAttr`,baseTexelExpr:`tgtIdx * u_layerAttributeTexelsPerNode`,textureWidthUniform:`u_layerAttributeTextureWidth`,textureSamplerUniform:`u_layerAttributeTexture`,outputPrefix:`v_target_`}),f=s.map(function(e){return`${c(e)} g_${e};`}).join(`
|
|
1612
|
+
`),p=s.map(function(e){return` g_${e} = v_source_${e};`}).join(`
|
|
1613
|
+
`),m=s.map(function(e){return` g_${e} = v_target_${e};`}).join(`
|
|
1614
|
+
`),h=new Set,g=[],_=function(e){h.has(e.name)||(h.add(e.name),g.push(`uniform ${e.type} ${e.name};`))};e.forEach(function(e){return e.uniforms.forEach(_)}),t.forEach(function(e){return e.uniforms.forEach(_)});var v=t.map(function(e){return Z(e.widthFactor)}).join(`, `),y=Math.max.apply(Math,Y(e.map(function(e){return e.minBodyLengthRatio||0})));return`#version 300 es
|
|
1615
|
+
|
|
1616
|
+
// Node and edge data textures
|
|
1617
|
+
uniform sampler2D u_nodeDataTexture;
|
|
1618
|
+
uniform int u_nodeDataTextureWidth;
|
|
1619
|
+
uniform sampler2D u_edgeDataTexture;
|
|
1620
|
+
uniform int u_edgeDataTextureWidth;
|
|
1621
|
+
|
|
1622
|
+
// Edge attribute texture (for path-specific attributes like curvature)
|
|
1623
|
+
${a.uniformDeclarations}
|
|
1624
|
+
|
|
1625
|
+
// Node attribute texture (for node shape attributes)
|
|
1626
|
+
uniform sampler2D u_layerAttributeTexture;
|
|
1627
|
+
uniform int u_layerAttributeTextureWidth;
|
|
1628
|
+
uniform int u_layerAttributeTexelsPerNode;
|
|
1629
|
+
|
|
1630
|
+
// Render params needed for clamping
|
|
1631
|
+
uniform float u_sizeRatio;
|
|
1632
|
+
uniform float u_correctionRatio;
|
|
1633
|
+
uniform float u_cameraAngle;
|
|
1634
|
+
uniform float u_minEdgeThickness;
|
|
1635
|
+
|
|
1636
|
+
// Edge-frame texture dimensions, for scattering each point to its texel
|
|
1637
|
+
uniform float u_frameTextureWidth;
|
|
1638
|
+
uniform float u_frameTextureHeight;
|
|
1639
|
+
|
|
1640
|
+
// Custom path/extremity uniforms
|
|
1641
|
+
${g.join(`
|
|
1642
|
+
`)}
|
|
1643
|
+
|
|
1644
|
+
// Path attribute varyings — assigned so path functions can read them as globals
|
|
1645
|
+
${a.vertexVaryingDeclarations}
|
|
1646
|
+
|
|
1647
|
+
// Node size varyings — read by path functions like loop
|
|
1648
|
+
out float v_sourceNodeSize;
|
|
1649
|
+
out float v_targetNodeSize;
|
|
1650
|
+
|
|
1651
|
+
// Node shape attributes per endpoint, and the ones querySDF reads
|
|
1652
|
+
${l}
|
|
1653
|
+
${f}
|
|
1654
|
+
|
|
1655
|
+
// Scattered output written to the edge-frame texel: [tStart, tEnd, straightenFactor, pathLength]
|
|
1656
|
+
out vec4 v_clamp;
|
|
1657
|
+
|
|
1658
|
+
// Extremity width factor array (needed for extremityScale computation)
|
|
1659
|
+
const float EXTREMITY_WIDTH_FACTORS[${t.length}] = float[](${v});
|
|
1660
|
+
|
|
1661
|
+
// Node-data fetch helpers (geometry texel + rotation-flags texel)
|
|
1662
|
+
${Ei}
|
|
1663
|
+
${Di}
|
|
1664
|
+
|
|
1665
|
+
// Shape SDFs for node boundary clamping
|
|
1666
|
+
${fi()}
|
|
1667
|
+
${pi(new Set(s))}
|
|
1668
|
+
|
|
1669
|
+
// Path functions
|
|
1670
|
+
${Za(e)}
|
|
1671
|
+
${to(e)}
|
|
1672
|
+
${ro(e)}
|
|
1673
|
+
|
|
1674
|
+
void main() {
|
|
1675
|
+
// One point per edge-data row; the row index is the edge-frame texel target.
|
|
1676
|
+
int edgeIdx = gl_VertexID;
|
|
1677
|
+
int texel0Idx = edgeIdx * 2;
|
|
1678
|
+
int texel1Idx = edgeIdx * 2 + 1;
|
|
1679
|
+
ivec2 edgeTexCoord0 = ivec2(texel0Idx % u_edgeDataTextureWidth, texel0Idx / u_edgeDataTextureWidth);
|
|
1680
|
+
ivec2 edgeTexCoord1 = ivec2(texel1Idx % u_edgeDataTextureWidth, texel1Idx / u_edgeDataTextureWidth);
|
|
1681
|
+
vec4 edgeData0 = texelFetch(u_edgeDataTexture, edgeTexCoord0, 0);
|
|
1682
|
+
vec4 edgeData1 = texelFetch(u_edgeDataTexture, edgeTexCoord1, 0);
|
|
1683
|
+
|
|
1684
|
+
int srcIdx = int(edgeData0.x);
|
|
1685
|
+
int tgtIdx = int(edgeData0.y);
|
|
1686
|
+
float a_thickness = edgeData0.z;
|
|
1687
|
+
float a_headLengthRatio = edgeData1.x;
|
|
1688
|
+
float a_tailLengthRatio = edgeData1.y;
|
|
1689
|
+
int pathId = int(edgeData1.z);
|
|
1690
|
+
int extremityPacked = int(edgeData1.w);
|
|
1691
|
+
int headId = extremityPacked >> 4;
|
|
1692
|
+
int tailId = extremityPacked & 15;
|
|
1693
|
+
|
|
1694
|
+
// Fetch path/layer attributes and assign to path-function globals
|
|
1695
|
+
${a.fetchCode}
|
|
1696
|
+
${a.varyingAssignments}
|
|
1697
|
+
|
|
1698
|
+
// Fetch node shape attributes for both endpoints
|
|
1699
|
+
${u.fetchCode}
|
|
1700
|
+
${u.varyingAssignments}
|
|
1701
|
+
${d.fetchCode}
|
|
1702
|
+
${d.varyingAssignments}
|
|
1703
|
+
|
|
1704
|
+
// Fetch node geometry (texel 0) and rotation flags (texel 1).
|
|
1705
|
+
vec4 srcNodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, srcIdx);
|
|
1706
|
+
vec4 tgtNodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, tgtIdx);
|
|
1707
|
+
|
|
1708
|
+
vec2 a_source = srcNodeData.xy;
|
|
1709
|
+
vec2 a_target = tgtNodeData.xy;
|
|
1710
|
+
float a_sourceSize = srcNodeData.z;
|
|
1711
|
+
float a_targetSize = tgtNodeData.z;
|
|
1712
|
+
float a_sourceShapeId = srcNodeData.w;
|
|
1713
|
+
float a_targetShapeId = tgtNodeData.w;
|
|
1714
|
+
// Per-node rotation alignment (0 = viewport, 1 = graph), for boundary clamping.
|
|
1715
|
+
float a_sourceRotateAlign = readNodeFlags(u_nodeDataTexture, u_nodeDataTextureWidth, srcIdx).r;
|
|
1716
|
+
float a_targetRotateAlign = readNodeFlags(u_nodeDataTexture, u_nodeDataTextureWidth, tgtIdx).r;
|
|
1717
|
+
|
|
1718
|
+
v_sourceNodeSize = a_sourceSize;
|
|
1719
|
+
v_targetNodeSize = a_targetSize;
|
|
1720
|
+
|
|
1721
|
+
float headLengthRatio = a_headLengthRatio;
|
|
1722
|
+
float tailLengthRatio = a_tailLengthRatio;
|
|
1723
|
+
float headWidthFactor = EXTREMITY_WIDTH_FACTORS[headId];
|
|
1724
|
+
float tailWidthFactor = EXTREMITY_WIDTH_FACTORS[tailId];
|
|
1725
|
+
float minBodyLengthRatio = ${Z(y)};
|
|
1726
|
+
|
|
1727
|
+
// Thickness in WebGL units (needed to compute clamping margin and extremity lengths)
|
|
1728
|
+
float pixelsThickness = max(a_thickness, u_minEdgeThickness * u_sizeRatio);
|
|
1729
|
+
float webGLThickness = pixelsThickness * u_correctionRatio / u_sizeRatio;
|
|
1730
|
+
|
|
1731
|
+
// SDF clamping: find where the edge body meets the node boundaries. Always
|
|
1732
|
+
// searched (ungated) so labels get a true boundary clamp; the body re-applies
|
|
1733
|
+
// its extremity gating in-shader.
|
|
1734
|
+
${p}
|
|
1735
|
+
float tStart = queryFindSourceClampT(pathId, a_source, a_sourceSize, int(a_sourceShapeId), a_sourceRotateAlign, a_target, 0.0);
|
|
1736
|
+
${m}
|
|
1737
|
+
float tEnd = queryFindTargetClampT(pathId, a_source, a_target, a_targetSize, int(a_targetShapeId), a_targetRotateAlign, 0.0);
|
|
1738
|
+
|
|
1739
|
+
// straightenFactor (frame .z) is consumed only by the body, which runs to the
|
|
1740
|
+
// node center when an extremity is absent. Derive the straightening math from
|
|
1741
|
+
// these gated clamps — not the ungated boundary ones above — so it matches the
|
|
1742
|
+
// geometry it drives. The ungated tStart/tEnd remain what labels read.
|
|
1743
|
+
float bodyTStart = tailLengthRatio > 0.0 ? tStart : 0.0;
|
|
1744
|
+
float bodyTEnd = headLengthRatio > 0.0 ? tEnd : 1.0;
|
|
1745
|
+
|
|
1746
|
+
// Path length and zone boundaries (needed for straightening check)
|
|
1747
|
+
float pathLength = queryPathLength(pathId, a_source, a_target);
|
|
1748
|
+
float visibleLength = pathLength * (bodyTEnd - bodyTStart);
|
|
1749
|
+
|
|
1750
|
+
float headLength = headLengthRatio * webGLThickness;
|
|
1751
|
+
float tailLength = tailLengthRatio * webGLThickness;
|
|
1752
|
+
float minBodyLength = minBodyLengthRatio * webGLThickness;
|
|
1753
|
+
|
|
1754
|
+
float totalNeededLength = headLength + tailLength + minBodyLength;
|
|
1755
|
+
float extremityScale = 1.0;
|
|
1756
|
+
if (totalNeededLength > visibleLength && totalNeededLength > 0.0001) {
|
|
1757
|
+
extremityScale = visibleLength / totalNeededLength;
|
|
1758
|
+
headLength *= extremityScale;
|
|
1759
|
+
tailLength *= extremityScale;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
float headLengthT = pathLength > 0.0001 ? headLength / pathLength : 0.0;
|
|
1763
|
+
float tailLengthT = pathLength > 0.0001 ? tailLength / pathLength : 0.0;
|
|
1764
|
+
|
|
1765
|
+
float tTailEnd = bodyTStart + tailLengthT;
|
|
1766
|
+
float tHeadStart = bodyTEnd - headLengthT;
|
|
1767
|
+
if (tTailEnd > tHeadStart) {
|
|
1768
|
+
float mid = (bodyTStart + bodyTEnd) * 0.5;
|
|
1769
|
+
tTailEnd = mid;
|
|
1770
|
+
tHeadStart = mid;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
// Straighten factor: blend toward straight line when path twists in extremity zones
|
|
1774
|
+
float straightenFactor = 0.0;
|
|
1775
|
+
{
|
|
1776
|
+
float maxDeviation = 0.0;
|
|
1777
|
+
if (tailLengthT > 0.0001) {
|
|
1778
|
+
vec2 tailTang = queryPathTangent(pathId, tTailEnd, a_source, a_target);
|
|
1779
|
+
vec2 tailChord = queryPathPosition(pathId, bodyTStart, a_source, a_target)
|
|
1780
|
+
- queryPathPosition(pathId, tTailEnd, a_source, a_target);
|
|
1781
|
+
float tailChordLen = length(tailChord);
|
|
1782
|
+
if (tailChordLen > 0.0001) {
|
|
1783
|
+
maxDeviation = max(maxDeviation, 1.0 - dot(-tailTang, tailChord / tailChordLen));
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
if (headLengthT > 0.0001) {
|
|
1787
|
+
vec2 headTang = queryPathTangent(pathId, tHeadStart, a_source, a_target);
|
|
1788
|
+
vec2 headChord = queryPathPosition(pathId, bodyTEnd, a_source, a_target)
|
|
1789
|
+
- queryPathPosition(pathId, tHeadStart, a_source, a_target);
|
|
1790
|
+
float headChordLen = length(headChord);
|
|
1791
|
+
if (headChordLen > 0.0001) {
|
|
1792
|
+
maxDeviation = max(maxDeviation, 1.0 - dot(headTang, headChord / headChordLen));
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
straightenFactor = smoothstep(0.035, 0.5, maxDeviation);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
// When straightening, blend the ungated tStart/tEnd (the label-facing clamps)
|
|
1799
|
+
// toward straight-line clamp positions.
|
|
1800
|
+
if (straightenFactor > 0.001) {
|
|
1801
|
+
if (tailLengthRatio > 0.0) {
|
|
1802
|
+
${p}
|
|
1803
|
+
float srcExtent = a_sourceSize * u_correctionRatio / u_sizeRatio * 2.0;
|
|
1804
|
+
float srcEffective = 1.0 - u_correctionRatio / srcExtent;
|
|
1805
|
+
float srcCa = u_cameraAngle * (1.0 - a_sourceRotateAlign);
|
|
1806
|
+
mat2 srcRot = mat2(cos(srcCa), -sin(srcCa), sin(srcCa), cos(srcCa));
|
|
1807
|
+
float lo = 0.0, hi = 0.5;
|
|
1808
|
+
for (int i = 0; i < 12; i++) {
|
|
1809
|
+
float mid = (lo + hi) * 0.5;
|
|
1810
|
+
vec2 pos = mix(a_source, a_target, mid);
|
|
1811
|
+
vec2 localPos = srcRot * ((pos - a_source) / srcExtent);
|
|
1812
|
+
float sdf = querySDF(int(a_sourceShapeId), localPos, srcEffective);
|
|
1813
|
+
if (sdf < 0.0) lo = mid; else hi = mid;
|
|
1814
|
+
}
|
|
1815
|
+
tStart = mix(tStart, (lo + hi) * 0.5, straightenFactor);
|
|
1816
|
+
}
|
|
1817
|
+
if (headLengthRatio > 0.0) {
|
|
1818
|
+
${m}
|
|
1819
|
+
float tgtExtent = a_targetSize * u_correctionRatio / u_sizeRatio * 2.0;
|
|
1820
|
+
float tgtEffective = 1.0 - u_correctionRatio / tgtExtent;
|
|
1821
|
+
float tgtCa = u_cameraAngle * (1.0 - a_targetRotateAlign);
|
|
1822
|
+
mat2 tgtRot = mat2(cos(tgtCa), -sin(tgtCa), sin(tgtCa), cos(tgtCa));
|
|
1823
|
+
float lo = 0.5, hi = 1.0;
|
|
1824
|
+
for (int i = 0; i < 12; i++) {
|
|
1825
|
+
float mid = (lo + hi) * 0.5;
|
|
1826
|
+
vec2 pos = mix(a_source, a_target, mid);
|
|
1827
|
+
vec2 localPos = tgtRot * ((pos - a_target) / tgtExtent);
|
|
1828
|
+
float sdf = querySDF(int(a_targetShapeId), localPos, tgtEffective);
|
|
1829
|
+
if (sdf < 0.0) hi = mid; else lo = mid;
|
|
1830
|
+
}
|
|
1831
|
+
tEnd = mix(tEnd, (lo + hi) * 0.5, straightenFactor);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
v_clamp = vec4(tStart, tEnd, straightenFactor, pathLength);
|
|
1836
|
+
|
|
1837
|
+
// Scatter this point to its edge's texel center in the frame texture.
|
|
1838
|
+
float x = mod(float(edgeIdx), u_frameTextureWidth);
|
|
1839
|
+
float y = floor(float(edgeIdx) / u_frameTextureWidth);
|
|
1840
|
+
vec2 ndc = (vec2(x, y) + 0.5) / vec2(u_frameTextureWidth, u_frameTextureHeight) * 2.0 - 1.0;
|
|
1841
|
+
gl_Position = vec4(ndc, 0.0, 1.0);
|
|
1842
|
+
gl_PointSize = 1.0;
|
|
1843
|
+
}
|
|
1844
|
+
`}var ao=0,oo=1,so=2;function co(e,t,n){var r=[];n&&(r.push([ao,0,-1],[ao,0,1]),r.push([ao,1,-1],[ao,1,1]));for(var i=0;i<=e;i++){var a=i/e;r.push([oo,a,-1],[oo,a,1])}return t&&(r.push([so,0,-1],[so,0,1]),r.push([so,1,-1],[so,1,1])),{data:r,attributes:[{name:`a_zone`,size:1,type:Ja},{name:`a_zoneT`,size:1,type:Ja},{name:`a_side`,size:1,type:Ja}],verticesPerEdge:r.length}}function lo(e,t,n,r){var i=Ia(zi([].concat(Y(e),Y(n)))),a=new Set([`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_zoomRatio`,`u_pixelRatio`,`u_cameraAngle`,`u_minEdgeThickness`,`u_pickingPadding`,`u_nodeDataTexture`]),o=new Set,s=[],c=function(e){!a.has(e.name)&&!o.has(e.name)&&(o.add(e.name),s.push(`uniform ${e.type} ${e.name};`))};e.forEach(function(e){return e.uniforms.forEach(c)}),t.forEach(function(e){return e.uniforms.forEach(c)}),n.forEach(function(e){return e.uniforms.forEach(c)});var l=r.map(function(e){return`in ${e.size===1?`float`:`vec${e.size}`} ${e.name};`}).join(`
|
|
1845
|
+
`),u=t.map(function(e){return Z(e.widthFactor)}).join(`, `),d=Math.max.apply(Math,Y(e.map(function(e){return e.minBodyLengthRatio||0}))),f=n.some(function(e){return e.needsNodeColors}),p=e.some(function(e){return e.needsNodeSize});return`#version 300 es
|
|
1846
|
+
|
|
1847
|
+
// Constant attributes (per vertex)
|
|
1848
|
+
${l}
|
|
1849
|
+
|
|
1850
|
+
// Per-edge attributes
|
|
1851
|
+
// Edge data (source/target indices, thickness, extremity ratios, path/extremity IDs)
|
|
1852
|
+
// is fetched from edge data texture via edge index
|
|
1853
|
+
in float a_edgeIndex; // Index into edge data texture
|
|
1854
|
+
in vec4 a_color; // Edge color
|
|
1855
|
+
in vec4 a_id; // Edge ID for picking
|
|
1856
|
+
in float a_opacity; // Edge opacity
|
|
1857
|
+
|
|
1858
|
+
// Standard uniforms
|
|
1859
|
+
uniform mat3 u_matrix;
|
|
1860
|
+
uniform float u_sizeRatio;
|
|
1861
|
+
uniform float u_correctionRatio;
|
|
1862
|
+
uniform float u_zoomRatio;
|
|
1863
|
+
uniform float u_pixelRatio;
|
|
1864
|
+
uniform float u_cameraAngle;
|
|
1865
|
+
uniform float u_minEdgeThickness;
|
|
1866
|
+
#ifdef PICKING_MODE
|
|
1867
|
+
uniform float u_pickingPadding;
|
|
1868
|
+
#endif
|
|
1869
|
+
uniform sampler2D u_nodeDataTexture;
|
|
1870
|
+
uniform int u_nodeDataTextureWidth;
|
|
1871
|
+
uniform sampler2D u_edgeDataTexture;
|
|
1872
|
+
uniform int u_edgeDataTextureWidth;
|
|
1873
|
+
uniform sampler2D u_edgeFrameTexture;
|
|
1874
|
+
uniform int u_edgeFrameTextureWidth;
|
|
1875
|
+
|
|
1876
|
+
// Edge path attribute texture uniforms
|
|
1877
|
+
${i.uniformDeclarations}
|
|
1878
|
+
|
|
1879
|
+
// Custom uniforms
|
|
1880
|
+
${s.join(`
|
|
1881
|
+
`)}
|
|
1882
|
+
|
|
1883
|
+
// Standard varyings
|
|
1884
|
+
out vec4 v_color;
|
|
1885
|
+
out float v_opacity;
|
|
1886
|
+
out vec4 v_id;
|
|
1887
|
+
out float v_thickness; // Edge body thickness (in consistent units)
|
|
1888
|
+
out float v_t;
|
|
1889
|
+
out float v_tStart;
|
|
1890
|
+
out float v_tEnd;
|
|
1891
|
+
out float v_side;
|
|
1892
|
+
out float v_antialiasingWidth; // Anti-aliasing width (normalized: u_correctionRatio / thickness)
|
|
1893
|
+
out vec2 v_source;
|
|
1894
|
+
out vec2 v_target;
|
|
1895
|
+
out float v_edgeLength;
|
|
1896
|
+
${p?`
|
|
1897
|
+
out float v_sourceNodeSize; // Source node size (mirrored in labels/generator.ts as plain float)
|
|
1898
|
+
out float v_targetNodeSize; // Target node size (mirrored in labels/generator.ts as plain float)`:``}
|
|
1899
|
+
${f?`
|
|
1900
|
+
out vec4 v_sourceColor;
|
|
1901
|
+
out vec4 v_targetColor;`:``}
|
|
1902
|
+
// Zone varyings
|
|
1903
|
+
out float v_zone; // 0=tail, 1=body, 2=head
|
|
1904
|
+
out float v_zoneT; // Position within zone [0,1]
|
|
1905
|
+
out float v_headLengthRatio; // Head length as ratio of thickness
|
|
1906
|
+
out float v_tailLengthRatio; // Tail length as ratio of thickness
|
|
1907
|
+
out float v_headWidthRatio; // Head width factor
|
|
1908
|
+
out float v_tailWidthRatio; // Tail width factor
|
|
1909
|
+
|
|
1910
|
+
// Multi-path/extremity varyings
|
|
1911
|
+
flat out int v_pathId;
|
|
1912
|
+
flat out int v_headId;
|
|
1913
|
+
flat out int v_tailId;
|
|
1914
|
+
|
|
1915
|
+
// Path/layer attribute varyings (fetched from edge attribute texture)
|
|
1916
|
+
${i.vertexVaryingDeclarations}
|
|
1917
|
+
|
|
1918
|
+
const float bias = 255.0 / 254.0;
|
|
1919
|
+
|
|
1920
|
+
// Width factor array for extremities (shared pool for head/tail)
|
|
1921
|
+
const float EXTREMITY_WIDTH_FACTORS[${t.length}] = float[](${u});
|
|
1922
|
+
|
|
1923
|
+
// All path functions
|
|
1924
|
+
${Za(e)}
|
|
1925
|
+
|
|
1926
|
+
// Path selector functions
|
|
1927
|
+
${to(e)}
|
|
1928
|
+
|
|
1929
|
+
// Node-data fetch helper (geometry texel of the two-texel node stride)
|
|
1930
|
+
${Ei}
|
|
1931
|
+
${f?Oi:``}
|
|
1932
|
+
// Per-edge clamp from the frame-pass (tStart, tEnd, straightenFactor, pathLength)
|
|
1933
|
+
${ki}
|
|
1934
|
+
|
|
1935
|
+
void main() {
|
|
1936
|
+
// Fetch edge data from edge texture (2 texels per edge)
|
|
1937
|
+
// Texel 0: sourceNodeIndex, targetNodeIndex, thickness, reserved
|
|
1938
|
+
// Texel 1: headLengthRatio, tailLengthRatio, pathId, (headId << 4) | tailId
|
|
1939
|
+
int edgeIdx = int(a_edgeIndex);
|
|
1940
|
+
|
|
1941
|
+
// Hidden edges are flagged with a negative row by EdgeProgram.process(). Push
|
|
1942
|
+
// the whole primitive outside the clip volume: every vertex lands at the same
|
|
1943
|
+
// out-of-range position, so it is fully clipped and rasterizes nothing —
|
|
1944
|
+
// neither to the frame buffer nor to the picking buffer.
|
|
1945
|
+
if (edgeIdx < 0) {
|
|
1946
|
+
gl_Position = vec4(2.0, 0.0, 0.0, 1.0);
|
|
1947
|
+
v_color = vec4(0.0);
|
|
1948
|
+
v_id = vec4(0.0);
|
|
1949
|
+
return;
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
int texel0Idx = edgeIdx * 2;
|
|
1953
|
+
int texel1Idx = edgeIdx * 2 + 1;
|
|
1954
|
+
ivec2 edgeTexCoord0 = ivec2(texel0Idx % u_edgeDataTextureWidth, texel0Idx / u_edgeDataTextureWidth);
|
|
1955
|
+
ivec2 edgeTexCoord1 = ivec2(texel1Idx % u_edgeDataTextureWidth, texel1Idx / u_edgeDataTextureWidth);
|
|
1956
|
+
vec4 edgeData0 = texelFetch(u_edgeDataTexture, edgeTexCoord0, 0);
|
|
1957
|
+
vec4 edgeData1 = texelFetch(u_edgeDataTexture, edgeTexCoord1, 0);
|
|
1958
|
+
|
|
1959
|
+
// Unpack edge data
|
|
1960
|
+
int srcIdx = int(edgeData0.x);
|
|
1961
|
+
int tgtIdx = int(edgeData0.y);
|
|
1962
|
+
float a_thickness = edgeData0.z;
|
|
1963
|
+
// edgeData0.w is now reserved (curvature moved to path attribute texture)
|
|
1964
|
+
float a_headLengthRatio = edgeData1.x;
|
|
1965
|
+
float a_tailLengthRatio = edgeData1.y;
|
|
1966
|
+
int pathId = int(edgeData1.z);
|
|
1967
|
+
int extremityPacked = int(edgeData1.w);
|
|
1968
|
+
int headId = extremityPacked >> 4;
|
|
1969
|
+
int tailId = extremityPacked & 15;
|
|
1970
|
+
|
|
1971
|
+
// Fetch path/layer attributes from edge attribute texture
|
|
1972
|
+
${i.fetchCode}
|
|
1973
|
+
|
|
1974
|
+
// Assign path/layer attribute varyings
|
|
1975
|
+
${i.varyingAssignments}
|
|
1976
|
+
|
|
1977
|
+
// Fetch source and target node geometry (texel 0 of the two-texel node stride)
|
|
1978
|
+
vec4 srcNodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, srcIdx);
|
|
1979
|
+
vec4 tgtNodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, tgtIdx);
|
|
1980
|
+
|
|
1981
|
+
vec2 a_source = srcNodeData.xy;
|
|
1982
|
+
vec2 a_target = tgtNodeData.xy;
|
|
1983
|
+
${p?`
|
|
1984
|
+
// Assign node size varyings early (path functions like loops need them during clamping)
|
|
1985
|
+
v_sourceNodeSize = srcNodeData.z;
|
|
1986
|
+
v_targetNodeSize = tgtNodeData.z;`:``}
|
|
1987
|
+
${f?`
|
|
1988
|
+
v_sourceColor = readNodeColor(u_nodeDataTexture, u_nodeDataTextureWidth, srcIdx);
|
|
1989
|
+
v_targetColor = readNodeColor(u_nodeDataTexture, u_nodeDataTextureWidth, tgtIdx);`:``}
|
|
1990
|
+
|
|
1991
|
+
// Convert thickness to WebGL units
|
|
1992
|
+
float minThickness = u_minEdgeThickness;
|
|
1993
|
+
float pixelsThickness = max(a_thickness, minThickness * u_sizeRatio);
|
|
1994
|
+
float webGLThickness = pixelsThickness * u_correctionRatio / u_sizeRatio;
|
|
1995
|
+
|
|
1996
|
+
// Extremity parameters from ID lookups (shared pool)
|
|
1997
|
+
float headLengthRatio = a_headLengthRatio;
|
|
1998
|
+
float tailLengthRatio = a_tailLengthRatio;
|
|
1999
|
+
float headWidthFactor = EXTREMITY_WIDTH_FACTORS[headId];
|
|
2000
|
+
float tailWidthFactor = EXTREMITY_WIDTH_FACTORS[tailId];
|
|
2001
|
+
float minBodyLengthRatio = ${Z(d)};
|
|
2002
|
+
|
|
2003
|
+
// Per-edge values from the frame-pass texture (read by edge index).
|
|
2004
|
+
// tStart/tEnd are the ungated boundary clamps: re-apply the body's extremity
|
|
2005
|
+
// gating here (no extremity → body runs to the node center, 0/1).
|
|
2006
|
+
vec4 frameClamp = readFrameTexel(u_edgeFrameTexture, u_edgeFrameTextureWidth, edgeIdx);
|
|
2007
|
+
float tStart = a_tailLengthRatio > 0.0 ? frameClamp.x : 0.0;
|
|
2008
|
+
float tEnd = a_headLengthRatio > 0.0 ? frameClamp.y : 1.0;
|
|
2009
|
+
float straightenFactor = frameClamp.z;
|
|
2010
|
+
float pathLength = frameClamp.w;
|
|
2011
|
+
|
|
2012
|
+
// Anti-aliasing width (~1 pixel, normalized by thickness)
|
|
2013
|
+
float antialiasingWidth = u_correctionRatio / webGLThickness;
|
|
2014
|
+
|
|
2015
|
+
float visibleLength = pathLength * (tEnd - tStart);
|
|
2016
|
+
|
|
2017
|
+
// Compute extremity lengths in world units
|
|
2018
|
+
float headLength = headLengthRatio * webGLThickness;
|
|
2019
|
+
float tailLength = tailLengthRatio * webGLThickness;
|
|
2020
|
+
float minBodyLength = minBodyLengthRatio * webGLThickness;
|
|
2021
|
+
|
|
2022
|
+
// Handle short edges: scale down extremities if needed
|
|
2023
|
+
float totalNeededLength = headLength + tailLength + minBodyLength;
|
|
2024
|
+
float extremityScale = 1.0;
|
|
2025
|
+
if (totalNeededLength > visibleLength && totalNeededLength > 0.0001) {
|
|
2026
|
+
extremityScale = visibleLength / totalNeededLength;
|
|
2027
|
+
headLength *= extremityScale;
|
|
2028
|
+
tailLength *= extremityScale;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
// Convert lengths to t-values
|
|
2032
|
+
float headLengthT = pathLength > 0.0001 ? headLength / pathLength : 0.0;
|
|
2033
|
+
float tailLengthT = pathLength > 0.0001 ? tailLength / pathLength : 0.0;
|
|
2034
|
+
|
|
2035
|
+
// Zone boundaries in t-space
|
|
2036
|
+
float tTailEnd = tStart + tailLengthT;
|
|
2037
|
+
float tHeadStart = tEnd - headLengthT;
|
|
2038
|
+
|
|
2039
|
+
// Ensure body has non-negative length
|
|
2040
|
+
if (tTailEnd > tHeadStart) {
|
|
2041
|
+
float mid = (tStart + tEnd) * 0.5;
|
|
2042
|
+
tTailEnd = mid;
|
|
2043
|
+
tHeadStart = mid;
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
// Convert to webGL units for geometry expansion
|
|
2047
|
+
float aaWidthWebGL = antialiasingWidth * webGLThickness;
|
|
2048
|
+
|
|
2049
|
+
// Extra geometry width for picking padding (0 in visual mode)
|
|
2050
|
+
#ifdef PICKING_MODE
|
|
2051
|
+
float pickingPaddingWebGL = u_pickingPadding * u_correctionRatio;
|
|
2052
|
+
#else
|
|
2053
|
+
float pickingPaddingWebGL = 0.0;
|
|
2054
|
+
#endif
|
|
2055
|
+
|
|
2056
|
+
// Straight-line direction and normal (for blending when straightenFactor > 0)
|
|
2057
|
+
vec2 straightDir = length(a_target - a_source) > 0.0001
|
|
2058
|
+
? normalize(a_target - a_source) : vec2(1.0, 0.0);
|
|
2059
|
+
vec2 straightNormal = vec2(-straightDir.y, straightDir.x);
|
|
2060
|
+
|
|
2061
|
+
// Zone-based vertex processing using path selectors
|
|
2062
|
+
vec2 position;
|
|
2063
|
+
vec2 normal;
|
|
2064
|
+
float t;
|
|
2065
|
+
float zone = a_zone;
|
|
2066
|
+
float zoneT = a_zoneT;
|
|
2067
|
+
float side = a_side;
|
|
2068
|
+
|
|
2069
|
+
// Scaled extremity width factors (geometry must be at least as wide as body)
|
|
2070
|
+
float scaledTailWidth = max(tailWidthFactor * extremityScale, 1.0);
|
|
2071
|
+
float scaledHeadWidth = max(headWidthFactor * extremityScale, 1.0);
|
|
2072
|
+
|
|
2073
|
+
if (zone < 0.5) {
|
|
2074
|
+
// TAIL ZONE: rectangular quad with scaled width
|
|
2075
|
+
vec2 tang = queryPathTangent(pathId, tTailEnd, a_source, a_target);
|
|
2076
|
+
normal = vec2(-tang.y, tang.x);
|
|
2077
|
+
vec2 centerPos = mix(queryPathPosition(pathId, tStart, a_source, a_target),
|
|
2078
|
+
queryPathPosition(pathId, tTailEnd, a_source, a_target), zoneT);
|
|
2079
|
+
float halfWidth = webGLThickness * scaledTailWidth * 0.5 + aaWidthWebGL + pickingPaddingWebGL;
|
|
2080
|
+
position = centerPos + normal * side * halfWidth;
|
|
2081
|
+
t = mix(tStart, tTailEnd, zoneT);
|
|
2082
|
+
|
|
2083
|
+
} else if (zone < 1.5) {
|
|
2084
|
+
// BODY ZONE: follows path curvature with width = 1.0
|
|
2085
|
+
t = mix(tTailEnd, tHeadStart, zoneT);
|
|
2086
|
+
normal = queryPathNormal(pathId, t, a_source, a_target);
|
|
2087
|
+
float halfWidth = webGLThickness * 0.5 + aaWidthWebGL + pickingPaddingWebGL;
|
|
2088
|
+
position = queryPathPosition(pathId, t, a_source, a_target) + normal * side * halfWidth;
|
|
2089
|
+
|
|
2090
|
+
} else {
|
|
2091
|
+
// HEAD ZONE: rectangular quad with scaled width
|
|
2092
|
+
vec2 tang = queryPathTangent(pathId, tHeadStart, a_source, a_target);
|
|
2093
|
+
normal = vec2(-tang.y, tang.x);
|
|
2094
|
+
vec2 centerPos = mix(queryPathPosition(pathId, tHeadStart, a_source, a_target),
|
|
2095
|
+
queryPathPosition(pathId, tEnd, a_source, a_target), zoneT);
|
|
2096
|
+
float halfWidth = webGLThickness * scaledHeadWidth * 0.5 + aaWidthWebGL + pickingPaddingWebGL;
|
|
2097
|
+
position = centerPos + normal * side * halfWidth;
|
|
2098
|
+
t = mix(tHeadStart, tEnd, zoneT);
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
// Blend toward straight line based on path twist in extremity zones
|
|
2102
|
+
if (straightenFactor > 0.001) {
|
|
2103
|
+
float zoneWidth = zone < 0.5 ? webGLThickness * scaledTailWidth * 0.5 + aaWidthWebGL + pickingPaddingWebGL :
|
|
2104
|
+
zone < 1.5 ? webGLThickness * 0.5 + aaWidthWebGL + pickingPaddingWebGL :
|
|
2105
|
+
webGLThickness * scaledHeadWidth * 0.5 + aaWidthWebGL + pickingPaddingWebGL;
|
|
2106
|
+
vec2 straightPos = mix(a_source, a_target, t) + straightNormal * side * zoneWidth;
|
|
2107
|
+
position = mix(position, straightPos, straightenFactor);
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
gl_Position = vec4((u_matrix * vec3(position, 1.0)).xy, 0.0, 1.0);
|
|
2111
|
+
|
|
2112
|
+
// Pass varyings to fragment shader
|
|
2113
|
+
v_color = a_color;
|
|
2114
|
+
v_color.a *= bias;
|
|
2115
|
+
v_opacity = a_opacity;
|
|
2116
|
+
v_id = a_id;
|
|
2117
|
+
v_thickness = webGLThickness;
|
|
2118
|
+
v_t = t;
|
|
2119
|
+
v_tStart = tStart;
|
|
2120
|
+
v_tEnd = tEnd;
|
|
2121
|
+
v_side = side;
|
|
2122
|
+
v_antialiasingWidth = antialiasingWidth;
|
|
2123
|
+
v_source = a_source;
|
|
2124
|
+
v_target = a_target;
|
|
2125
|
+
v_edgeLength = pathLength;
|
|
2126
|
+
|
|
2127
|
+
// Zone varyings
|
|
2128
|
+
v_zone = zone;
|
|
2129
|
+
v_zoneT = zoneT;
|
|
2130
|
+
v_headLengthRatio = headLengthRatio * extremityScale;
|
|
2131
|
+
v_tailLengthRatio = tailLengthRatio * extremityScale;
|
|
2132
|
+
// Scale extremity width proportionally with length when crushed
|
|
2133
|
+
v_headWidthRatio = headWidthFactor * extremityScale;
|
|
2134
|
+
v_tailWidthRatio = tailWidthFactor * extremityScale;
|
|
2135
|
+
|
|
2136
|
+
// Multi-path varyings
|
|
2137
|
+
v_pathId = pathId;
|
|
2138
|
+
v_headId = headId;
|
|
2139
|
+
v_tailId = tailId;
|
|
2140
|
+
}
|
|
2141
|
+
`}function uo(e,t,n,r){var i=Ia(zi([].concat(Y(e),Y(n)))),a=new Set([`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_zoomRatio`,`u_pixelRatio`,`u_cameraAngle`,`u_minEdgeThickness`,`u_pickingPadding`]),o=new Set,s=[],c=function(e){!a.has(e.name)&&!o.has(e.name)&&(o.add(e.name),s.push(`uniform ${e.type} ${e.name};`))};e.forEach(function(e){return e.uniforms.forEach(c)}),t.forEach(function(e){return e.uniforms.forEach(c)}),n.forEach(function(e){return e.uniforms.forEach(c)});var l=t.map(function(e){return Z(e.baseRatio??.5)}).join(`, `),u=function(e){return t.length>1?`EXTREMITY_BASE_RATIOS[${e}]`:Z(t[0]?.baseRatio??.5)},d=t.some(function(e){return Tn(e.length)?!0:e.length>0}),f=n.some(function(e){return e.needsNodeColors}),p=e.some(function(e){return e.needsNodeSize}),m=n.map(function(e,t){return` // Layer ${t+1}: ${e.name}
|
|
2142
|
+
color = blendOver(color, layer_${e.name}(context));`}).join(`
|
|
2143
|
+
|
|
2144
|
+
`);return`#version 300 es
|
|
2145
|
+
precision highp float;
|
|
2146
|
+
|
|
2147
|
+
// Standard varyings
|
|
2148
|
+
in vec4 v_color;
|
|
2149
|
+
in float v_opacity;
|
|
2150
|
+
in vec4 v_id;
|
|
2151
|
+
in float v_thickness; // Edge body thickness
|
|
2152
|
+
in float v_t;
|
|
2153
|
+
in float v_tStart;
|
|
2154
|
+
in float v_tEnd;
|
|
2155
|
+
in float v_side;
|
|
2156
|
+
in float v_antialiasingWidth; // Anti-aliasing width (normalized: u_correctionRatio / thickness)
|
|
2157
|
+
in vec2 v_source;
|
|
2158
|
+
in vec2 v_target;
|
|
2159
|
+
in float v_edgeLength;
|
|
2160
|
+
${p?`
|
|
2161
|
+
in float v_sourceNodeSize; // Source node size (mirrored in labels/generator.ts as plain float)
|
|
2162
|
+
in float v_targetNodeSize; // Target node size (mirrored in labels/generator.ts as plain float)`:``}
|
|
2163
|
+
${f?`
|
|
2164
|
+
in vec4 v_sourceColor;
|
|
2165
|
+
in vec4 v_targetColor;`:``}
|
|
2166
|
+
// Zone varyings
|
|
2167
|
+
in float v_zone; // 0=tail, 1=body, 2=head
|
|
2168
|
+
in float v_zoneT; // Position within zone [0,1]
|
|
2169
|
+
in float v_headLengthRatio; // Head length as ratio of thickness (scaled for short edges)
|
|
2170
|
+
in float v_tailLengthRatio; // Tail length as ratio of thickness (scaled for short edges)
|
|
2171
|
+
in float v_headWidthRatio; // Head width factor
|
|
2172
|
+
in float v_tailWidthRatio; // Tail width factor
|
|
2173
|
+
|
|
2174
|
+
// Multi-path/extremity varyings
|
|
2175
|
+
flat in int v_pathId;
|
|
2176
|
+
flat in int v_headId;
|
|
2177
|
+
flat in int v_tailId;
|
|
2178
|
+
|
|
2179
|
+
// Path/layer attribute varyings (from vertex shader texture fetch)
|
|
2180
|
+
${i.fragmentVaryingDeclarations}
|
|
2181
|
+
|
|
2182
|
+
// Standard uniforms (needed by some path types)
|
|
2183
|
+
uniform float u_sizeRatio;
|
|
2184
|
+
uniform float u_correctionRatio;
|
|
2185
|
+
uniform float u_cameraAngle;
|
|
2186
|
+
#ifdef PICKING_MODE
|
|
2187
|
+
uniform float u_pickingPadding;
|
|
2188
|
+
#endif
|
|
2189
|
+
|
|
2190
|
+
// Custom uniforms
|
|
2191
|
+
${s.join(`
|
|
2192
|
+
`)}
|
|
2193
|
+
|
|
2194
|
+
// Fragment output (single target - picking handled via separate pass)
|
|
2195
|
+
out vec4 fragColor;
|
|
2196
|
+
|
|
2197
|
+
${t.length>1?`// Base ratio array for extremities (shared pool for head/tail)
|
|
2198
|
+
const float EXTREMITY_BASE_RATIOS[${t.length}] = float[](${l});`:``}
|
|
2199
|
+
|
|
2200
|
+
// EdgeContext struct
|
|
2201
|
+
struct EdgeContext {
|
|
2202
|
+
float t; // Position along path [0, 1]
|
|
2203
|
+
float sdf; // Signed distance from centerline
|
|
2204
|
+
vec2 position; // World position
|
|
2205
|
+
vec2 tangent; // Path tangent
|
|
2206
|
+
vec2 normal; // Path normal
|
|
2207
|
+
float thickness; // Edge thickness
|
|
2208
|
+
float aaWidth; // Anti-aliasing width
|
|
2209
|
+
float edgeLength; // Total path length
|
|
2210
|
+
float tStart; // Clamped start t
|
|
2211
|
+
float tEnd; // Clamped end t
|
|
2212
|
+
float distanceFromSource; // Arc distance from source
|
|
2213
|
+
float distanceToTarget; // Arc distance to target
|
|
2214
|
+
};
|
|
2215
|
+
|
|
2216
|
+
EdgeContext context;
|
|
2217
|
+
|
|
2218
|
+
// Alpha "over" compositing for layer blending
|
|
2219
|
+
vec4 blendOver(vec4 bg, vec4 fg) {
|
|
2220
|
+
float a = fg.a;
|
|
2221
|
+
return vec4(mix(bg.rgb, fg.rgb, a), bg.a + a * (1.0 - bg.a));
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
// All path functions
|
|
2225
|
+
${Za(e)}
|
|
2226
|
+
|
|
2227
|
+
// Path selector functions
|
|
2228
|
+
${to(e)}
|
|
2229
|
+
|
|
2230
|
+
// All extremity functions
|
|
2231
|
+
${Qa(t)}
|
|
2232
|
+
|
|
2233
|
+
// Extremity SDF selector (shared pool for head/tail)
|
|
2234
|
+
${no(t)}
|
|
2235
|
+
|
|
2236
|
+
// Layer functions
|
|
2237
|
+
${n.map(function(e){return e.glsl}).join(`
|
|
2238
|
+
|
|
2239
|
+
`)}
|
|
2240
|
+
|
|
2241
|
+
// Helper: Compute arc length using path selector
|
|
2242
|
+
float computeArcLengthMulti(int pathId, float t0, float t1, vec2 source, vec2 target, int samples) {
|
|
2243
|
+
float arcLen = 0.0;
|
|
2244
|
+
vec2 prev = queryPathPosition(pathId, t0, source, target);
|
|
2245
|
+
for (int i = 1; i <= samples; i++) {
|
|
2246
|
+
float t = t0 + (t1 - t0) * float(i) / float(samples);
|
|
2247
|
+
vec2 curr = queryPathPosition(pathId, t, source, target);
|
|
2248
|
+
arcLen += length(curr - prev);
|
|
2249
|
+
prev = curr;
|
|
2250
|
+
}
|
|
2251
|
+
return arcLen;
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
void main() {
|
|
2255
|
+
// Compute normalized t within visible edge (0 = start, 1 = end)
|
|
2256
|
+
float tNorm = (v_t - v_tStart) / max(v_tEnd - v_tStart, 0.0001);
|
|
2257
|
+
|
|
2258
|
+
// Edge body half-thickness
|
|
2259
|
+
float halfThickness = v_thickness * 0.5;
|
|
2260
|
+
|
|
2261
|
+
// Convert normalized AA width to webGL units (~1 pixel)
|
|
2262
|
+
float aaWidthWebGL = v_antialiasingWidth * v_thickness;
|
|
2263
|
+
|
|
2264
|
+
// Distance from centerline based on v_side interpolation
|
|
2265
|
+
float zoneWidthFactor = v_zone < 0.5 ? v_tailWidthRatio :
|
|
2266
|
+
v_zone < 1.5 ? 1.0 :
|
|
2267
|
+
v_headWidthRatio;
|
|
2268
|
+
// In PICKING_MODE, inflate halfGeometryWidth to match the inflated vertex geometry
|
|
2269
|
+
#ifdef PICKING_MODE
|
|
2270
|
+
float halfGeometryWidth = halfThickness * zoneWidthFactor + aaWidthWebGL + u_pickingPadding * aaWidthWebGL;
|
|
2271
|
+
#else
|
|
2272
|
+
float halfGeometryWidth = halfThickness * zoneWidthFactor + aaWidthWebGL;
|
|
2273
|
+
#endif
|
|
2274
|
+
float distFromCenter = abs(v_side) * halfGeometryWidth;
|
|
2275
|
+
|
|
2276
|
+
// Populate EdgeContext (for layer functions)
|
|
2277
|
+
context.t = tNorm;
|
|
2278
|
+
context.sdf = distFromCenter - halfThickness;
|
|
2279
|
+
context.position = queryPathPosition(v_pathId, v_t, v_source, v_target);
|
|
2280
|
+
context.tangent = queryPathTangent(v_pathId, v_t, v_source, v_target);
|
|
2281
|
+
context.normal = vec2(-context.tangent.y, context.tangent.x);
|
|
2282
|
+
context.thickness = v_thickness;
|
|
2283
|
+
context.aaWidth = aaWidthWebGL;
|
|
2284
|
+
context.edgeLength = v_edgeLength;
|
|
2285
|
+
context.tStart = v_tStart;
|
|
2286
|
+
context.tEnd = v_tEnd;
|
|
2287
|
+
|
|
2288
|
+
// Compute arc distances
|
|
2289
|
+
float visibleLength = v_edgeLength * (v_tEnd - v_tStart);
|
|
2290
|
+
float pathT = v_t;
|
|
2291
|
+
float pathTNorm = tNorm;
|
|
2292
|
+
${e.every(function(e){return e.linearParameterization})?` // All paths have linear parameterization: t maps directly to arc distance
|
|
2293
|
+
context.distanceFromSource = pathTNorm * visibleLength;
|
|
2294
|
+
context.distanceToTarget = (1.0 - pathTNorm) * visibleLength;`:e.every(function(e){return!e.linearParameterization})?` // No paths have linear parameterization: use numerical integration
|
|
2295
|
+
context.distanceFromSource = computeArcLengthMulti(v_pathId, v_tStart, pathT, v_source, v_target, 16);
|
|
2296
|
+
context.distanceToTarget = computeArcLengthMulti(v_pathId, pathT, v_tEnd, v_source, v_target, 16);`:` // Mixed parameterization: use analytical for linear paths, numerical for others
|
|
2297
|
+
if (${e.filter(function(e){return e.linearParameterization}).map(function(t){return`v_pathId == ${e.indexOf(t)}`}).join(` || `)}) {
|
|
2298
|
+
context.distanceFromSource = pathTNorm * visibleLength;
|
|
2299
|
+
context.distanceToTarget = (1.0 - pathTNorm) * visibleLength;
|
|
2300
|
+
} else {
|
|
2301
|
+
context.distanceFromSource = computeArcLengthMulti(v_pathId, v_tStart, pathT, v_source, v_target, 16);
|
|
2302
|
+
context.distanceToTarget = computeArcLengthMulti(v_pathId, pathT, v_tEnd, v_source, v_target, 16);
|
|
2303
|
+
}`}
|
|
2304
|
+
|
|
2305
|
+
// Compute SDF based on zone using extremity selector (shared pool)
|
|
2306
|
+
float bodySDF = distFromCenter - halfThickness;
|
|
2307
|
+
float finalSDF;
|
|
2308
|
+
|
|
2309
|
+
${d?` // Base ratios, from baseRatioLookup
|
|
2310
|
+
float headBaseRatio = ${u(`v_headId`)};
|
|
2311
|
+
float tailBaseRatio = ${u(`v_tailId`)};
|
|
2312
|
+
|
|
2313
|
+
if (v_zone < 0.5) {
|
|
2314
|
+
// TAIL ZONE: v_zoneT goes 0 (tip) to 1 (base)
|
|
2315
|
+
vec2 uv = vec2((1.0 - v_zoneT) * v_tailLengthRatio, v_side * v_tailWidthRatio * 0.5);
|
|
2316
|
+
float tailSDF = queryExtremitySDF(v_tailId, uv, v_tailLengthRatio, v_tailWidthRatio) * v_thickness;
|
|
2317
|
+
|
|
2318
|
+
// Apply union only near base (v_zoneT > 1 - baseRatio)
|
|
2319
|
+
if (v_zoneT > 1.0 - tailBaseRatio) {
|
|
2320
|
+
finalSDF = min(tailSDF, bodySDF);
|
|
2321
|
+
} else {
|
|
2322
|
+
finalSDF = tailSDF;
|
|
2323
|
+
}
|
|
2324
|
+
} else if (v_zone < 1.5) {
|
|
2325
|
+
// BODY ZONE: distance from centerline
|
|
2326
|
+
finalSDF = bodySDF;
|
|
2327
|
+
} else {
|
|
2328
|
+
// HEAD ZONE: v_zoneT goes 0 (base) to 1 (tip)
|
|
2329
|
+
vec2 uv = vec2(v_zoneT * v_headLengthRatio, v_side * v_headWidthRatio * 0.5);
|
|
2330
|
+
float headSDF = queryExtremitySDF(v_headId, uv, v_headLengthRatio, v_headWidthRatio) * v_thickness;
|
|
2331
|
+
|
|
2332
|
+
// Apply union only near base (v_zoneT < baseRatio)
|
|
2333
|
+
if (v_zoneT < headBaseRatio) {
|
|
2334
|
+
finalSDF = min(headSDF, bodySDF);
|
|
2335
|
+
} else {
|
|
2336
|
+
finalSDF = headSDF;
|
|
2337
|
+
}
|
|
2338
|
+
}`:` // No extremity draws tail/head geometry, so every vertex is body zone.
|
|
2339
|
+
finalSDF = bodySDF;`}
|
|
2340
|
+
|
|
2341
|
+
#ifdef PICKING_MODE
|
|
2342
|
+
// Picking pass: output edge ID for pixels within the picking area
|
|
2343
|
+
if (finalSDF > u_pickingPadding * aaWidthWebGL) discard;
|
|
2344
|
+
fragColor = v_id;
|
|
2345
|
+
#else
|
|
2346
|
+
${r?` // Visual pass: anti-aliased edge with layers, edge opacity applied once
|
|
2347
|
+
float alpha = smoothstep(aaWidthWebGL, -aaWidthWebGL, finalSDF) * v_opacity;`:` // Visual pass: hard-edged (no anti-aliasing gradient) edge with layers, edge opacity applied once
|
|
2348
|
+
float alpha = (finalSDF < 0.0 ? 1.0 : 0.0) * v_opacity;`}
|
|
2349
|
+
if (alpha < 0.01) discard;
|
|
2350
|
+
|
|
2351
|
+
// Apply layers sequentially with "over" compositing
|
|
2352
|
+
vec4 color = vec4(0.0);
|
|
2353
|
+
|
|
2354
|
+
${m}
|
|
2355
|
+
|
|
2356
|
+
// Mix with transparent to fade both color AND alpha (pre-multiplied alpha for correct blending)
|
|
2357
|
+
fragColor = mix(vec4(0.0), color, alpha);
|
|
2358
|
+
#endif
|
|
2359
|
+
}
|
|
2360
|
+
`}function fo(e,t,n){var r=Tn(t.length)?!0:t.length>0,i=Tn(n.length)?!0:n.length>0;if(e.generateConstantData){var a=e.generateConstantData();return{data:a.data,attributes:a.attributes,verticesPerEdge:a.verticesPerEdge}}return co(e.segments,r,i)}function po(e){var t=Ka(e),n=t.paths,r=t.extremities,i=t.layers,a=e.antialias??!0,o=new Map,s=new Map,c=new Map,l=H(n),u;try{for(l.s();!(u=l.n()).done;){var d=u.value,f=H(r),p;try{for(f.s();!(p=f.n()).done;){var m=p.value,h=H(r),g;try{for(h.s();!(g=h.n()).done;){var _=g.value,v=`${d.name}:${m.name}:${_.name}`,y=fo(d,m,_);o.set(v,y.verticesPerEdge),s.set(v,y.data);var b=H(y.attributes),x;try{for(b.s();!(x=b.n()).done;){var S=x.value;c.has(S.name)||c.set(S.name,S)}}catch(e){b.e(e)}finally{b.f()}}}catch(e){h.e(e)}finally{h.f()}}}catch(e){f.e(e)}finally{f.f()}}}catch(e){l.e(e)}finally{l.f()}var C=Array.from(c.values()),w={};C.forEach(function(e,t){w[e.name]=t});var T=0,E=``,D=H(o),O;try{for(D.s();!(O=D.n()).done;){var k=V(O.value,2),A=k[0],j=k[1];j>T&&(T=j,E=A)}}catch(e){D.e(e)}finally{D.f()}var M=s.get(E)||[],N=V(E.split(`:`),1)[0],P=n.find(function(e){return e.name===N}),F=[];F=P!=null&&P.generateConstantData?P.generateConstantData().attributes:[{name:`a_zone`},{name:`a_zoneT`},{name:`a_side`}];var I=M.map(function(e){var t=Array(C.length).fill(0);return F.forEach(function(n,r){var i=w[n.name];i!==void 0&&r<e.length&&(t[i]=e[r])}),t});return{vertexShader:lo(n,r,i,C),fragmentShader:uo(n,r,i,a),uniforms:Xa(n,r,i),attributes:mo(),verticesPerEdge:T,constantData:I,constantAttributes:C,vertexCountsPerCombination:o,constantDataPerCombination:s}}function mo(e,t,n){return[{name:`a_edgeIndex`,size:1,type:Ja},{name:`a_color`,size:4,type:Ya,normalized:!0},{name:`a_id`,size:4,type:Ya,normalized:!0},{name:`a_opacity`,size:1,type:Ja}]}var ho=`#version 300 es
|
|
2361
|
+
precision highp float;
|
|
2362
|
+
|
|
2363
|
+
in vec4 v_clamp;
|
|
2364
|
+
|
|
2365
|
+
// RGBA32F target: stores (tStart, tEnd, straightenFactor, pathLength).
|
|
2366
|
+
out vec4 fragColor;
|
|
2367
|
+
|
|
2368
|
+
void main() {
|
|
2369
|
+
fragColor = v_clamp;
|
|
2370
|
+
}
|
|
2371
|
+
`,go=function(){function e(t,n){G(this,e),U(this,`uniformLocations`,{});var r=n.paths,i=n.extremities,a=n.layers,o=n.nodeShapes,s=n.nodeLayers;this.gl=t,this.hasAttributeData=zi([].concat(Y(r),Y(a))).floatsPerItem>0,this.hasNodeAttributeData=Object.keys(ta(o,s).offsets).length>0,this.vertexShader=$r(t,io(r,i,a,o,s)),this.fragmentShader=ei(t,ho),this.program=ti(t,[this.vertexShader,this.fragmentShader]);var c=new Set;this.customUniforms=[];for(var l=0,u=[].concat(Y(r),Y(i));l<u.length;l++){var d=u[l],f=H(d.uniforms),p;try{for(f.s();!(p=f.n()).done;){var m=p.value;c.has(m.name)||(c.add(m.name),this.customUniforms.push(m))}}catch(e){f.e(e)}finally{f.f()}}var h=H([`u_sizeRatio`,`u_correctionRatio`,`u_cameraAngle`,`u_minEdgeThickness`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_edgeDataTexture`,`u_edgeDataTextureWidth`,`u_edgeAttributeTexture`,`u_edgeAttributeTextureWidth`,`u_edgeAttributeTexelsPerEdge`,`u_layerAttributeTexture`,`u_layerAttributeTextureWidth`,`u_layerAttributeTexelsPerNode`,`u_frameTextureWidth`,`u_frameTextureHeight`].concat(Y(this.customUniforms.map(function(e){return e.name})))),g;try{for(h.s();!(g=h.n()).done;){var _=g.value;this.uniformLocations[_]=t.getUniformLocation(this.program,_)}}catch(e){h.e(e)}finally{h.f()}this.vao=t.createVertexArray()}return K(e,[{key:`run`,value:function(e,t,n,r,i){if(n!==0){var a=this.gl,o=this.uniformLocations;a.useProgram(this.program),a.bindVertexArray(this.vao),o.u_sizeRatio&&a.uniform1f(o.u_sizeRatio,e.sizeRatio),o.u_correctionRatio&&a.uniform1f(o.u_correctionRatio,e.correctionRatio),o.u_cameraAngle&&a.uniform1f(o.u_cameraAngle,e.cameraAngle),o.u_minEdgeThickness&&a.uniform1f(o.u_minEdgeThickness,e.minEdgeThickness),o.u_nodeDataTexture&&a.uniform1i(o.u_nodeDataTexture,e.nodeDataTextureUnit),o.u_nodeDataTextureWidth&&a.uniform1i(o.u_nodeDataTextureWidth,e.nodeDataTextureWidth),o.u_edgeDataTexture&&a.uniform1i(o.u_edgeDataTexture,e.edgeDataTextureUnit),o.u_edgeDataTextureWidth&&a.uniform1i(o.u_edgeDataTextureWidth,e.edgeDataTextureWidth),o.u_frameTextureWidth&&a.uniform1f(o.u_frameTextureWidth,t.getTextureWidth()),o.u_frameTextureHeight&&a.uniform1f(o.u_frameTextureHeight,t.getTextureHeight()),this.hasAttributeData&&r&&(r.bind(Fa),o.u_edgeAttributeTexture&&a.uniform1i(o.u_edgeAttributeTexture,Fa),o.u_edgeAttributeTextureWidth&&a.uniform1i(o.u_edgeAttributeTextureWidth,r.getTextureWidth()),o.u_edgeAttributeTexelsPerEdge&&a.uniform1i(o.u_edgeAttributeTexelsPerEdge,r.getTexelsPerItem())),this.hasNodeAttributeData&&i&&(i.bind($i),o.u_layerAttributeTexture&&a.uniform1i(o.u_layerAttributeTexture,$i),o.u_layerAttributeTextureWidth&&a.uniform1i(o.u_layerAttributeTextureWidth,i.getTextureWidth()),o.u_layerAttributeTexelsPerNode&&a.uniform1i(o.u_layerAttributeTexelsPerNode,i.getTexelsPerItem()));var s=H(this.customUniforms),c;try{for(s.s();!(c=s.n()).done;){var l=c.value;Gi(a,this.uniformLocations[l.name],l)}}catch(e){s.e(e)}finally{s.f()}t.bindAsRenderTarget(),a.disable(a.BLEND),a.disable(a.DEPTH_TEST),a.drawArrays(a.POINTS,0,n),a.bindFramebuffer(a.FRAMEBUFFER,null),a.bindVertexArray(null)}}},{key:`kill`,value:function(){var e=this.gl;e.deleteProgram(this.program),e.deleteShader(this.vertexShader),e.deleteShader(this.fragmentShader),e.deleteVertexArray(this.vao)}}])}();function _o(e,t,n,r,i,a){return e.length===1?`${r} ${t}(int pathId, ${i}) {
|
|
2372
|
+
return path_${e[0].name}_${n}(${a});
|
|
2373
|
+
}`:`${r} ${t}(int pathId, ${i}) {
|
|
2374
|
+
switch (pathId) {
|
|
2375
|
+
${e.map(function(e,t){return` case ${t}: return path_${e.name}_${n}(${a});`}).join(`
|
|
2376
|
+
`)}
|
|
2377
|
+
default: return path_${e[0].name}_${n}(${a});
|
|
2378
|
+
}
|
|
2379
|
+
}`}var vo=`
|
|
2380
|
+
vec3 computeEdgeLabelBodyBounds(
|
|
2381
|
+
float tStart, float tEnd, float pathLength,
|
|
2382
|
+
float webGLThickness, float headLengthRatio, float tailLengthRatio
|
|
2383
|
+
) {
|
|
2384
|
+
float visibleLength = pathLength * (tEnd - tStart);
|
|
2385
|
+
|
|
2386
|
+
float headLength = headLengthRatio * webGLThickness;
|
|
2387
|
+
float tailLength = tailLengthRatio * webGLThickness;
|
|
2388
|
+
float totalNeededLength = headLength + tailLength;
|
|
2389
|
+
if (totalNeededLength > visibleLength && totalNeededLength > 0.0001) {
|
|
2390
|
+
float extremityScale = visibleLength / totalNeededLength;
|
|
2391
|
+
headLength *= extremityScale;
|
|
2392
|
+
tailLength *= extremityScale;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
float bodyStartDist = tStart * pathLength + tailLength;
|
|
2396
|
+
float bodyEndDist = tEnd * pathLength - headLength;
|
|
2397
|
+
return vec3(bodyStartDist, bodyEndDist, max(bodyEndDist - bodyStartDist, 0.0));
|
|
2398
|
+
}
|
|
2399
|
+
`;function yo(e,t){var n=Z(e),r=Z(t);return`
|
|
2400
|
+
float computeEdgeLabelAlpha(float bodyLength, float textWidthWebGL) {
|
|
2401
|
+
float ratio = textWidthWebGL > 0.0001 ? min(bodyLength / textWidthWebGL, 1.0) : 1.0;
|
|
2402
|
+
if (ratio < ${n}) return 0.0;
|
|
2403
|
+
if (ratio < ${r}) return (ratio - ${n}) / (${r} - ${n});
|
|
2404
|
+
return 1.0;
|
|
2405
|
+
}
|
|
2406
|
+
`}var bo=`
|
|
2407
|
+
float computeEdgeLabelPerpOffset(
|
|
2408
|
+
float positionMode,
|
|
2409
|
+
float halfThickness, float marginWebGL, float halfTextHeight,
|
|
2410
|
+
vec2 source, vec2 target, mat3 matrix
|
|
2411
|
+
) {
|
|
2412
|
+
float magnitude = halfThickness + marginWebGL + halfTextHeight;
|
|
2413
|
+
if (positionMode == 1.0) return magnitude;
|
|
2414
|
+
if (positionMode == 2.0) return -magnitude;
|
|
2415
|
+
if (positionMode == 3.0) {
|
|
2416
|
+
vec3 sc = matrix * vec3(source, 1.0);
|
|
2417
|
+
vec3 tc = matrix * vec3(target, 1.0);
|
|
2418
|
+
return sc.x < tc.x ? magnitude : -magnitude;
|
|
2419
|
+
}
|
|
2420
|
+
return 0.0;
|
|
2421
|
+
}
|
|
2422
|
+
`;function xo(e){var t=e.paths,n=e.minVisibilityThreshold,r=e.fullVisibilityThreshold,i=t.some(function(e){return e.hasSharpCorners}),a=t.map(function(e){return`// --- Path: ${e.name} ---
|
|
2423
|
+
${e.glsl}
|
|
2424
|
+
|
|
2425
|
+
// Tangent/normal functions: analytical if provided, otherwise numerical
|
|
2426
|
+
${e.analyticalTangentGlsl||za(e.name)}
|
|
2427
|
+
|
|
2428
|
+
// Auto-generated fallbacks for any missing path functions
|
|
2429
|
+
${Ga(e.name,e.glsl)}
|
|
2430
|
+
|
|
2431
|
+
// Corner skip helpers (for paths with sharp corners like step/taxi)
|
|
2432
|
+
${e.cornerSkipGlsl||``}
|
|
2433
|
+
`}).join(`
|
|
2434
|
+
`),o=i?`// Corner function selectors (only some paths have sharp corners)
|
|
2435
|
+
vec2 queryGetCornerTs(int pathId, vec2 source, vec2 target) {
|
|
2436
|
+
switch (pathId) {
|
|
2437
|
+
${t.map(function(e,t){return e.hasSharpCorners?` case ${t}: return path_${e.name}_getCornerTs(source, target);`:` case ${t}: return vec2(-1.0, -1.0); // No corners for ${e.name}`}).join(`
|
|
2438
|
+
`)}
|
|
2439
|
+
default: return vec2(-1.0, -1.0);
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
|
|
2443
|
+
vec2 queryGetCornerConcavity(int pathId, vec2 source, vec2 target, float perpOffset) {
|
|
2444
|
+
switch (pathId) {
|
|
2445
|
+
${t.map(function(e,t){return e.hasSharpCorners?` case ${t}: return path_${e.name}_getCornerConcavity(source, target, perpOffset);`:` case ${t}: return vec2(0.0, 0.0); // No corners for ${e.name}`}).join(`
|
|
2446
|
+
`)}
|
|
2447
|
+
default: return vec2(0.0, 0.0);
|
|
2448
|
+
}
|
|
2449
|
+
}`:``;return`
|
|
2450
|
+
// ============================================================================
|
|
2451
|
+
// Node data fetch (geometry texel) and per-edge clamp fetch (edge-frame texture)
|
|
2452
|
+
// ============================================================================
|
|
2453
|
+
|
|
2454
|
+
${Ei}
|
|
2455
|
+
${ki}
|
|
2456
|
+
|
|
2457
|
+
// ============================================================================
|
|
2458
|
+
// Path Functions (one block per path)
|
|
2459
|
+
// ============================================================================
|
|
2460
|
+
|
|
2461
|
+
${a}
|
|
2462
|
+
|
|
2463
|
+
// ============================================================================
|
|
2464
|
+
// Path Query Selectors (dispatch by pathId)
|
|
2465
|
+
// ============================================================================
|
|
2466
|
+
|
|
2467
|
+
${_o(t,`queryPathPosition`,`position`,`vec2`,`float t, vec2 source, vec2 target`,`t, source, target`)}
|
|
2468
|
+
|
|
2469
|
+
${_o(t,`queryPathTangent`,`tangent`,`vec2`,`float t, vec2 source, vec2 target`,`t, source, target`)}
|
|
2470
|
+
|
|
2471
|
+
${_o(t,`queryPathNormal`,`normal`,`vec2`,`float t, vec2 source, vec2 target`,`t, source, target`)}
|
|
2472
|
+
|
|
2473
|
+
${_o(t,`queryPathLength`,`length`,`float`,`vec2 source, vec2 target`,`source, target`)}
|
|
2474
|
+
|
|
2475
|
+
${_o(t,`queryPathTAtDistance`,`t_at_distance`,`float`,`float dist, vec2 source, vec2 target`,`dist, source, target`)}
|
|
2476
|
+
|
|
2477
|
+
${o}
|
|
2478
|
+
|
|
2479
|
+
// ============================================================================
|
|
2480
|
+
// Shared helpers (body bounds, alpha ramp, perpendicular offset)
|
|
2481
|
+
// ============================================================================
|
|
2482
|
+
|
|
2483
|
+
${vo}
|
|
2484
|
+
${yo(n,r)}
|
|
2485
|
+
${bo}
|
|
2486
|
+
`}var So=_a.fontSize,Co=new Map,wo=24,To=(wo+1)*2;function Eo(e){var t=e.paths,n=e.fontSizeMode,r=e.headLengthRatio,i=e.tailLengthRatio,a=e.minVisibilityThreshold,o=e.fullVisibilityThreshold,s=n===`scaled`,c=kn(),l=Ia(zi([].concat(Y(t),[c])));return`#version 300 es
|
|
2487
|
+
|
|
2488
|
+
// Per-instance attributes
|
|
2489
|
+
in float a_edgeIndex;
|
|
2490
|
+
in float a_edgeAttrIndex;
|
|
2491
|
+
in float a_baseFontSize;
|
|
2492
|
+
in float a_totalTextWidth;
|
|
2493
|
+
in float a_positionMode;
|
|
2494
|
+
in float a_margin;
|
|
2495
|
+
in float a_padding;
|
|
2496
|
+
in vec4 a_color;
|
|
2497
|
+
in vec4 a_id;
|
|
2498
|
+
|
|
2499
|
+
// Per-vertex (constant) attribute: strip vertex index
|
|
2500
|
+
in float a_vertexIndex;
|
|
2501
|
+
|
|
2502
|
+
uniform mat3 u_matrix;
|
|
2503
|
+
uniform float u_sizeRatio;
|
|
2504
|
+
uniform float u_correctionRatio;
|
|
2505
|
+
uniform float u_pixelRatio;
|
|
2506
|
+
uniform float u_cameraAngle;
|
|
2507
|
+
uniform vec2 u_resolution;
|
|
2508
|
+
uniform sampler2D u_nodeDataTexture;
|
|
2509
|
+
uniform int u_nodeDataTextureWidth;
|
|
2510
|
+
uniform sampler2D u_edgeDataTexture;
|
|
2511
|
+
uniform int u_edgeDataTextureWidth;
|
|
2512
|
+
uniform sampler2D u_edgeFrameTexture; // Per-edge clamp (tStart, tEnd, straightenFactor, pathLength)
|
|
2513
|
+
uniform int u_edgeFrameTextureWidth;
|
|
2514
|
+
${s?`uniform float u_zoomSizeRatio;`:``}
|
|
2515
|
+
|
|
2516
|
+
${l.uniformDeclarations}
|
|
2517
|
+
|
|
2518
|
+
out vec4 v_color;
|
|
2519
|
+
out vec4 v_id;
|
|
2520
|
+
out float v_alphaModifier;
|
|
2521
|
+
|
|
2522
|
+
const float ATLAS_FONT_SIZE = ${Z(So)};
|
|
2523
|
+
const float HEAD_RATIO = ${Z(r)};
|
|
2524
|
+
const float TAIL_RATIO = ${Z(i)};
|
|
2525
|
+
const int RIBBON_SEGMENTS = ${wo};
|
|
2526
|
+
|
|
2527
|
+
// Path attribute varyings (declared as plain locals since this shader has no FS inputs for them)
|
|
2528
|
+
${l.vertexVaryingDeclarations.replace(/out /g,``)}
|
|
2529
|
+
|
|
2530
|
+
// Node size variables used by some path functions (self-loops, etc.)
|
|
2531
|
+
float v_sourceNodeSize;
|
|
2532
|
+
float v_targetNodeSize;
|
|
2533
|
+
|
|
2534
|
+
// Shared preamble: shape SDFs, path functions + selectors, clamp, helpers.
|
|
2535
|
+
${xo({paths:t,minVisibilityThreshold:a,fullVisibilityThreshold:o})}
|
|
2536
|
+
|
|
2537
|
+
void main() {
|
|
2538
|
+
int vIdx = int(a_vertexIndex);
|
|
2539
|
+
int pairIdx = vIdx / 2;
|
|
2540
|
+
int side = vIdx - pairIdx * 2; // 0 = left/bottom, 1 = right/top
|
|
2541
|
+
|
|
2542
|
+
// --- Fetch edge data (2 texels per edge) ---
|
|
2543
|
+
int edgeIdx = int(a_edgeIndex);
|
|
2544
|
+
int texel0Idx = edgeIdx * 2;
|
|
2545
|
+
int texel1Idx = edgeIdx * 2 + 1;
|
|
2546
|
+
ivec2 e0 = ivec2(texel0Idx % u_edgeDataTextureWidth, texel0Idx / u_edgeDataTextureWidth);
|
|
2547
|
+
ivec2 e1 = ivec2(texel1Idx % u_edgeDataTextureWidth, texel1Idx / u_edgeDataTextureWidth);
|
|
2548
|
+
vec4 edgeData0 = texelFetch(u_edgeDataTexture, e0, 0);
|
|
2549
|
+
vec4 edgeData1 = texelFetch(u_edgeDataTexture, e1, 0);
|
|
2550
|
+
|
|
2551
|
+
int srcIdx = int(edgeData0.x);
|
|
2552
|
+
int tgtIdx = int(edgeData0.y);
|
|
2553
|
+
float thickness = edgeData0.z;
|
|
2554
|
+
int pathId = int(edgeData1.z);
|
|
2555
|
+
|
|
2556
|
+
// --- Fetch path attributes (curvature, etc.) ---
|
|
2557
|
+
{
|
|
2558
|
+
int edgeIdx = int(a_edgeAttrIndex);
|
|
2559
|
+
${l.fetchCode}
|
|
2560
|
+
${l.varyingAssignments}
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
// --- Fetch node data: geometry (texel 0) + rotation flags (texel 1) ---
|
|
2564
|
+
vec4 srcN = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, srcIdx);
|
|
2565
|
+
vec4 tgtN = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, tgtIdx);
|
|
2566
|
+
|
|
2567
|
+
vec2 source = srcN.xy;
|
|
2568
|
+
vec2 target = tgtN.xy;
|
|
2569
|
+
float sourceSize = srcN.z;
|
|
2570
|
+
float targetSize = tgtN.z;
|
|
2571
|
+
v_sourceNodeSize = sourceSize;
|
|
2572
|
+
v_targetNodeSize = targetSize;
|
|
2573
|
+
|
|
2574
|
+
// --- Pixel-to-graph conversion (fixed font mode) ---
|
|
2575
|
+
float matrixScaleX = length(vec2(u_matrix[0][0], u_matrix[1][0]));
|
|
2576
|
+
float pixelToGraph = 2.0 / (matrixScaleX * u_resolution.x);
|
|
2577
|
+
|
|
2578
|
+
float webGLThickness = thickness * u_correctionRatio / u_sizeRatio;
|
|
2579
|
+
|
|
2580
|
+
// --- Body bounds (shared with edge label shader) ---
|
|
2581
|
+
vec4 edgeClamp = readFrameTexel(u_edgeFrameTexture, u_edgeFrameTextureWidth, edgeIdx);
|
|
2582
|
+
vec3 bodyBounds = computeEdgeLabelBodyBounds(
|
|
2583
|
+
edgeClamp.x, edgeClamp.y, edgeClamp.w,
|
|
2584
|
+
webGLThickness, HEAD_RATIO, TAIL_RATIO
|
|
2585
|
+
);
|
|
2586
|
+
float bodyStartDist = bodyBounds.x;
|
|
2587
|
+
float bodyEndDist = bodyBounds.y;
|
|
2588
|
+
float bodyLength = bodyBounds.z;
|
|
2589
|
+
|
|
2590
|
+
// --- Text dimensions ---
|
|
2591
|
+
float baseFontSize = a_baseFontSize;
|
|
2592
|
+
${s?`float fontScale = baseFontSize / ATLAS_FONT_SIZE * u_zoomSizeRatio;
|
|
2593
|
+
float textWidthWebGL = a_totalTextWidth * fontScale * u_correctionRatio / u_sizeRatio;
|
|
2594
|
+
float halfTextHeight = baseFontSize * 0.35 * u_zoomSizeRatio * u_correctionRatio / u_sizeRatio;
|
|
2595
|
+
float marginWebGL = a_margin * u_zoomSizeRatio * u_correctionRatio / u_sizeRatio;`:`float fontScale = baseFontSize / ATLAS_FONT_SIZE;
|
|
2596
|
+
float textWidthWebGL = a_totalTextWidth * fontScale * pixelToGraph;
|
|
2597
|
+
float halfTextHeight = baseFontSize * 0.35 * pixelToGraph;
|
|
2598
|
+
float marginWebGL = a_margin * pixelToGraph;`}
|
|
2599
|
+
float paddingWebGL = a_padding * pixelToGraph;
|
|
2600
|
+
|
|
2601
|
+
// --- Alpha modifier (shared with edge label shader) ---
|
|
2602
|
+
float alphaModifier = computeEdgeLabelAlpha(bodyLength, textWidthWebGL);
|
|
2603
|
+
if (alphaModifier <= 0.0 || textWidthWebGL <= 0.0) {
|
|
2604
|
+
gl_Position = vec4(2.0, 0.0, 0.0, 1.0);
|
|
2605
|
+
v_color = vec4(0.0);
|
|
2606
|
+
v_id = vec4(0.0);
|
|
2607
|
+
v_alphaModifier = 0.0;
|
|
2608
|
+
return;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
// --- Perpendicular offset (shared with edge label shader) ---
|
|
2612
|
+
float halfThickness = webGLThickness * 0.5;
|
|
2613
|
+
float perpOffset = computeEdgeLabelPerpOffset(
|
|
2614
|
+
a_positionMode, halfThickness, marginWebGL, halfTextHeight, source, target, u_matrix
|
|
2615
|
+
);
|
|
2616
|
+
|
|
2617
|
+
// --- Ribbon span (clipped to body) ---
|
|
2618
|
+
float bodyCenterDist = (bodyStartDist + bodyEndDist) * 0.5;
|
|
2619
|
+
float halfTextWebGL = textWidthWebGL * 0.5;
|
|
2620
|
+
float labelStartDist = max(bodyCenterDist - halfTextWebGL, bodyStartDist);
|
|
2621
|
+
float labelEndDist = min(bodyCenterDist + halfTextWebGL, bodyEndDist);
|
|
2622
|
+
|
|
2623
|
+
// Sample centerline at this pair, then apply perpendicular offset.
|
|
2624
|
+
// The ribbon follows the centerline path (simple & robust); for curved edges
|
|
2625
|
+
// this closely matches the offset path the characters sit on.
|
|
2626
|
+
float u = float(pairIdx) / float(RIBBON_SEGMENTS);
|
|
2627
|
+
float arcDist = mix(labelStartDist, labelEndDist, u);
|
|
2628
|
+
float t = queryPathTAtDistance(pathId, arcDist, source, target);
|
|
2629
|
+
vec2 pos = queryPathPosition(pathId, t, source, target);
|
|
2630
|
+
vec2 tan = queryPathTangent(pathId, t, source, target);
|
|
2631
|
+
vec2 perp = vec2(-tan.y, tan.x);
|
|
2632
|
+
|
|
2633
|
+
vec2 centerPos = pos + perp * perpOffset;
|
|
2634
|
+
|
|
2635
|
+
float halfRibbon = halfTextHeight + paddingWebGL;
|
|
2636
|
+
float sideSign = side == 0 ? -1.0 : 1.0;
|
|
2637
|
+
vec2 ribbonPos = centerPos + perp * (sideSign * halfRibbon);
|
|
2638
|
+
|
|
2639
|
+
vec3 clipPos = u_matrix * vec3(ribbonPos, 1.0);
|
|
2640
|
+
gl_Position = vec4(clipPos.xy, 0.0, 1.0);
|
|
2641
|
+
|
|
2642
|
+
v_color = a_color;
|
|
2643
|
+
v_id = a_id;
|
|
2644
|
+
v_alphaModifier = alphaModifier;
|
|
2645
|
+
}
|
|
2646
|
+
`}var Do=`#version 300 es
|
|
2647
|
+
precision highp float;
|
|
2648
|
+
|
|
2649
|
+
in vec4 v_color;
|
|
2650
|
+
in vec4 v_id;
|
|
2651
|
+
in float v_alphaModifier;
|
|
2652
|
+
|
|
2653
|
+
out vec4 fragColor;
|
|
2654
|
+
|
|
2655
|
+
void main() {
|
|
2656
|
+
#ifdef PICKING_MODE
|
|
2657
|
+
if (v_alphaModifier <= 0.0) discard;
|
|
2658
|
+
fragColor = v_id;
|
|
2659
|
+
#else
|
|
2660
|
+
float alpha = v_color.a * v_alphaModifier;
|
|
2661
|
+
if (alpha <= 0.0) discard;
|
|
2662
|
+
fragColor = vec4(v_color.rgb * alpha, alpha);
|
|
2663
|
+
#endif
|
|
2664
|
+
}
|
|
2665
|
+
`;function Oo(e,t,n,r){var i=r.shaderConfig,a=i.paths,o=i.fontSizeMode;if(a.length===0)throw Error(`createEdgeLabelBackgroundProgram: shaderConfig must declare at least one path`);var s=kn(),c=zi([].concat(Y(a),[s])),l=Vi([].concat(Y(a),[s]),c),u=Eo(i);return new(function(e){function t(e,n,r){var i;return G(this,t),i=q(this,t,[e,n,r]),U(i,`totalCount`,0),U(i,`bufferCapacity`,0),U(i,`edgeAttributeTexture`,null),i.edgeAttributeTexture=new Bi(e,c),i.packedAttributeData=new Float32Array(c.floatsPerItem),i}return J(t,e),K(t,[{key:`getDefinition`,value:function(){for(var e=WebGL2RenderingContext,t=e.FLOAT,n=e.UNSIGNED_BYTE,r=e.TRIANGLE_STRIP,i=[],a=0;a<To;a++)i.push([a]);var s=[`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_pixelRatio`,`u_cameraAngle`,`u_resolution`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_edgeDataTexture`,`u_edgeDataTextureWidth`,`u_edgeFrameTexture`,`u_edgeFrameTextureWidth`];return o===`scaled`&&s.push(`u_zoomSizeRatio`),c.floatsPerItem>0&&s.push(`u_edgeAttributeTexture`,`u_edgeAttributeTextureWidth`,`u_edgeAttributeTexelsPerEdge`),{VERTICES:To,VERTEX_SHADER_SOURCE:u,FRAGMENT_SHADER_SOURCE:Do,METHOD:r,UNIFORMS:s,ATTRIBUTES:[{name:`a_edgeIndex`,size:1,type:t},{name:`a_edgeAttrIndex`,size:1,type:t},{name:`a_baseFontSize`,size:1,type:t},{name:`a_totalTextWidth`,size:1,type:t},{name:`a_positionMode`,size:1,type:t},{name:`a_margin`,size:1,type:t},{name:`a_padding`,size:1,type:t},{name:`a_color`,size:4,type:n,normalized:!0},{name:`a_id`,size:4,type:n,normalized:!0}],CONSTANT_ATTRIBUTES:[{name:`a_vertexIndex`,size:1,type:t}],CONSTANT_DATA:i}}},{key:`processEdgeLabelBackground`,value:function(e,t,n){var r=0;if(this.edgeAttributeTexture&&c.floatsPerItem>0){r=this.edgeAttributeTexture.allocate(t);var i=this.packedAttributeData;Hi(l,n.edgeAttributes,i,``,Co,0),this.edgeAttributeTexture.updateAllAttributes(t,i)}var a=this.floats,o=this.ints,s=e*this.STRIDE;a[s++]=n.edgeIndex,a[s++]=r,a[s++]=n.baseFontSize,a[s++]=n.totalTextWidth,a[s++]=n.positionMode,a[s++]=n.margin,a[s++]=n.padding,a[s++]=n.color,o[s++]=n.id}},{key:`setUniforms`,value:function(e,t){var n=t.gl,r=t.uniformLocations;if(n.uniformMatrix3fv(r.u_matrix,!1,e.matrix),n.uniform1f(r.u_sizeRatio,e.sizeRatio),n.uniform1f(r.u_correctionRatio,e.correctionRatio),n.uniform1f(r.u_pixelRatio,e.pixelRatio),n.uniform1f(r.u_cameraAngle,e.cameraAngle),n.uniform2f(r.u_resolution,e.width,e.height),r.u_nodeDataTexture!==void 0&&n.uniform1i(r.u_nodeDataTexture,e.nodeDataTextureUnit),r.u_nodeDataTextureWidth!==void 0&&n.uniform1i(r.u_nodeDataTextureWidth,e.nodeDataTextureWidth),r.u_edgeDataTexture!==void 0&&n.uniform1i(r.u_edgeDataTexture,e.edgeDataTextureUnit),r.u_edgeDataTextureWidth!==void 0&&n.uniform1i(r.u_edgeDataTextureWidth,e.edgeDataTextureWidth),r.u_edgeFrameTexture!==void 0&&n.uniform1i(r.u_edgeFrameTexture,e.edgeFrameTextureUnit),r.u_edgeFrameTextureWidth!==void 0&&n.uniform1i(r.u_edgeFrameTextureWidth,e.edgeFrameTextureWidth),o===`scaled`&&r.u_zoomSizeRatio!==void 0){var i=this.renderer.getSetting(`zoomToSizeRatioFunction`);n.uniform1f(r.u_zoomSizeRatio,1/i(e.zoomRatio))}this.edgeAttributeTexture&&c.floatsPerItem>0&&r.u_edgeAttributeTexture!==void 0&&(this.edgeAttributeTexture.bind(Fa),n.uniform1i(r.u_edgeAttributeTexture,Fa),n.uniform1i(r.u_edgeAttributeTextureWidth,this.edgeAttributeTexture.getTextureWidth()),n.uniform1i(r.u_edgeAttributeTexelsPerEdge,this.edgeAttributeTexture.getTexelsPerItem()))}},{key:`renderProgram`,value:function(e,n){this.edgeAttributeTexture&&c.floatsPerItem>0&&this.edgeAttributeTexture.upload(),Q(t,`renderProgram`,this,3)([e,n])}},{key:`kill`,value:function(){this.edgeAttributeTexture&&=(this.edgeAttributeTexture.kill(),null),Q(t,`kill`,this,3)([])}},{key:`drawWebGL`,value:function(e,t){var n=t.gl;this.totalCount!==0&&n.drawArraysInstanced(n.TRIANGLE_STRIP,0,this.VERTICES,this.totalCount)}},{key:`reallocate`,value:function(e){this.totalCount=e,e>this.bufferCapacity&&(this.bufferCapacity=Math.max(e,Math.ceil(this.bufferCapacity*1.5)||10),Q(t,`reallocate`,this,3)([this.bufferCapacity]))}}])}(Ji))(e,t,n)}function ko(e){return{paths:e.paths,headLengthRatio:e.headLengthRatio??0,tailLengthRatio:e.tailLengthRatio??0,fontSizeMode:e.fontSizeMode??`fixed`,minVisibilityThreshold:e.minVisibilityThreshold??.7,fullVisibilityThreshold:e.fullVisibilityThreshold??.8}}var Ao=_a.fontSize,jo=17/64;function Mo(e){var t=e.paths,n=e.hasBorder,r=n!==void 0&&n,i=e.fontSizeMode,a=i===void 0?`fixed`:i,o=e.minVisibilityThreshold,s=o===void 0?.5:o,c=e.fullVisibilityThreshold,l=c===void 0?.6:c,u=a===`scaled`,d=t.some(function(e){return e.hasSharpCorners}),f=kn(),p=Ia(zi([].concat(Y(t),[f])));return`#version 300 es
|
|
2666
|
+
|
|
2667
|
+
// ============================================================================
|
|
2668
|
+
// Attributes - Per Character (Instanced)
|
|
2669
|
+
// ============================================================================
|
|
2670
|
+
|
|
2671
|
+
// Edge geometry: indices for texture lookup
|
|
2672
|
+
// Edge data (source/target node indices, thickness, head/tail ratios) is fetched from edge data texture
|
|
2673
|
+
// Edge path attributes (curvature, etc.) are fetched from edge attribute texture
|
|
2674
|
+
in float a_edgeIndex; // Index into edge data texture
|
|
2675
|
+
in float a_edgeAttrIndex; // Index into edge attribute texture (for curvature, etc.)
|
|
2676
|
+
in float a_baseFontSize; // Base font size in pixels (per-label)
|
|
2677
|
+
|
|
2678
|
+
// Character metrics (in glyph units = atlas font size pixels)
|
|
2679
|
+
in vec4 a_charMetrics; // (charTextOffset, charAdvance, totalTextWidth, positionMode)
|
|
2680
|
+
in vec4 a_charDims; // (charSize.x, charSize.y, charOffset.x, charOffset.y)
|
|
2681
|
+
|
|
2682
|
+
// Atlas texture coordinates
|
|
2683
|
+
in vec4 a_texCoords; // (x, y, width, height) in atlas pixels
|
|
2684
|
+
|
|
2685
|
+
// Label parameters
|
|
2686
|
+
in vec2 a_labelParams; // (margin, unused)
|
|
2687
|
+
|
|
2688
|
+
// Appearance
|
|
2689
|
+
in vec4 a_color; // Character color (RGBA, normalized)
|
|
2690
|
+
${r?`in vec4 a_borderColor; // Border color (RGBA, normalized)`:``}
|
|
2691
|
+
|
|
2692
|
+
// ============================================================================
|
|
2693
|
+
// Attributes - Per Vertex (Constant)
|
|
2694
|
+
// ============================================================================
|
|
2695
|
+
|
|
2696
|
+
in vec2 a_quadCorner; // Quad corner: (0,0), (1,0), (0,1), (1,1)
|
|
2697
|
+
|
|
2698
|
+
// ============================================================================
|
|
2699
|
+
// Uniforms
|
|
2700
|
+
// ============================================================================
|
|
2701
|
+
|
|
2702
|
+
uniform mat3 u_matrix;
|
|
2703
|
+
uniform float u_sizeRatio;
|
|
2704
|
+
uniform float u_correctionRatio;
|
|
2705
|
+
uniform float u_pixelRatio;
|
|
2706
|
+
uniform float u_cameraAngle; // Required by node shape SDFs
|
|
2707
|
+
// u_sdfBufferPixels kept for ABI compatibility but unused in shader
|
|
2708
|
+
uniform float u_sdfBufferPixels;
|
|
2709
|
+
uniform vec2 u_resolution;
|
|
2710
|
+
uniform vec2 u_atlasSize;
|
|
2711
|
+
uniform sampler2D u_nodeDataTexture; // Shared texture with node position/size/shape data
|
|
2712
|
+
uniform int u_nodeDataTextureWidth; // Width of 2D node data texture for coordinate calculation
|
|
2713
|
+
uniform sampler2D u_edgeDataTexture; // Shared texture with edge data
|
|
2714
|
+
uniform int u_edgeDataTextureWidth; // Width of 2D edge data texture for coordinate calculation
|
|
2715
|
+
uniform sampler2D u_edgeFrameTexture; // Per-edge clamp (tStart, tEnd, straightenFactor, pathLength)
|
|
2716
|
+
uniform int u_edgeFrameTextureWidth;
|
|
2717
|
+
${u?`uniform float u_zoomSizeRatio; // Zoom-based size ratio from zoomToSizeRatioFunction`:``}
|
|
2718
|
+
|
|
2719
|
+
// Edge path attribute texture uniforms (for curvature and other path attributes)
|
|
2720
|
+
${p.uniformDeclarations}
|
|
2721
|
+
|
|
2722
|
+
// ============================================================================
|
|
2723
|
+
// Varyings
|
|
2724
|
+
// ============================================================================
|
|
2725
|
+
|
|
2726
|
+
out vec2 v_texCoord;
|
|
2727
|
+
out vec4 v_color;
|
|
2728
|
+
${r?`out vec4 v_borderColor;`:``}
|
|
2729
|
+
out float v_edgeFade; // 0 = fully visible, 1 = fully faded (outside body)
|
|
2730
|
+
out float v_alphaModifier; // 0-1 based on label visibility ratio
|
|
2731
|
+
out float v_fontScale; // Ratio of rendered font size to atlas font size
|
|
2732
|
+
${r?`out float v_positionMode; // Position mode for conditional border (0=over needs border)`:``}
|
|
2733
|
+
|
|
2734
|
+
// ============================================================================
|
|
2735
|
+
// Constants
|
|
2736
|
+
// ============================================================================
|
|
2737
|
+
|
|
2738
|
+
const float bias = 255.0 / 254.0;
|
|
2739
|
+
const float FADE_WIDTH_PIXELS = 15.0; // Width of fade gradient in pixels
|
|
2740
|
+
const float ATLAS_FONT_SIZE = ${Z(Ao)}; // Base font size used in SDF atlas
|
|
2741
|
+
const float VERTICAL_CENTER_RATIO = ${Z(jo)}; // Baseline to visual center ratio
|
|
2742
|
+
|
|
2743
|
+
// ============================================================================
|
|
2744
|
+
// Path Attribute Variables (set in main, used by path functions)
|
|
2745
|
+
// ============================================================================
|
|
2746
|
+
// Path attributes are fetched from the edge attribute texture and stored in
|
|
2747
|
+
// variables with v_ prefix (e.g., v_curvature) for path functions to access.
|
|
2748
|
+
${p.vertexVaryingDeclarations.replace(/out /g,``)}
|
|
2749
|
+
|
|
2750
|
+
// Node size variables (set in main, used by some path functions like loops).
|
|
2751
|
+
// These mirror the v_sourceNodeSize / v_targetNodeSize varyings in generator.ts,
|
|
2752
|
+
// but are plain floats here since the label shader is vertex-only.
|
|
2753
|
+
float v_sourceNodeSize;
|
|
2754
|
+
float v_targetNodeSize;
|
|
2755
|
+
|
|
2756
|
+
// Shared preamble: shape SDFs, path functions + selectors, clamp, helpers.
|
|
2757
|
+
${xo({paths:t,minVisibilityThreshold:s,fullVisibilityThreshold:l})}
|
|
2758
|
+
|
|
2759
|
+
// ============================================================================
|
|
2760
|
+
// Main
|
|
2761
|
+
// ============================================================================
|
|
2762
|
+
|
|
2763
|
+
void main() {
|
|
2764
|
+
// -------------------------------------------------------------------------
|
|
2765
|
+
// Fetch edge data from edge texture (2 texels per edge)
|
|
2766
|
+
// -------------------------------------------------------------------------
|
|
2767
|
+
// Texel 0: sourceNodeIndex, targetNodeIndex, thickness, reserved
|
|
2768
|
+
// Texel 1: headLengthRatio, tailLengthRatio, pathId, extremityIds
|
|
2769
|
+
int edgeIdx = int(a_edgeIndex);
|
|
2770
|
+
int texel0Idx = edgeIdx * 2;
|
|
2771
|
+
int texel1Idx = edgeIdx * 2 + 1;
|
|
2772
|
+
ivec2 edgeTexCoord0 = ivec2(texel0Idx % u_edgeDataTextureWidth, texel0Idx / u_edgeDataTextureWidth);
|
|
2773
|
+
ivec2 edgeTexCoord1 = ivec2(texel1Idx % u_edgeDataTextureWidth, texel1Idx / u_edgeDataTextureWidth);
|
|
2774
|
+
vec4 edgeData0 = texelFetch(u_edgeDataTexture, edgeTexCoord0, 0);
|
|
2775
|
+
vec4 edgeData1 = texelFetch(u_edgeDataTexture, edgeTexCoord1, 0);
|
|
2776
|
+
|
|
2777
|
+
// Unpack edge data
|
|
2778
|
+
int srcIdx = int(edgeData0.x);
|
|
2779
|
+
int tgtIdx = int(edgeData0.y);
|
|
2780
|
+
float thickness = edgeData0.z;
|
|
2781
|
+
// edgeData0.w is reserved
|
|
2782
|
+
float headLengthRatio = edgeData1.x;
|
|
2783
|
+
float tailLengthRatio = edgeData1.y;
|
|
2784
|
+
int pathId = int(edgeData1.z); // Path type for multi-path support
|
|
2785
|
+
float baseFontSize = a_baseFontSize;
|
|
2786
|
+
|
|
2787
|
+
// -------------------------------------------------------------------------
|
|
2788
|
+
// Fetch path attributes from edge attribute texture
|
|
2789
|
+
// -------------------------------------------------------------------------
|
|
2790
|
+
// Note: The fetch code uses 'edgeIdx' variable, so we set it to the attribute texture index
|
|
2791
|
+
{
|
|
2792
|
+
int edgeIdx = int(a_edgeAttrIndex); // Use attribute texture index for path attributes
|
|
2793
|
+
${p.fetchCode}
|
|
2794
|
+
${p.varyingAssignments}
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
// -------------------------------------------------------------------------
|
|
2798
|
+
// Fetch node data from node texture (geometry texel + rotation-flags texel)
|
|
2799
|
+
// -------------------------------------------------------------------------
|
|
2800
|
+
vec4 srcNodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, srcIdx);
|
|
2801
|
+
vec4 tgtNodeData = readNodeData(u_nodeDataTexture, u_nodeDataTextureWidth, tgtIdx);
|
|
2802
|
+
|
|
2803
|
+
vec2 source = srcNodeData.xy;
|
|
2804
|
+
vec2 target = tgtNodeData.xy;
|
|
2805
|
+
float sourceSize = srcNodeData.z;
|
|
2806
|
+
float targetSize = tgtNodeData.z;
|
|
2807
|
+
v_sourceNodeSize = sourceSize;
|
|
2808
|
+
v_targetNodeSize = targetSize;
|
|
2809
|
+
float charTextOffset = a_charMetrics.x;
|
|
2810
|
+
float charAdvance = a_charMetrics.y;
|
|
2811
|
+
float totalTextWidth = a_charMetrics.z;
|
|
2812
|
+
float positionMode = a_charMetrics.w;
|
|
2813
|
+
vec2 charSize = a_charDims.xy;
|
|
2814
|
+
vec2 charOffset = a_charDims.zw;
|
|
2815
|
+
float margin = a_labelParams.x;
|
|
2816
|
+
|
|
2817
|
+
// -------------------------------------------------------------------------
|
|
2818
|
+
// Compute pixel-to-graph conversion (for fixed font size mode)
|
|
2819
|
+
// -------------------------------------------------------------------------
|
|
2820
|
+
// This converts screen pixels to graph units such that N pixels on screen
|
|
2821
|
+
// becomes N pixels regardless of zoom level.
|
|
2822
|
+
// matrixScaleX is how much the matrix scales graph units to clip space
|
|
2823
|
+
float matrixScaleX = length(vec2(u_matrix[0][0], u_matrix[1][0]));
|
|
2824
|
+
float pixelToGraph = 2.0 / (matrixScaleX * u_resolution.x);
|
|
2825
|
+
|
|
2826
|
+
// -------------------------------------------------------------------------
|
|
2827
|
+
// Step 1: Convert thickness to WebGL units
|
|
2828
|
+
// -------------------------------------------------------------------------
|
|
2829
|
+
float webGLThickness = thickness * u_correctionRatio / u_sizeRatio;
|
|
2830
|
+
|
|
2831
|
+
// -------------------------------------------------------------------------
|
|
2832
|
+
// Step 2: Compute body bounds (truncated at node boundaries + extremities)
|
|
2833
|
+
// -------------------------------------------------------------------------
|
|
2834
|
+
vec4 edgeClamp = readFrameTexel(u_edgeFrameTexture, u_edgeFrameTextureWidth, edgeIdx);
|
|
2835
|
+
vec3 bodyBounds = computeEdgeLabelBodyBounds(
|
|
2836
|
+
edgeClamp.x, edgeClamp.y, edgeClamp.w,
|
|
2837
|
+
webGLThickness, headLengthRatio, tailLengthRatio
|
|
2838
|
+
);
|
|
2839
|
+
float bodyStartDist = bodyBounds.x;
|
|
2840
|
+
float bodyEndDist = bodyBounds.y;
|
|
2841
|
+
float bodyLength = bodyBounds.z;
|
|
2842
|
+
|
|
2843
|
+
// -------------------------------------------------------------------------
|
|
2844
|
+
// Step 3: Compute font scale and text dimensions
|
|
2845
|
+
// -------------------------------------------------------------------------
|
|
2846
|
+
// Font size modes:
|
|
2847
|
+
// - "fixed": Constant pixel size regardless of zoom, using pixelToGraph conversion
|
|
2848
|
+
// - "scaled": Scales with zoom using zoomToSizeRatioFunction
|
|
2849
|
+
${u?`// Scaled mode: font scales with zoom
|
|
2850
|
+
float fontScale = baseFontSize / ATLAS_FONT_SIZE * u_zoomSizeRatio;
|
|
2851
|
+
// Convert glyph-unit metrics to WebGL units (scales with zoom)
|
|
2852
|
+
float textWidthWebGL = totalTextWidth * fontScale * u_correctionRatio / u_sizeRatio;
|
|
2853
|
+
float charOffsetWebGL = charTextOffset * fontScale * u_correctionRatio / u_sizeRatio;
|
|
2854
|
+
float charAdvanceWebGL = charAdvance * fontScale * u_correctionRatio / u_sizeRatio;`:`// Fixed mode: font stays constant in screen pixels
|
|
2855
|
+
float fontScale = baseFontSize / ATLAS_FONT_SIZE;
|
|
2856
|
+
// Convert glyph-unit metrics to graph units using pixelToGraph (zoom-independent)
|
|
2857
|
+
float textWidthWebGL = totalTextWidth * fontScale * pixelToGraph;
|
|
2858
|
+
float charOffsetWebGL = charTextOffset * fontScale * pixelToGraph;
|
|
2859
|
+
float charAdvanceWebGL = charAdvance * fontScale * pixelToGraph;`}
|
|
2860
|
+
|
|
2861
|
+
// Font scale varying for fragment shader gamma scaling.
|
|
2862
|
+
// Ratio of rendered font size to atlas font size — used to tighten the
|
|
2863
|
+
// anti-aliasing band for large labels so they stay sharp.
|
|
2864
|
+
v_fontScale = fontScale;
|
|
2865
|
+
|
|
2866
|
+
// -------------------------------------------------------------------------
|
|
2867
|
+
// Step 4: Alpha modifier from how much of the label fits in the body
|
|
2868
|
+
// -------------------------------------------------------------------------
|
|
2869
|
+
float alphaModifier = computeEdgeLabelAlpha(bodyLength, textWidthWebGL);
|
|
2870
|
+
|
|
2871
|
+
// -------------------------------------------------------------------------
|
|
2872
|
+
// Step 5: Compute character center offset (truncation check moved to after curvature adjustment)
|
|
2873
|
+
// -------------------------------------------------------------------------
|
|
2874
|
+
// Character center position relative to label center (on centerline, before curvature adjustment)
|
|
2875
|
+
float charCenterOffset = charOffsetWebGL + charAdvanceWebGL * 0.5 - textWidthWebGL * 0.5;
|
|
2876
|
+
|
|
2877
|
+
// -------------------------------------------------------------------------
|
|
2878
|
+
// Step 6: Compute perpendicular offset based on position mode
|
|
2879
|
+
// -------------------------------------------------------------------------
|
|
2880
|
+
// Position modes: 0=over, 1=above, 2=below, 3=auto
|
|
2881
|
+
// Needed early for curvature-adaptive character spacing in Step 7
|
|
2882
|
+
float halfThickness = webGLThickness * 0.5;
|
|
2883
|
+
${u?`// Scaled mode: margin and text height scale with zoom (same factor as font)
|
|
2884
|
+
float marginWebGL = margin * u_zoomSizeRatio * u_correctionRatio / u_sizeRatio;
|
|
2885
|
+
float halfTextHeight = baseFontSize * 0.35 * u_zoomSizeRatio * u_correctionRatio / u_sizeRatio;`:`// Fixed mode: margin and text height stay constant in screen pixels
|
|
2886
|
+
float marginWebGL = margin * pixelToGraph;
|
|
2887
|
+
float halfTextHeight = baseFontSize * 0.35 * pixelToGraph;`}
|
|
2888
|
+
float perpOffset = computeEdgeLabelPerpOffset(
|
|
2889
|
+
positionMode, halfThickness, marginWebGL, halfTextHeight, source, target, u_matrix
|
|
2890
|
+
);
|
|
2891
|
+
|
|
2892
|
+
// -------------------------------------------------------------------------
|
|
2893
|
+
// Step 7: Position character on path using offset path traversal
|
|
2894
|
+
// -------------------------------------------------------------------------
|
|
2895
|
+
// Body center in arc distance
|
|
2896
|
+
float bodyCenterDist = (bodyStartDist + bodyEndDist) * 0.5;
|
|
2897
|
+
|
|
2898
|
+
// For "over" mode (perpOffset = 0), use simple centerline placement
|
|
2899
|
+
// For above/below modes, walk along the offset path to find correct position
|
|
2900
|
+
float charT;
|
|
2901
|
+
|
|
2902
|
+
if (perpOffset == 0.0) {
|
|
2903
|
+
// Simple case: place on centerline
|
|
2904
|
+
float charArcDist = bodyCenterDist + charCenterOffset;
|
|
2905
|
+
charT = queryPathTAtDistance(pathId, charArcDist, source, target);
|
|
2906
|
+
} else {
|
|
2907
|
+
// Offset path traversal: walk along the offset curve to find character position
|
|
2908
|
+
// This ensures even character spacing regardless of curvature
|
|
2909
|
+
|
|
2910
|
+
// Start from body center on offset path
|
|
2911
|
+
float centerT = queryPathTAtDistance(pathId, bodyCenterDist, source, target);
|
|
2912
|
+
|
|
2913
|
+
${d?`// -----------------------------------------------------------------------
|
|
2914
|
+
// Corner skip setup for step/taxi edges with above/below labels
|
|
2915
|
+
// -----------------------------------------------------------------------
|
|
2916
|
+
// At concave corners (inner side of the bend), characters would bunch up
|
|
2917
|
+
// because the offset path has near-zero arc length. We detect corner
|
|
2918
|
+
// crossings during the offset path traversal and add skip distance.
|
|
2919
|
+
|
|
2920
|
+
// Get corner t values and concavity
|
|
2921
|
+
vec2 cornerTs = queryGetCornerTs(pathId, source, target);
|
|
2922
|
+
vec2 concavity = queryGetCornerConcavity(pathId, source, target, perpOffset);
|
|
2923
|
+
|
|
2924
|
+
// Skip distance in graph units, proportional to on-screen font size
|
|
2925
|
+
// For fixed mode: use pixelToGraph so gap stays constant regardless of zoom
|
|
2926
|
+
// For scaled mode: use the same conversion as text width
|
|
2927
|
+
${u?`float skipDistGraph = STEP_INNER_CORNER_SKIP_FACTOR * baseFontSize * u_zoomSizeRatio * u_correctionRatio / u_sizeRatio;`:`float skipDistGraph = STEP_INNER_CORNER_SKIP_FACTOR * baseFontSize * pixelToGraph;`}
|
|
2928
|
+
|
|
2929
|
+
// Corner t values for detecting crossings during traversal
|
|
2930
|
+
float corner1T = cornerTs.x;
|
|
2931
|
+
float corner2T = cornerTs.y;
|
|
2932
|
+
bool corner1IsConcave = concavity.x > 0.5;
|
|
2933
|
+
bool corner2IsConcave = concavity.y > 0.5;`:``}
|
|
2934
|
+
|
|
2935
|
+
// Target distance along offset path from center
|
|
2936
|
+
float targetOffsetDist = abs(charCenterOffset);
|
|
2937
|
+
|
|
2938
|
+
// Handle center character (charCenterOffset ≈ 0) - no search needed
|
|
2939
|
+
if (targetOffsetDist < 0.0001) {
|
|
2940
|
+
charT = centerT;
|
|
2941
|
+
} else {
|
|
2942
|
+
vec2 centerPos = queryPathPosition(pathId, centerT, source, target);
|
|
2943
|
+
vec2 centerNormal = queryPathNormal(pathId, centerT, source, target);
|
|
2944
|
+
vec2 offsetCenter = centerPos + centerNormal * perpOffset;
|
|
2945
|
+
|
|
2946
|
+
float searchDir = charCenterOffset > 0.0 ? 1.0 : -1.0;
|
|
2947
|
+
|
|
2948
|
+
// Search bounds (t values for body start and end)
|
|
2949
|
+
float tBodyStart = queryPathTAtDistance(pathId, bodyStartDist, source, target);
|
|
2950
|
+
float tBodyEnd = queryPathTAtDistance(pathId, bodyEndDist, source, target);
|
|
2951
|
+
|
|
2952
|
+
// Walk along offset path to find character position
|
|
2953
|
+
float accumDist = 0.0;
|
|
2954
|
+
vec2 prevOffsetPos = offsetCenter;
|
|
2955
|
+
float prevT = centerT;
|
|
2956
|
+
float foundT = centerT;
|
|
2957
|
+
|
|
2958
|
+
// Search range depends on direction
|
|
2959
|
+
float tSearchEnd = searchDir > 0.0 ? tBodyEnd : tBodyStart;
|
|
2960
|
+
|
|
2961
|
+
${d?`// Track which concave corners we've crossed to add skip distance
|
|
2962
|
+
bool crossedCorner1 = false;
|
|
2963
|
+
bool crossedCorner2 = false;
|
|
2964
|
+
float effectiveTargetDist = targetOffsetDist;`:``}
|
|
2965
|
+
|
|
2966
|
+
const int STEPS = 32;
|
|
2967
|
+
for (int i = 1; i <= STEPS; i++) {
|
|
2968
|
+
// Step along centerline t, from center toward target
|
|
2969
|
+
float stepT = centerT + searchDir * float(i) * abs(tSearchEnd - centerT) / float(STEPS);
|
|
2970
|
+
|
|
2971
|
+
${d?`// Check for concave corner crossings and add skip distance
|
|
2972
|
+
// Corner 1 crossing check
|
|
2973
|
+
if (corner1IsConcave && !crossedCorner1) {
|
|
2974
|
+
bool crossingCorner1 = (searchDir > 0.0)
|
|
2975
|
+
? (prevT < corner1T && stepT >= corner1T)
|
|
2976
|
+
: (prevT > corner1T && stepT <= corner1T);
|
|
2977
|
+
if (crossingCorner1) {
|
|
2978
|
+
crossedCorner1 = true;
|
|
2979
|
+
effectiveTargetDist += skipDistGraph;
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
|
|
2983
|
+
// Corner 2 crossing check
|
|
2984
|
+
if (corner2IsConcave && !crossedCorner2) {
|
|
2985
|
+
bool crossingCorner2 = (searchDir > 0.0)
|
|
2986
|
+
? (prevT < corner2T && stepT >= corner2T)
|
|
2987
|
+
: (prevT > corner2T && stepT <= corner2T);
|
|
2988
|
+
if (crossingCorner2) {
|
|
2989
|
+
crossedCorner2 = true;
|
|
2990
|
+
effectiveTargetDist += skipDistGraph;
|
|
2991
|
+
}
|
|
2992
|
+
}`:``}
|
|
2993
|
+
|
|
2994
|
+
// Compute offset position at this t
|
|
2995
|
+
vec2 stepPos = queryPathPosition(pathId, stepT, source, target);
|
|
2996
|
+
vec2 stepNormal = queryPathNormal(pathId, stepT, source, target);
|
|
2997
|
+
vec2 offsetPos = stepPos + stepNormal * perpOffset;
|
|
2998
|
+
|
|
2999
|
+
// Distance along offset path
|
|
3000
|
+
float segDist = length(offsetPos - prevOffsetPos);
|
|
3001
|
+
|
|
3002
|
+
${d?`if (accumDist + segDist >= effectiveTargetDist) {
|
|
3003
|
+
// Interpolate within segment to find exact t
|
|
3004
|
+
float remaining = effectiveTargetDist - accumDist;
|
|
3005
|
+
float segT = remaining / max(segDist, 0.0001);
|
|
3006
|
+
foundT = mix(prevT, stepT, segT);
|
|
3007
|
+
break;
|
|
3008
|
+
}`:`if (accumDist + segDist >= targetOffsetDist) {
|
|
3009
|
+
// Interpolate within segment to find exact t
|
|
3010
|
+
float remaining = targetOffsetDist - accumDist;
|
|
3011
|
+
float segT = remaining / max(segDist, 0.0001);
|
|
3012
|
+
foundT = mix(prevT, stepT, segT);
|
|
3013
|
+
break;
|
|
3014
|
+
}`}
|
|
3015
|
+
|
|
3016
|
+
accumDist += segDist;
|
|
3017
|
+
prevOffsetPos = offsetPos;
|
|
3018
|
+
prevT = stepT;
|
|
3019
|
+
// Update foundT to last valid position in case loop exhausts without finding target
|
|
3020
|
+
foundT = stepT;
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
charT = foundT;
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
// Get position and tangent at final character position
|
|
3028
|
+
vec2 pathPos = queryPathPosition(pathId, charT, source, target);
|
|
3029
|
+
vec2 tangent = queryPathTangent(pathId, charT, source, target);
|
|
3030
|
+
|
|
3031
|
+
// Compute perpendicular direction (90 degrees from tangent)
|
|
3032
|
+
vec2 perpDir = vec2(-tangent.y, tangent.x);
|
|
3033
|
+
|
|
3034
|
+
// Apply perpendicular offset to path position
|
|
3035
|
+
vec2 offsetPathPos = pathPos + perpDir * perpOffset;
|
|
3036
|
+
|
|
3037
|
+
// -------------------------------------------------------------------------
|
|
3038
|
+
// Step 8: Build character quad
|
|
3039
|
+
// -------------------------------------------------------------------------
|
|
3040
|
+
// Character size in screen pixels
|
|
3041
|
+
vec2 charSizePixels = charSize * fontScale;
|
|
3042
|
+
|
|
3043
|
+
// Character offset from origin to the atlas region's top-left corner.
|
|
3044
|
+
// bearingX/bearingY already include the SDF buffer.
|
|
3045
|
+
vec2 charOffsetPixels = charOffset * fontScale;
|
|
3046
|
+
|
|
3047
|
+
// The character's local X offset from pathPos (which is at character center)
|
|
3048
|
+
float charLocalX = -charAdvance * 0.5 * fontScale;
|
|
3049
|
+
|
|
3050
|
+
// Build quad position:
|
|
3051
|
+
// - Start at character origin (charLocalX on X axis, 0 on Y axis = baseline)
|
|
3052
|
+
// - Add bearing offset to get to atlas region corner
|
|
3053
|
+
// - Add quad corner * size to get vertex position
|
|
3054
|
+
vec2 quadPos;
|
|
3055
|
+
quadPos.x = charLocalX + charOffsetPixels.x + a_quadCorner.x * charSizePixels.x;
|
|
3056
|
+
// charOffset.y = -bearingY (negated), so -charOffsetPixels.y = bearingY * fontScale
|
|
3057
|
+
// (distance from baseline to atlas region top, positive = upward)
|
|
3058
|
+
// Quad corner (0,0) = bottom-left, (1,1) = top-right
|
|
3059
|
+
quadPos.y = -charOffsetPixels.y - charSizePixels.y * (1.0 - a_quadCorner.y);
|
|
3060
|
+
|
|
3061
|
+
// Center vertically on the path by offsetting by half the visual text height
|
|
3062
|
+
// VERTICAL_CENTER_RATIO is the distance from baseline to visual center as a ratio of atlas font size
|
|
3063
|
+
float verticalCenterOffset = VERTICAL_CENTER_RATIO * ATLAS_FONT_SIZE * fontScale;
|
|
3064
|
+
quadPos.y -= verticalCenterOffset;
|
|
3065
|
+
|
|
3066
|
+
// -------------------------------------------------------------------------
|
|
3067
|
+
// Step 9: Rotate quad to align with tangent
|
|
3068
|
+
// -------------------------------------------------------------------------
|
|
3069
|
+
// Rotation matrix from tangent
|
|
3070
|
+
// tangent = (cos(angle), sin(angle)), so we can build rotation directly
|
|
3071
|
+
mat2 rotation = mat2(tangent.x, tangent.y, -tangent.y, tangent.x);
|
|
3072
|
+
|
|
3073
|
+
// Convert pixel offset to WebGL units for rotation
|
|
3074
|
+
${u?`vec2 quadPosWebGL = quadPos * u_correctionRatio / u_sizeRatio; // Scaled mode`:`vec2 quadPosWebGL = quadPos * pixelToGraph; // Fixed mode: use pixelToGraph for zoom-independent size`}
|
|
3075
|
+
|
|
3076
|
+
// Rotate around character center on path
|
|
3077
|
+
vec2 rotatedOffset = rotation * quadPosWebGL;
|
|
3078
|
+
|
|
3079
|
+
// Final position in graph space (using offset path position for above/below modes)
|
|
3080
|
+
vec2 worldPos = offsetPathPos + rotatedOffset;
|
|
3081
|
+
|
|
3082
|
+
// -------------------------------------------------------------------------
|
|
3083
|
+
// Step 10: Transform to clip space
|
|
3084
|
+
// -------------------------------------------------------------------------
|
|
3085
|
+
vec3 clipPos = u_matrix * vec3(worldPos, 1.0);
|
|
3086
|
+
gl_Position = vec4(clipPos.xy, 0.0, 1.0);
|
|
3087
|
+
|
|
3088
|
+
// -------------------------------------------------------------------------
|
|
3089
|
+
// Step 11: Texture coordinates
|
|
3090
|
+
// -------------------------------------------------------------------------
|
|
3091
|
+
// Flip Y for texture coordinates (texture Y goes down, quad Y goes up)
|
|
3092
|
+
vec2 texCorner = vec2(a_quadCorner.x, 1.0 - a_quadCorner.y);
|
|
3093
|
+
v_texCoord = (a_texCoords.xy + texCorner * a_texCoords.zw) / u_atlasSize;
|
|
3094
|
+
|
|
3095
|
+
// -------------------------------------------------------------------------
|
|
3096
|
+
// Step 12: Pass color, border color, and alpha modifier
|
|
3097
|
+
// -------------------------------------------------------------------------
|
|
3098
|
+
v_color = a_color;
|
|
3099
|
+
v_color.a *= bias;
|
|
3100
|
+
${r?` v_borderColor = a_borderColor;
|
|
3101
|
+
v_borderColor.a *= bias;
|
|
3102
|
+
v_positionMode = positionMode;`:``}
|
|
3103
|
+
v_alphaModifier = alphaModifier;
|
|
3104
|
+
|
|
3105
|
+
// -------------------------------------------------------------------------
|
|
3106
|
+
// Step 13: Compute edge fade for soft truncation
|
|
3107
|
+
// -------------------------------------------------------------------------
|
|
3108
|
+
// Convert fade width from pixels to WebGL units
|
|
3109
|
+
${u?`float fadeWidthWebGL = FADE_WIDTH_PIXELS * u_correctionRatio / u_sizeRatio;`:`float fadeWidthWebGL = FADE_WIDTH_PIXELS * pixelToGraph;`}
|
|
3110
|
+
|
|
3111
|
+
// Compute the arc position of THIS VERTEX (not just character center)
|
|
3112
|
+
// The quad extends from charCenter - advance/2 to charCenter + advance/2
|
|
3113
|
+
// a_quadCorner.x is 0 for left edge, 1 for right edge
|
|
3114
|
+
float vertexLocalOffset = (a_quadCorner.x - 0.5) * charAdvanceWebGL;
|
|
3115
|
+
float vertexArcOffset = charCenterOffset + vertexLocalOffset;
|
|
3116
|
+
|
|
3117
|
+
// Compute distance from body edges (positive = inside body, negative = outside)
|
|
3118
|
+
float halfBody = bodyLength * 0.5;
|
|
3119
|
+
float distFromStart = vertexArcOffset + halfBody; // Distance from body start edge
|
|
3120
|
+
float distFromEnd = halfBody - vertexArcOffset; // Distance from body end edge
|
|
3121
|
+
float distFromEdge = min(distFromStart, distFromEnd);
|
|
3122
|
+
|
|
3123
|
+
// Compute fade: 0 = fully visible (deep inside body), 1 = fully faded (at body edge)
|
|
3124
|
+
// Fade goes from 0 (at 2*fadeWidth inside) to 1 (at body edge)
|
|
3125
|
+
// This ensures text is fully transparent before reaching extremities
|
|
3126
|
+
v_edgeFade = 1.0 - smoothstep(0.0, fadeWidthWebGL * 2.0, distFromEdge);
|
|
3127
|
+
}
|
|
3128
|
+
`}function No(){var e=(arguments.length>0&&arguments[0]!==void 0?arguments[0]:{}).hasBorder,t=e!==void 0&&e;return`#version 300 es
|
|
3129
|
+
precision highp float;
|
|
3130
|
+
|
|
3131
|
+
in vec2 v_texCoord;
|
|
3132
|
+
in vec4 v_color;
|
|
3133
|
+
${t?`in vec4 v_borderColor;`:``}
|
|
3134
|
+
in float v_edgeFade; // 0 = fully visible, 1 = fully faded
|
|
3135
|
+
in float v_alphaModifier; // 0-1 based on label visibility ratio
|
|
3136
|
+
in float v_fontScale; // Ratio of rendered font size to atlas font size
|
|
3137
|
+
${t?`in float v_positionMode; // Position mode (0=over, 1=above, 2=below, 3=auto)`:``}
|
|
3138
|
+
|
|
3139
|
+
uniform sampler2D u_atlas;
|
|
3140
|
+
uniform float u_gamma;
|
|
3141
|
+
uniform float u_sdfBuffer;
|
|
3142
|
+
uniform float u_pixelRatio;
|
|
3143
|
+
${t?`uniform float u_borderWidth; // Border width in SDF units (normalized)`:``}
|
|
3144
|
+
|
|
3145
|
+
// Fragment output (single target - picking handled via separate pass)
|
|
3146
|
+
out vec4 fragColor;
|
|
3147
|
+
|
|
3148
|
+
void main() {
|
|
3149
|
+
#ifdef PICKING_MODE
|
|
3150
|
+
// Edge labels are not pickable - discard all fragments in picking mode
|
|
3151
|
+
discard;
|
|
3152
|
+
#else
|
|
3153
|
+
// SDF stores normalized distance: 0.5 = on edge, >0.5 = inside glyph
|
|
3154
|
+
float sdfValue = texture(u_atlas, v_texCoord).a;
|
|
3155
|
+
|
|
3156
|
+
// Edge threshold accounting for SDF buffer padding
|
|
3157
|
+
float edge = 1.0 - u_sdfBuffer;
|
|
3158
|
+
|
|
3159
|
+
// Scale gamma inversely with font scale so small labels get a wider AA band
|
|
3160
|
+
// (smoother) and large labels get a tighter band (sharper).
|
|
3161
|
+
float aaWidth = u_gamma / (u_pixelRatio * v_fontScale);
|
|
3162
|
+
|
|
3163
|
+
// Apply edge fade for soft truncation at body boundaries
|
|
3164
|
+
// Also apply visibility-based alpha modifier for short edge labels
|
|
3165
|
+
float edgeAlpha = (1.0 - v_edgeFade) * v_alphaModifier;
|
|
3166
|
+
|
|
3167
|
+
${t?` // Fill alpha: fully opaque inside the glyph
|
|
3168
|
+
float fillAlpha = smoothstep(edge - aaWidth, edge + aaWidth, sdfValue);
|
|
3169
|
+
|
|
3170
|
+
// Only apply border for "over" position mode (v_positionMode == 0.0)
|
|
3171
|
+
// Labels positioned above/below/auto don't overlap the edge line and don't need borders
|
|
3172
|
+
if (v_positionMode < 0.5) {
|
|
3173
|
+
// Border rendering: compute alpha for both fill and border regions
|
|
3174
|
+
// Border extends from (edge - borderWidth) to edge
|
|
3175
|
+
float borderEdge = edge - u_borderWidth;
|
|
3176
|
+
|
|
3177
|
+
// Border alpha: opaque in the border region (between borderEdge and edge)
|
|
3178
|
+
float borderAlpha = smoothstep(borderEdge - aaWidth, borderEdge + aaWidth, sdfValue);
|
|
3179
|
+
|
|
3180
|
+
// Composite: fill on top of border
|
|
3181
|
+
// Border is visible where borderAlpha > 0 but fillAlpha < 1
|
|
3182
|
+
vec3 borderColorPremult = v_borderColor.rgb * v_borderColor.a * borderAlpha * edgeAlpha;
|
|
3183
|
+
vec3 fillColorPremult = v_color.rgb * v_color.a * fillAlpha * edgeAlpha;
|
|
3184
|
+
|
|
3185
|
+
// Blend fill over border (fill replaces border where fill is opaque)
|
|
3186
|
+
float finalBorderAlpha = borderAlpha * (1.0 - fillAlpha);
|
|
3187
|
+
vec3 finalColor = fillColorPremult + v_borderColor.rgb * v_borderColor.a * finalBorderAlpha * edgeAlpha;
|
|
3188
|
+
float finalAlpha = (v_color.a * fillAlpha + v_borderColor.a * finalBorderAlpha) * edgeAlpha;
|
|
3189
|
+
|
|
3190
|
+
fragColor = vec4(finalColor, finalAlpha);
|
|
3191
|
+
} else {
|
|
3192
|
+
// No border for above/below/auto positions - simple text rendering
|
|
3193
|
+
float finalAlpha = v_color.a * fillAlpha * edgeAlpha;
|
|
3194
|
+
fragColor = vec4(v_color.rgb * finalAlpha, finalAlpha);
|
|
3195
|
+
}`:` // Smooth transition from transparent to opaque at glyph edge
|
|
3196
|
+
float alpha = smoothstep(edge - aaWidth, edge + aaWidth, sdfValue);
|
|
3197
|
+
|
|
3198
|
+
// Premultiplied alpha output
|
|
3199
|
+
float finalAlpha = v_color.a * alpha * edgeAlpha;
|
|
3200
|
+
fragColor = vec4(v_color.rgb * finalAlpha, finalAlpha);`}
|
|
3201
|
+
#endif
|
|
3202
|
+
}
|
|
3203
|
+
`}function Po(e){var t=arguments.length>1&&arguments[1]!==void 0&&arguments[1],n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:`fixed`,r=[`u_matrix`,`u_sizeRatio`,`u_correctionRatio`,`u_pixelRatio`,`u_cameraAngle`,`u_sdfBufferPixels`,`u_resolution`,`u_atlasSize`,`u_atlas`,`u_gamma`,`u_sdfBuffer`,`u_nodeDataTexture`,`u_nodeDataTextureWidth`,`u_edgeDataTexture`,`u_edgeDataTextureWidth`,`u_edgeFrameTexture`,`u_edgeFrameTextureWidth`,`u_edgeAttributeTexture`,`u_edgeAttributeTextureWidth`,`u_edgeAttributeTexelsPerEdge`];n===`scaled`&&r.push(`u_zoomSizeRatio`),t&&r.push(`u_borderWidth`);var i=H(e),a;try{for(i.s();!(a=i.n()).done;){var o=a.value,s=H(o.uniforms),c;try{for(s.s();!(c=s.n()).done;){var l=c.value;r.includes(l.name)||r.push(l.name)}}catch(e){s.e(e)}finally{s.f()}}}catch(e){i.e(e)}finally{i.f()}return r}function Fo(e){var t=e.hasBorder,n=t!==void 0&&t,r=e.fontSizeMode,i=r===void 0?`fixed`:r;return{vertexShader:Mo(e),fragmentShader:No({hasBorder:n}),uniforms:Po(e.paths,n,i)}}var Io=new Map;function Lo(e){switch(e){case`over`:return 0;case`above`:return 1;case`below`:return 2;case`auto`:return 3;default:return 0}}function Ro(e,t,n,r){var i=r.color,a=r.margin,o=r.textBorder,s=ko(r),c=s.paths,l=s.fontSizeMode,u=s.minVisibilityThreshold,d=s.fullVisibilityThreshold,f=!!o,p=Fo({paths:c,hasBorder:f,fontSizeMode:l,minVisibilityThreshold:u,fullVisibilityThreshold:d}),m=function(e){function t(e,n,r){var i;G(this,t),i=q(this,t,[e,n,r]),U(i,`atlasTexture`,null),U(i,`atlasNeedsUpdate`,!1),U(i,`labelGlyphCache`,new Map),U(i,`edgeAttributeTexture`,null);var a=kn();if(i.attributeLayout=zi([].concat(Y(c),[a])),i.attrDescriptors=Vi([].concat(Y(c),[a]),i.attributeLayout),i.edgeAttributeTexture=new Bi(e,i.attributeLayout),i.packedAttributeData=new Float32Array(i.attributeLayout.floatsPerItem),i.atlasManager=new wa,i.gamma=.025,i.sdfBuffer=_a.cutoff,i.atlasTexture=e.createTexture(),!i.atlasTexture)throw Error(`EdgeLabelProgram: failed to create atlas texture`);return e.bindTexture(e.TEXTURE_2D,i.atlasTexture),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.bindTexture(e.TEXTURE_2D,null),i.atlasManager.on(wa.ATLAS_UPDATED_EVENT,function(){i.atlasNeedsUpdate=!0,setTimeout(function(){return i.renderer.refresh()},0)}),i.defaultFontKey=i.atlasManager.registerFont({family:`sans-serif`,weight:`normal`,style:`normal`}),i}return J(t,e),K(t,[{key:`getDefinition`,value:function(){var e=WebGL2RenderingContext,t=e.FLOAT,n=e.UNSIGNED_BYTE,r=e.TRIANGLE_STRIP,i=new Set,a=[],o=H(c),s;try{for(o.s();!(s=o.n()).done;){var l=s.value,u=H(l.attributes),d;try{for(u.s();!(d=u.n()).done;){var m=d.value,h=m.name.startsWith(`a_`)?m.name:`a_${m.name}`;i.has(h)||(i.add(h),a.push({name:h,size:m.size,type:m.type}))}}catch(e){u.e(e)}finally{u.f()}}}catch(e){o.e(e)}finally{o.f()}return{VERTICES:4,VERTEX_SHADER_SOURCE:p.vertexShader,FRAGMENT_SHADER_SOURCE:p.fragmentShader,METHOD:r,UNIFORMS:p.uniforms,ATTRIBUTES:[{name:`a_edgeIndex`,size:1,type:t},{name:`a_edgeAttrIndex`,size:1,type:t},{name:`a_baseFontSize`,size:1,type:t},{name:`a_charMetrics`,size:4,type:t},{name:`a_charDims`,size:4,type:t},{name:`a_texCoords`,size:4,type:t},{name:`a_labelParams`,size:2,type:t},{name:`a_color`,size:4,type:n,normalized:!0}].concat(Y(f?[{name:`a_borderColor`,size:4,type:n,normalized:!0}]:[]),Y(a.filter(function(e){return![`a_curvature`,`curvature`].includes(e.name)}))),CONSTANT_ATTRIBUTES:[{name:`a_quadCorner`,size:2,type:t}],CONSTANT_DATA:[[0,0],[1,0],[0,1],[1,1]]}}},{key:`prepareLabelGlyphs`,value:function(e,t){if(t.hidden||!t.text)this.labelGlyphCache.delete(e);else{var n=t.text,r=t.fontKey||this.defaultFontKey;this.atlasManager.ensureGlyphs(n,r);var i=[],a=[],o=0,s=H(n),c;try{for(s.s();!(c=s.n()).done;){var l=c.value.codePointAt(0);if(l===void 0)i.push(void 0),a.push(o);else{var u=this.atlasManager.getGlyph(l,r);i.push(u),a.push(o),u&&(o+=u.advance)}}}catch(e){s.e(e)}finally{s.f()}this.labelGlyphCache.set(e,{glyphs:i,xOffsets:a,totalWidth:o})}}},{key:`processCharacter`,value:function(e,n,r,i){var a=this.floats,s=this.STRIDE,l=e*s,u=this.labelGlyphCache.get(n.parentKey);if(!u||!u.glyphs[i])for(var d=0;d<s;d++)a[l+d]=0;else{var p=u.glyphs[i],m=u.xOffsets[i],h=t.labelColor,g=sn(h&&X(h)===`object`&&`color`in h&&h.color?h.color:n.color),_=l;a[_++]=n.edgeIndex,a[_++]=this.edgeAttributeTexture?.getIndex(n.parentKey)??0,a[_++]=n.size,a[_++]=m,a[_++]=p.advance,a[_++]=u.totalWidth,a[_++]=Lo(n.position),a[_++]=p.atlasWidth,a[_++]=p.atlasHeight,a[_++]=p.bearingX,a[_++]=-p.bearingY,a[_++]=p.atlasX,a[_++]=p.atlasY,a[_++]=p.atlasWidth,a[_++]=p.atlasHeight;var v=t.labelMargin??n.margin;if(a[_++]=v,a[_++]=0,a[_++]=g,f&&o){var y=typeof o.color==`string`?o.color:o.color.color||`#ffffff`;a[_++]=sn(y)}var b=new Set,x=H(c),S;try{for(x.s();!(S=x.n()).done;){var C=S.value,w=H(C.attributes),T;try{for(w.s();!(T=w.n()).done;){var E=T.value,D=E.name.startsWith(`a_`)?E.name.slice(2):E.name;if(D!==`curvature`&&!b.has(D)){b.add(D);for(var O=0;O<E.size;O++)a[_++]=0}}}catch(e){w.e(e)}finally{w.f()}}}catch(e){x.e(e)}finally{x.f()}}}},{key:`processEdgeLabel`,value:function(e,n,r){if(this.prepareLabelGlyphs(e,r),this.edgeAttributeTexture&&!r.hidden&&r.text){this.edgeAttributeTexture.allocate(e);var i=this.packedAttributeData;Hi(this.attrDescriptors,r.edgeAttributes,i,``,Io,0),this.edgeAttributeTexture.updateAllAttributes(e,i)}return Q(t,`processLabel`,this,3)([e,n,r])}},{key:`updateAtlasTexture`,value:function(){if(this.atlasNeedsUpdate){var e=this.normalProgram.gl,t=this.atlasManager.getTextures();if(t.length!==0){var n=t[0];e.bindTexture(e.TEXTURE_2D,this.atlasTexture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,n.width,n.height,0,e.RGBA,e.UNSIGNED_BYTE,n.data),e.bindTexture(e.TEXTURE_2D,null),this.atlasNeedsUpdate=!1}}}},{key:`setUniforms`,value:function(e,t){var n=t.gl,r=t.uniformLocations,i=this.atlasManager.getTextures(),a=i.length>0?[i[0].width,i[0].height]:[1,1];if(n.uniformMatrix3fv(r.u_matrix,!1,e.matrix),n.uniform1f(r.u_sizeRatio,e.sizeRatio),n.uniform1f(r.u_correctionRatio,e.correctionRatio),n.uniform1f(r.u_pixelRatio,e.pixelRatio),n.uniform1f(r.u_cameraAngle,e.cameraAngle),n.uniform1f(r.u_sdfBufferPixels,_a.buffer),n.uniform2f(r.u_resolution,e.width,e.height),n.uniform2f(r.u_atlasSize,a[0],a[1]),n.uniform1f(r.u_gamma,this.gamma),n.uniform1f(r.u_sdfBuffer,this.sdfBuffer),n.activeTexture(n.TEXTURE0),n.bindTexture(n.TEXTURE_2D,this.atlasTexture),n.uniform1i(r.u_atlas,0),r.u_nodeDataTexture!==void 0&&n.uniform1i(r.u_nodeDataTexture,e.nodeDataTextureUnit),r.u_nodeDataTextureWidth!==void 0&&n.uniform1i(r.u_nodeDataTextureWidth,e.nodeDataTextureWidth),r.u_edgeDataTexture!==void 0&&n.uniform1i(r.u_edgeDataTexture,e.edgeDataTextureUnit),r.u_edgeDataTextureWidth!==void 0&&n.uniform1i(r.u_edgeDataTextureWidth,e.edgeDataTextureWidth),r.u_edgeFrameTexture!==void 0&&n.uniform1i(r.u_edgeFrameTexture,e.edgeFrameTextureUnit),r.u_edgeFrameTextureWidth!==void 0&&n.uniform1i(r.u_edgeFrameTextureWidth,e.edgeFrameTextureWidth),f&&o&&r.u_borderWidth!==void 0){var s=o.width/_a.buffer*this.sdfBuffer;n.uniform1f(r.u_borderWidth,s)}if(this.edgeAttributeTexture&&r.u_edgeAttributeTexture!==void 0&&(this.edgeAttributeTexture.bind(Fa),n.uniform1i(r.u_edgeAttributeTexture,Fa),n.uniform1i(r.u_edgeAttributeTextureWidth,this.edgeAttributeTexture.getTextureWidth()),n.uniform1i(r.u_edgeAttributeTexelsPerEdge,this.edgeAttributeTexture.getTexelsPerItem())),l===`scaled`&&r.u_zoomSizeRatio!==void 0){var c=1/this.renderer.getSetting(`zoomToSizeRatioFunction`)(e.zoomRatio);n.uniform1f(r.u_zoomSizeRatio,c)}}},{key:`renderProgram`,value:function(e,n){this.updateAtlasTexture(),this.atlasManager.hasPendingGlyphs()&&(this.atlasManager.flush(),this.updateAtlasTexture()),this.edgeAttributeTexture&&this.edgeAttributeTexture.upload(),Q(t,`renderProgram`,this,3)([e,n])}},{key:`registerFont`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:`normal`,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:`normal`;return this.atlasManager.registerFont({family:e,weight:t,style:n})}},{key:`getAtlasManager`,value:function(){return this.atlasManager}},{key:`ensureGlyphsReady`,value:function(e,t){var n=t||this.defaultFontKey,r=H(e),i;try{for(r.s();!(i=r.n()).done;){var a=i.value;this.atlasManager.ensureGlyphs(a,n)}}catch(e){r.e(e)}finally{r.f()}this.atlasManager.flush()}},{key:`measureLabelAtlasWidth`,value:function(e,t){var n=t||this.defaultFontKey;this.atlasManager.ensureGlyphs(e,n),this.atlasManager.hasPendingGlyphs()&&this.atlasManager.flush();var r=0,i=H(e),a;try{for(i.s();!(a=i.n()).done;){var o=a.value.codePointAt(0);if(o!==void 0){var s=this.atlasManager.getGlyph(o,n);s&&(r+=s.advance)}}}catch(e){i.e(e)}finally{i.f()}return r}},{key:`measureLabel`,value:function(e,t,n){return{width:this.measureLabelAtlasWidth(e,n)*(t/_a.fontSize),height:t,textHeight:t}}},{key:`kill`,value:function(){var e=this.normalProgram.gl;this.atlasTexture&&=(e.deleteTexture(this.atlasTexture),null),this.edgeAttributeTexture&&=(this.edgeAttributeTexture.kill(),null),this.atlasManager.destroy(),this.labelGlyphCache.clear(),Q(t,`kill`,this,3)([])}}])}(pa);return U(m,`labelColor`,i),U(m,`labelMargin`,a),new m(e,t,n)}function zo(){return{name:`none`,glsl:`
|
|
3204
|
+
// No extremity - always returns positive (outside)
|
|
3205
|
+
float extremity_none(vec2 uv, float lengthRatio, float widthRatio) {
|
|
3206
|
+
return 1.0;
|
|
3207
|
+
}
|
|
3208
|
+
`,length:0,widthFactor:1,margin:0,uniforms:[],attributes:[]}}function Bo(e,t,n,r,i,a,o){var s=Ka(r),c=s.paths,l=s.layers,u=s.defaultHead,d=s.defaultTail,f=[zo()].concat(Y(s.extremities)),p={},m={};c.forEach(function(e,t){return p[e.name]=t}),f.forEach(function(e,t){return m[e.name]=t});var h=m[u]??0,g=m[d]??0,_=null,v=zi([].concat(Y(c),Y(l))),y=function(e){function t(e,n,r){var a;G(this,t),_||=po({paths:c,extremities:f,layers:l,antialias:i}),a=q(this,t,[e,n,r]),U(a,`layerLifecycles`,new Map),U(a,`needsShaderRegeneration`,!1),U(a,`edgeAttributeTexture`,null),U(a,`layout`,v),U(a,`attrDescriptors`,[]),U(a,`lifecycleIndexOffset`,c.length),a._pickingBuffer=n,a.edgeAttributeTexture=new Bi(e,a.layout),a.packedAttributeData=new Float32Array(a.layout.floatsPerItem),l.forEach(function(t,n){if(t.lifecycle){var i={gl:e,renderer:{refresh:function(){return r.refresh()}},getUniformLocation:function(t){return e.getUniformLocation(a.normalProgram.program,t)},requestShaderRegeneration:function(){a.needsShaderRegeneration=!0},requestRefresh:function(){r.refresh()}};a.layerLifecycles.set(n,t.lifecycle(i))}}),a.layerLifecycles.forEach(function(e){return e.init?.call(e)});var o=new Map;return a.layerLifecycles.forEach(function(e,t){e.getAttributeData&&o.set(c.length+t,e)}),a.attrDescriptors=Vi([].concat(Y(c),Y(l)),a.layout,o),a}return J(t,e),K(t,[{key:`getAttributeTexture`,value:function(){return this.edgeAttributeTexture}},{key:`resolveEdgeIds`,value:function(e,t,n){var r=e,i=0,a=h,o=g,s=t?r.selfLoopPath:n&&r.parallelPath?r.parallelPath:r.path;s&&p[s]!==void 0&&(i=p[s]),r.head&&r.head!==`none`&&m[r.head]!==void 0&&(a=m[r.head]),r.tail&&r.tail!==`none`&&m[r.tail]!==void 0&&(o=m[r.tail]);var c=f[a],l=f[o];return{pathId:i,headId:a,tailId:o,headLengthRatio:Tn(c.length)?0:c.length,tailLengthRatio:Tn(l.length)?0:l.length}}},{key:`getDefinition`,value:function(){var e=WebGL2RenderingContext.TRIANGLE_STRIP,t=_;return{VERTICES:t.verticesPerEdge,VERTEX_SHADER_SOURCE:t.vertexShader,FRAGMENT_SHADER_SOURCE:t.fragmentShader,METHOD:e,UNIFORMS:t.uniforms,ATTRIBUTES:t.attributes,CONSTANT_ATTRIBUTES:t.constantAttributes,CONSTANT_DATA:t.constantData}}},{key:`maybeRegenerateShaders`,value:function(){var e=this;if(this.needsShaderRegeneration){this.needsShaderRegeneration=!1,_=po({paths:c,extremities:f,layers:l.map(function(t,n){var r=e.layerLifecycles.get(n);return r!=null&&r.regenerate?r.regenerate():t}),antialias:this.renderer.getSetting(`antialiasEdges`)});var t=this.normalProgram.gl,n=this.normalProgram,r=n.program,i=n.buffer,a=n.vertexShader,o=n.fragmentShader;t.deleteProgram(r),t.deleteBuffer(i),t.deleteShader(a),t.deleteShader(o),this.normalProgram=this.getProgramInfo(`normal`,t,_.vertexShader,_.fragmentShader,this._pickingBuffer)}}},{key:`process`,value:function(e,t,n,r,i,a){var o=t*this.STRIDE;if(i.visibility===`hidden`||n.visibility===`hidden`||r.visibility===`hidden`){for(var s=o+this.STRIDE;o<s;o++)this.floats[o]=0;this.floats[t*this.STRIDE]=Li}else this.processVisibleItem(ln(e),o,n,r,i,a)}},{key:`processVisibleItem`,value:function(e,t,n,r,i,a){var o=this.floats,s=this.ints;o[t++]=a,o[t++]=sn(i.color),s[t++]=e,o[t++]=i.opacity??1;var c=this.packedAttributeData;Hi(this.attrDescriptors,i,c,i.color,this.layerLifecycles,this.lifecycleIndexOffset),this.edgeAttributeTexture.updateAllAttributesAtRow(a,c)}},{key:`setUniforms`,value:function(e,t){var n=this,r=t.gl,i=t.uniformLocations;i.u_matrix&&r.uniformMatrix3fv(i.u_matrix,!1,e.matrix),i.u_sizeRatio&&r.uniform1f(i.u_sizeRatio,e.sizeRatio),i.u_correctionRatio&&r.uniform1f(i.u_correctionRatio,e.correctionRatio),i.u_zoomRatio&&r.uniform1f(i.u_zoomRatio,e.zoomRatio),i.u_pixelRatio&&r.uniform1f(i.u_pixelRatio,e.pixelRatio),i.u_cameraAngle&&r.uniform1f(i.u_cameraAngle,e.cameraAngle),i.u_feather&&r.uniform1f(i.u_feather,e.antiAliasingFeather),i.u_minEdgeThickness&&r.uniform1f(i.u_minEdgeThickness,e.minEdgeThickness),i.u_pickingPadding&&r.uniform1f(i.u_pickingPadding,e.edgePickingPadding),i.u_nodeDataTexture&&r.uniform1i(i.u_nodeDataTexture,e.nodeDataTextureUnit),i.u_nodeDataTextureWidth&&r.uniform1i(i.u_nodeDataTextureWidth,e.nodeDataTextureWidth),i.u_edgeDataTexture&&r.uniform1i(i.u_edgeDataTexture,e.edgeDataTextureUnit),i.u_edgeDataTextureWidth&&r.uniform1i(i.u_edgeDataTextureWidth,e.edgeDataTextureWidth),i.u_edgeFrameTexture&&r.uniform1i(i.u_edgeFrameTexture,e.edgeFrameTextureUnit),i.u_edgeFrameTextureWidth&&r.uniform1i(i.u_edgeFrameTextureWidth,e.edgeFrameTextureWidth),this.edgeAttributeTexture&&this.layout.floatsPerItem>0&&(this.edgeAttributeTexture.bind(Fa),i.u_edgeAttributeTexture&&r.uniform1i(i.u_edgeAttributeTexture,Fa),i.u_edgeAttributeTextureWidth&&r.uniform1i(i.u_edgeAttributeTextureWidth,this.edgeAttributeTexture.getTextureWidth()),i.u_edgeAttributeTexelsPerEdge&&r.uniform1i(i.u_edgeAttributeTexelsPerEdge,this.edgeAttributeTexture.getTexelsPerItem()));var a=new Set;c.forEach(function(e){e.uniforms.forEach(function(e){a.has(e.name)||(a.add(e.name),n.setTypedUniform(e,t))})}),f.forEach(function(e){e.uniforms.forEach(function(e){a.has(e.name)||(a.add(e.name),n.setTypedUniform(e,t))})}),l.forEach(function(e){e.uniforms.forEach(function(e){a.has(e.name)||(a.add(e.name),n.setTypedUniform(e,t))})})}},{key:`render`,value:function(e,n,r){this.maybeRegenerateShaders(),Q(t,`render`,this,3)([e,n,r])}},{key:`renderProgram`,value:function(e,n){this.layerLifecycles.forEach(function(e){return e.beforeRender?.call(e)}),Q(t,`renderProgram`,this,3)([e,n])}},{key:`uploadAttributeTexture`,value:function(){this.edgeAttributeTexture&&this.layout.floatsPerItem>0&&this.edgeAttributeTexture.upload()}},{key:`kill`,value:function(){this.layerLifecycles.forEach(function(e){return e.kill?.call(e)}),this.edgeAttributeTexture&&=(this.edgeAttributeTexture.kill(),null),Q(t,`kill`,this,3)([])}}])}(Ji),b=f[h],x=f[g],S=W({paths:c,headLengthRatio:Tn(b.length)?0:b.length,tailLengthRatio:Tn(x.length)?0:x.length},r.label),C=ko(S),w=Ro(e,null,n,S),T=Oo(e,t,n,{shaderConfig:C}),E=new go(e,{paths:c,extremities:f,layers:l,nodeShapes:a,nodeLayers:o});return{edgeProgram:new y(e,null,n),labelProgram:w,labelBackgroundProgram:T,framePass:E}}function Vo(e){return X(e)===`object`&&`uniforms`in e&&Array.isArray(e.uniforms)}function Ho(e){return X(e)===`object`&&`uniforms`in e&&`attributes`in e&&`glsl`in e}function Uo(e){return X(e)===`object`&&`uniforms`in e&&`attributes`in e&&`segments`in e}function Wo(e){return X(e)===`object`&&`uniforms`in e&&`attributes`in e&&`length`in e}function Go(e){return X(e)===`object`&&`uniforms`in e&&`attributes`in e&&`glsl`in e}function Ko(e){return X(e)===`object`&&`glsl`in e&&`name`in e&&!(`uniforms`in e)}function qo(e){return X(e)===`object`&&`glsl`in e&&`name`in e&&!(`uniforms`in e)}function Jo(e){return X(e)===`object`&&`glsl`in e&&`name`in e&&!(`uniforms`in e)}function Yo(e){if(Vo(e))return e;if(Ko(e))return{name:e.name,glsl:e.glsl,inradiusFactor:e.inradiusFactor,uniforms:[]};throw Error(`Invalid node shape specification: ${JSON.stringify(e)}`)}function Xo(e){if(Ho(e))return e;if(Mn(e))return{name:e.name,glsl:e.glsl,uniforms:[],attributes:[]};throw Error(`Invalid node layer specification: ${JSON.stringify(e)}`)}function Zo(e){if(Uo(e))return e;if(qo(e))return{name:e.name,glsl:e.glsl,segments:e.segments,uniforms:[],attributes:[]};throw Error(`Invalid edge path specification: ${JSON.stringify(e)}`)}function Qo(e){if(Go(e))return e;if(Nn(e))return{name:e.name,glsl:e.glsl,uniforms:[],attributes:[]};throw Error(`Invalid edge layer specification: ${JSON.stringify(e)}`)}function $o(e){if(Wo(e))return e;if(Jo(e))return{name:e.name,glsl:e.glsl,length:e.length,widthFactor:e.widthFactor,margin:0,uniforms:[],attributes:[]};throw Error(`Invalid edge extremity specification: ${JSON.stringify(e)}`)}function es(e){var t=e?.shapes??Pn.shapes,n=e?.layers??Pn.layers,r=t.map(Yo),i=n.map(Xo);if(r.length===0)throw Error(`At least one node shape must be specified.`);if(i.length===0)throw Error(`At least one node layer must be specified.`);return{shapes:r,layers:i}}function ts(e){var t=e?.paths??Fn.paths,n=e?.extremities??Fn.extremities,r=e?.layers??Fn.layers,i=t.map(Zo),a=n.map($o).filter(function(e){return e!==null}),o=r.map(Qo);if(i.length===0)throw Error(`At least one edge path must be specified.`);if(o.length===0)throw Error(`At least one edge layer must be specified.`);return{paths:i,extremities:a,layers:o}}function ns(e,t){var n={},r=H(e),i;try{for(r.s();!(i=r.n()).done;){var a=i.value;a.variables&&Object.assign(n,a.variables)}}catch(e){r.e(e)}finally{r.f()}return Object.assign(n,t||{}),n}function rs(e,t,n,r,i){var a=es(r),o=a.shapes,s=a.layers,c=ns(o,r?.variables);return W(W({},Pa(e,t,n,{shapes:o,layers:s,label:r?.label,backdrop:r?.backdrop,labelAttachments:r?.labelAttachments},i)),{},{variables:c})}function is(e,t,n,r,i,a){var o=ts(r),s=o.paths,c=o.extremities,l=o.layers,u=es(a),d=u.shapes,f=u.layers,p=ns(s,r?.variables);return W(W({},Bo(e,t,n,{paths:s,extremities:c,layers:l,defaultHead:r?.defaultHead,defaultTail:r?.defaultTail,label:r?.label},i,d,f)),{},{variables:p,paths:s})}var as=2;function os(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:as,i=t.canvas,a=i.width,o=i.height,s=n.x,c=n.y,l=n.rowHeight,u=n.maxRowWidth,d={},f=[],p=H(e),m;try{for(p.s();!(m=p.n()).done;){var h=m.value,g=h.width+r,_=h.height+r;g>a||_>o||s+g>a&&c+l+_>o?f.push(h):(s+g>a&&(u=Math.max(u,s),s=0,c+=l,l=_),h.draw(t,s,c),d[h.key]={x:s,y:c,width:h.width,height:h.height},s+=g,l=Math.max(l,_))}}catch(e){p.e(e)}finally{p.f()}return u=Math.max(u,s),{atlas:d,cursor:{x:s,y:c,rowHeight:l,maxRowWidth:u},remaining:f}}function ss(e,t,n,r){var i=Object.defineProperty;try{i({},``,{})}catch{i=0}ss=function(e,t,n,r){function a(t,n){ss(e,t,function(e){return this._invoke(t,n,e)})}t?i?i(e,t,{value:n,enumerable:!r,configurable:!r,writable:!r}):e[t]=n:(a(`next`,0),a(`throw`,1),a(`return`,2))},ss(e,t,n,r)}function cs(){var e,t,n=typeof Symbol==`function`?Symbol:{},r=n.iterator||`@@iterator`,i=n.toStringTag||`@@toStringTag`;function a(n,r,i,a){var c=r&&r.prototype instanceof s?r:s,l=Object.create(c.prototype);return ss(l,`_invoke`,function(n,r,i){var a,s,c,l=0,u=i||[],d=!1,f={p:0,n:0,v:e,a:p,f:p.bind(e,4),d:function(t,n){return a=t,s=0,c=e,f.n=n,o}};function p(n,r){for(s=n,c=r,t=0;!d&&l&&!i&&t<u.length;t++){var i,a=u[t],p=f.p,m=a[2];n>3?(i=m===r)&&(c=a[(s=a[4])?5:(s=3,3)],a[4]=a[5]=e):a[0]<=p&&((i=n<2&&p<a[1])?(s=0,f.v=r,f.n=a[1]):p<m&&(i=n<3||a[0]>r||r>m)&&(a[4]=n,a[5]=r,f.n=m,s=0))}if(i||n>1)return o;throw d=!0,r}return function(i,u,m){if(l>1)throw TypeError(`Generator is already running`);for(d&&u===1&&p(u,m),s=u,c=m;(t=s<2?e:c)||!d;){a||(s?s<3?(s>1&&(f.n=-1),p(s,c)):f.n=c:f.v=c);try{if(l=2,a){if(s||(i=`next`),t=a[i]){if(!(t=t.call(a,c)))throw TypeError(`iterator result is not an object`);if(!t.done)return t;c=t.value,s<2&&(s=0)}else s===1&&(t=a.return)&&t.call(a),s<2&&(c=TypeError(`The iterator does not provide a '`+i+`' method`),s=1);a=e}else if((t=(d=f.n<0)?c:n.call(r,f))!==o)break}catch(t){a=e,s=1,c=t}finally{l=1}}return{value:t,done:d}}}(n,i,a),!0),l}var o={};function s(){}function c(){}function l(){}t=Object.getPrototypeOf;var u=[][r]?t(t([][r]())):(ss(t={},r,function(){return this}),t),d=l.prototype=s.prototype=Object.create(u);function f(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,l):(e.__proto__=l,ss(e,i,`GeneratorFunction`)),e.prototype=Object.create(d),e}return c.prototype=l,ss(d,`constructor`,l),ss(l,`constructor`,c),c.displayName=`GeneratorFunction`,ss(l,i,`GeneratorFunction`),ss(d),ss(d,i,`Generator`),ss(d,r,function(){return this}),ss(d,`toString`,function(){return`[object Generator]`}),(cs=function(){return{w:a,m:f}})()}function ls(e,t,n,r,i,a,o){try{var s=e[a](o),c=s.value}catch(e){n(e);return}s.done?t(c):Promise.resolve(c).then(r,i)}function us(e){return function(){var t=this,n=arguments;return new Promise(function(r,i){var a=e.apply(t,n);function o(e){ls(a,r,i,o,s,`next`,e)}function s(e){ls(a,r,i,o,s,`throw`,e)}o(void 0)})}}var ds=new Map,fs=!1;function ps(e){return new Promise(function(t,n){var r=new FileReader;r.onload=function(){return t(r.result)},r.onerror=n,r.readAsDataURL(e)})}function ms(e){if(!ds.has(e)){var t=fetch(e).then(function(e){return e.blob()}).then(ps).catch(function(){return ds.delete(e),null});ds.set(e,t)}return ds.get(e)}function hs(e){return gs.apply(this,arguments)}function gs(){return gs=us(cs().m(function e(t){var n,r,i;return cs().w(function(e){for(;;)switch(e.n){case 0:return n=document.createElement(`div`),n.innerHTML=t,r=Array.from(n.querySelectorAll(`img[src]`)),i=r.filter(function(e){return!e.getAttribute(`src`).startsWith(`data:`)}),e.n=1,Promise.all(i.map(function(){var e=us(cs().m(function e(t){var n;return cs().w(function(e){for(;;)switch(e.n){case 0:return e.n=1,ms(t.getAttribute(`src`));case 1:n=e.v,n&&t.setAttribute(`src`,n);case 2:return e.a(2)}},e)}));return function(t){return e.apply(this,arguments)}}()));case 1:return e.a(2,n.innerHTML)}},e)})),gs.apply(this,arguments)}function _s(e){return vs.apply(this,arguments)}function vs(){return vs=us(cs().m(function e(t){var n,r,i,a,o,s,c,l,u,d,f,p,m,h=arguments;return cs().w(function(e){for(;;)switch(e.n){case 0:if(n=h.length>1&&h[1]!==void 0?h[1]:1,r=t instanceof SVGElement?new XMLSerializer().serializeToString(t):t,i=new DOMParser,a=i.parseFromString(r,`image/svg+xml`),o=a.querySelector(`svg`),o){e.n=1;break}return e.a(2,null);case 1:if(s=parseFloat(o.getAttribute(`width`)||``),c=parseFloat(o.getAttribute(`height`)||``),(!(s>0)||!(c>0))&&(l=o.getAttribute(`viewBox`),l&&(u=l.trim().split(/[\s,]+/),s=parseFloat(u[2]),c=parseFloat(u[3]))),s>0&&c>0){e.n=2;break}return console.warn(`Sigma: SVG label attachment has no parseable dimensions — skipped.`),e.a(2,null);case 2:return d=Math.ceil(s*n),f=Math.ceil(c*n),p=new Blob([r],{type:`image/svg+xml`}),m=URL.createObjectURL(p),e.a(2,new Promise(function(e){var t=new Image;t.onload=function(){var n=document.createElement(`canvas`);n.width=d,n.height=f,n.getContext(`2d`).drawImage(t,0,0,d,f),URL.revokeObjectURL(m);try{n.getContext(`2d`).getImageData(0,0,1,1)}catch(t){if(t instanceof DOMException&&t.name===`SecurityError`){fs||(fs=!0,console.warn(`Sigma: A label attachment was skipped because the rendered canvas is tainted. SVG with <foreignObject> (used by the "html" attachment type) is blocked in Chromium and Safari. Use type: "canvas" with Canvas 2D rendering instead.`)),e(null);return}throw t}e(n)},t.onerror=function(){URL.revokeObjectURL(m),e(null)},t.src=m}))}},e)})),vs.apply(this,arguments)}function ys(e,t){var n=document.createElement(`div`);n.style.cssText=`position:fixed;left:-99999px;top:0;visibility:hidden;width:max-content;height:max-content`,n.innerHTML=(t?`<style>${t}</style>`:``)+e,document.body.appendChild(n);var r=n.getBoundingClientRect(),i=r.width,a=r.height;return document.body.removeChild(n),{width:Math.ceil(i),height:Math.ceil(a)}}function bs(e,t,n,r){return xs.apply(this,arguments)}function xs(){return xs=us(cs().m(function e(t,n,r,i){var a,o,s,c,l,u,d,f,p=arguments;return cs().w(function(e){for(;;)switch(e.n){case 0:return a=p.length>4&&p[4]!==void 0?p[4]:1,o=t instanceof HTMLElement?t.outerHTML:t,e.n=1,hs(o);case 1:return s=e.v,(r==null||i==null)&&(c=ys(s,n),r??=c.width,i??=c.height),l=Math.ceil(r*a),u=Math.ceil(i*a),d=n?`<style>${n}</style>`:``,f=`<svg xmlns="http://www.w3.org/2000/svg" width="${l}" height="${u}" viewBox="0 0 ${r} ${i}"><foreignObject width="${r}" height="${i}"><body xmlns="http://www.w3.org/1999/xhtml" style="margin:0;padding:0">${d}${s}</body></foreignObject></svg>`,e.a(2,_s(f,1))}},e)})),xs.apply(this,arguments)}function Ss(e){return Cs.apply(this,arguments)}function Cs(){return Cs=us(cs().m(function e(t){var n,r=arguments,i;return cs().w(function(e){for(;;)switch(e.n){case 0:n=r.length>1&&r[1]!==void 0?r[1]:1,i=t.type,e.n=i===`canvas`?1:i===`svg`?2:i===`html`?3:4;break;case 1:return e.a(2,t.canvas);case 2:return e.a(2,_s(t.svg,n));case 3:return e.a(2,bs(t.html,t.css,t.width,t.height,n));case 4:return e.a(2)}},e)})),Cs.apply(this,arguments)}var ws=2048,Ts=function(){function e(t,n,r){G(this,e),U(this,`cache`,new Map),U(this,`pending`,new Set),U(this,`atlas`,{}),U(this,`glTexture`,null),U(this,`dirty`,!0),this.gl=t,this.renderers=n,this.scheduleRender=r,this.packCanvas=document.createElement(`canvas`),this.packCanvas.width=ws,this.packCanvas.height=ws,this.packCtx=this.packCanvas.getContext(`2d`)}return K(e,[{key:`renderAttachment`,value:function(e,t,n){var r=this,i=`${e}:${t}`;if(!(this.cache.has(i)||this.pending.has(i))){var a=this.renderers[t];if(a){var o=a(n);if(o){this.pending.add(i);var s=n.pixelRatio;Promise.resolve(o).then(function(){var e=us(cs().m(function e(t){var n;return cs().w(function(e){for(;;)switch(e.n){case 0:if(r.pending.has(i)){e.n=1;break}return e.a(2);case 1:if(r.pending.delete(i),t){e.n=2;break}return e.a(2);case 2:return e.n=3,Ss(t,s);case 3:if(n=e.v,n&&n.width!==0&&n.height!==0){e.n=4;break}return e.a(2);case 4:r.cache.set(i,{image:n,width:n.width,height:n.height}),r.dirty=!0,r.scheduleRender();case 5:return e.a(2)}},e)}));return function(t){return e.apply(this,arguments)}}())}}}}},{key:`regenerateAtlas`,value:function(){if(this.dirty){this.dirty=!1;var e=[];if(this.cache.forEach(function(t,n){e.push({key:n,width:t.width,height:t.height,draw:function(e,n,r){e.drawImage(t.image,n,r)}})}),e.length===0)this.atlas={},this.deleteGLTexture();else{var t={x:0,y:0,rowHeight:0,maxRowWidth:0};this.packCtx.clearRect(0,0,ws,ws);var n=os(e,this.packCtx,t),r=n.atlas,i=n.remaining;this.atlas=r,i.length>0&&console.warn(`Sigma: ${i.length} label attachment(s) could not fit in the ${ws}x${ws} atlas and will not be rendered.`),this.deleteGLTexture();var a=this.gl,o=a.createTexture();a.activeTexture(a.TEXTURE0+7),a.bindTexture(a.TEXTURE_2D,o),a.pixelStorei(a.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,this.packCanvas),a.pixelStorei(a.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.glTexture=o}}}},{key:`bindTexture`,value:function(e){if(this.glTexture){var t=this.gl;t.activeTexture(t.TEXTURE0+e),t.bindTexture(t.TEXTURE_2D,this.glTexture)}}},{key:`getEntry`,value:function(e,t){var n=`${e}:${t}`;return this.atlas[n]||null}},{key:`invalidateNode`,value:function(e){var t=`${e}:`,n=H(this.cache.keys()),r;try{for(n.s();!(r=n.n()).done;){var i=r.value;i.startsWith(t)&&(this.cache.delete(i),this.dirty=!0)}}catch(e){n.e(e)}finally{n.f()}var a=H(this.pending),o;try{for(a.s();!(o=a.n()).done;){var s=o.value;s.startsWith(t)&&this.pending.delete(s)}}catch(e){a.e(e)}finally{a.f()}}},{key:`restore`,value:function(){this.glTexture=null,this.dirty=!0}},{key:`clear`,value:function(){this.cache.clear(),this.pending.clear(),this.atlas={},this.dirty=!0,this.deleteGLTexture()}},{key:`kill`,value:function(){this.clear(),this.packCanvas=null,this.packCtx=null,this.gl=null}},{key:`deleteGLTexture`,value:function(){this.glTexture&&=(this.gl.deleteTexture(this.glTexture),null)}}])}(),Es=function(){function e(t){G(this,e),U(this,`buckets`,new Map),U(this,`keyDepth`,new Map);var n=H(t),r;try{for(n.s();!(r=n.n()).done;){var i=r.value;this.buckets.set(i,new Set)}}catch(e){n.e(e)}finally{n.f()}}return K(e,[{key:`has`,value:function(e){return this.keyDepth.has(e)}},{key:`getBucket`,value:function(e){return this.buckets.get(e)}},{key:`set`,value:function(e,t){var n,r=this.keyDepth.get(e);if(r!==t){var i=this.buckets.get(t);if(!i)throw Error(`Sigma: "${t}" is not a declared depth layer`);r!==void 0&&((n=this.buckets.get(r))==null||n.delete(e)),i.add(e),this.keyDepth.set(e,t)}}},{key:`remove`,value:function(e){var t=this.keyDepth.get(e);t!==void 0&&(this.buckets.get(t).delete(e),this.keyDepth.delete(e))}},{key:`clearAll`,value:function(){var e=H(this.buckets.values()),t;try{for(e.s();!(t=e.n()).done;)t.value.clear()}catch(t){e.e(t)}finally{e.f()}this.keyDepth.clear()}},{key:`getSorted`,value:function(e,t){var n=this.buckets.get(e);return!n||n.size===0?[]:Y(n).sort(function(e,n){return t(e)-t(n)})}}])}(),Ds=function(e){function t(e,n){return G(this,t),q(this,t,[e,2,n])}return J(t,e),K(t,[{key:`updateNode`,value:function(e,t,n,r,i,a,o,s){var c=this.indexMap.get(e);if(c===void 0)throw Error(`Node "${e}" not allocated in NodeDataTexture`);var l=V(cn(s),4),u=l[0],d=l[1],f=l[2],p=l[3],m=c*2*4;this.data[m]=t,this.data[m+1]=n,this.data[m+2]=r,this.data[m+3]=i,this.data[m+4]=a,this.data[m+5]=o,this.data[m+6]=u*65536+d*256+f,this.data[m+7]=p/255,this.markDirty(c)}}])}(Ri),Os=1024,ks=1.5,As=4096,js=function(){function e(t,n){if(G(this,e),U(this,`texture`,null),U(this,`framebuffer`,null),!t.getExtension(`EXT_color_buffer_float`))throw Error(`sigma: EXT_color_buffer_float is required for label/edge placement but is unavailable in this WebGL2 context.`);this.gl=t,this.channels=n.channels,this.capacity=this.roundUpToPowerOfTwo(n.initialCapacity??Os);var r=this.computeDimensions(this.capacity);this.textureWidth=r.width,this.textureHeight=r.height,this.create()}return K(e,[{key:`roundUpToPowerOfTwo`,value:function(e){return 2**Math.ceil(Math.log2(Math.max(1,e)))}},{key:`computeDimensions`,value:function(e){var t=Math.min(e,As);return{width:t,height:Math.ceil(e/t)}}},{key:`create`,value:function(){var e=this.gl,t=this.channels===1?e.R32F:e.RGBA32F,n=this.channels===1?e.RED:e.RGBA;if(this.texture=e.createTexture(),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.texture),e.texImage2D(e.TEXTURE_2D,0,t,this.textureWidth,this.textureHeight,0,n,e.FLOAT,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),this.framebuffer=e.createFramebuffer(),e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0),e.checkFramebufferStatus(e.FRAMEBUFFER)!==e.FRAMEBUFFER_COMPLETE)throw Error(`sigma: float framebuffer for frame-pass placement is incomplete.`);e.bindFramebuffer(e.FRAMEBUFFER,null),e.bindTexture(e.TEXTURE_2D,null)}},{key:`ensureCapacity`,value:function(e){if(!(e<=this.capacity)){var t=this.gl;this.capacity=this.roundUpToPowerOfTwo(Math.ceil(e*ks));var n=this.computeDimensions(this.capacity);this.textureWidth=n.width,this.textureHeight=n.height,this.texture&&t.deleteTexture(this.texture),this.framebuffer&&t.deleteFramebuffer(this.framebuffer),this.create()}}},{key:`bindAsRenderTarget`,value:function(){var e=this.gl;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer),e.viewport(0,0,this.textureWidth,this.textureHeight)}},{key:`bind`,value:function(e){var t=this.gl;t.activeTexture(t.TEXTURE0+e),t.bindTexture(t.TEXTURE_2D,this.texture)}},{key:`getTexture`,value:function(){return this.texture}},{key:`getTextureWidth`,value:function(){return this.textureWidth}},{key:`getTextureHeight`,value:function(){return this.textureHeight}},{key:`restore`,value:function(){this.gl.getExtension(`EXT_color_buffer_float`),this.create()}},{key:`kill`,value:function(){var e=this.gl;this.texture&&=(e.deleteTexture(this.texture),null),this.framebuffer&&=(e.deleteFramebuffer(this.framebuffer),null)}}])}(),Ms=function(e){function t(e,n){return G(this,t),q(this,t,[e,2,n])}return J(t,e),K(t,[{key:`updateEdge`,value:function(e,t,n,r,i,a){var o=arguments.length>6&&arguments[6]!==void 0?arguments[6]:0,s=arguments.length>7&&arguments[7]!==void 0?arguments[7]:0,c=arguments.length>8&&arguments[8]!==void 0?arguments[8]:0,l=this.indexMap.get(e);if(l===void 0)throw Error(`Edge "${e}" not allocated in EdgeDataTexture`);var u=l*this.TEXELS_PER_ITEM*4;this.data[u+0]=t,this.data[u+1]=n,this.data[u+2]=r,this.data[u+3]=0,this.data[u+4]=i,this.data[u+5]=a,this.data[u+6]=o,this.data[u+7]=(s&15)<<4|c&15,this.markDirty(l)}}])}(Ri);function Ns(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function Ps(e,t){if(e==null)return{};var n,r,i=Ns(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var Fs=[`factor`],Is=[`factor`],Ls=1.5,Rs={x:.5,y:.5,angle:0,ratio:1},zs=function(e){function t(){var e;G(this,t);var n=[...arguments];return e=q(this,t,[].concat(n)),U(e,`minRatio`,null),U(e,`maxRatio`,null),U(e,`enabled`,!0),U(e,`enabledZooming`,!0),U(e,`enabledPanning`,!0),U(e,`enabledRotation`,!0),U(e,`constrainState`,null),U(e,`state`,W({},Rs)),U(e,`previousState`,W({},Rs)),U(e,`nextFrame`,null),U(e,`currentAnimationFrom`,null),U(e,`currentAnimationTo`,null),U(e,`animationCallback`,null),e}return J(t,e),K(t,[{key:`x`,get:function(){return this.state.x}},{key:`y`,get:function(){return this.state.y}},{key:`angle`,get:function(){return this.state.angle}},{key:`ratio`,get:function(){return this.state.ratio}},{key:`getState`,value:function(){return W({},this.state)}},{key:`getPreviousState`,value:function(){return W({},this.previousState)}},{key:`getBoundedRatio`,value:function(e){var t=e;return typeof this.minRatio==`number`&&(t=Math.max(t,this.minRatio)),typeof this.maxRatio==`number`&&(t=Math.min(t,this.maxRatio)),t}},{key:`validateState`,value:function(e){var t=this.getState();return this.enabledPanning&&typeof e.x==`number`&&(t.x=e.x),this.enabledPanning&&typeof e.y==`number`&&(t.y=e.y),this.enabledZooming&&typeof e.ratio==`number`&&(t.ratio=this.getBoundedRatio(e.ratio)),this.enabledRotation&&typeof e.angle==`number`&&(t.angle=e.angle),this.constrainState?this.constrainState(t):t}},{key:`isAnimating`,value:function(){return this.nextFrame!==null}},{key:`setState`,value:function(e){if(!this.enabled)return this;var t=this.validateState(e);return jr(this.state,t)||(this.previousState=this.state,this.state=t,this.emit(`updated`,this.getState())),this}},{key:`updateState`,value:function(e){return this.setState(e(this.getState())),this}},{key:`animate`,value:function(e,t){var n=this;return this.enabled?new Promise(function(r){return n.runAnimation(e,W(W({},Pr),t),r)}):Promise.resolve()}},{key:`cancelAnimation`,value:function(){return this.nextFrame!==null&&(cancelAnimationFrame(this.nextFrame),this.nextFrame=null),this.resolveAnimation(),this.emitAnimationEnd(!1),this}},{key:`zoomIn`,value:function(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=e.factor,n=t===void 0?Ls:t,r=Ps(e,Fs);return this.animate({ratio:this.ratio/n},r)}},{key:`zoomOut`,value:function(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=e.factor,n=t===void 0?Ls:t,r=Ps(e,Is);return this.animate({ratio:this.ratio*n},r)}},{key:`reset`,value:function(e){return this.animate(Rs,e)}},{key:`runAnimation`,value:function(e,t,n){var r=this,i=Vn(t.easing),a=Date.now(),o=this.getState(),s=this.validateState(e),c=function(){if(!r.enabled)r.cancelAnimation();else{var e=t.duration>0?(Date.now()-a)/t.duration:1;if(e>=1)r.nextFrame=null,r.setState(s),r.resolveAnimation(),r.emitAnimationEnd(!0);else{var n=i(e);r.setState({x:o.x+(s.x-o.x)*n,y:o.y+(s.y-o.y)*n,angle:o.angle+(s.angle-o.angle)*n,ratio:o.ratio+(s.ratio-o.ratio)*n}),r.nextFrame=requestAnimationFrame(c)}}};this.cancelAnimation(),this.currentAnimationFrom=o,this.currentAnimationTo=s,this.animationCallback=n,this.emit(`animationStart`,{from:o,to:s}),c()}},{key:`resolveAnimation`,value:function(){var e=this.animationCallback;this.animationCallback=null,e&&e()}},{key:`emitAnimationEnd`,value:function(e){var t=this.currentAnimationFrom,n=this.currentAnimationTo;t&&n&&(this.currentAnimationFrom=null,this.currentAnimationTo=null,this.emit(`animationEnd`,{from:t,to:n,completed:e}))}}],[{key:`from`,value:function(e){return new t().setState(e)}}])}(Er);function Bs(e,t){var n=t.getBoundingClientRect();return{x:e.clientX-n.left,y:e.clientY-n.top}}function Vs(e,t){var n=W(W({},Bs(e,t)),{},{sigmaDefaultPrevented:!1,preventSigmaDefault:function(){n.sigmaDefaultPrevented=!0},original:e});return n}function Hs(e){var t=`x`in e?e:W(W({},e.touches[0]||e.previousTouches[0]),{},{original:e.original,sigmaDefaultPrevented:e.sigmaDefaultPrevented,preventSigmaDefault:function(){e.sigmaDefaultPrevented=!0,t.sigmaDefaultPrevented=!0}});return t}function Us(e,t){var n=Vs(e,t);return n.delta=qs(e),n}var Ws=2;function Gs(e){for(var t=[],n=0,r=Math.min(e.length,Ws);n<r;n++)t.push(e[n]);return t}function Ks(e,t,n){var r={touches:Gs(e.touches).map(function(e){return Bs(e,n)}),previousTouches:t.map(function(e){return Bs(e,n)}),sigmaDefaultPrevented:!1,preventSigmaDefault:function(){r.sigmaDefaultPrevented=!0},original:e};return r}function qs(e){if(e.deltaY!==void 0)return e.deltaY*-3/360;if(e.detail!==void 0)return e.detail/-9;throw Error(`Captor: could not extract delta from event.`)}var Js=function(e){function t(e,n){var r;return G(this,t),r=q(this,t),r.container=e,r.renderer=n,r}return J(t,e),K(t)}(Er),Ys=[`doubleClickTimeout`,`doubleClickZoomingDuration`,`doubleClickZoomingRatio`,`dragTimeout`,`draggedEventsTolerance`,`enableCameraMouseRotation`,`gestureTarget`,`inertiaDuration`,`inertiaRatio`,`zoomDuration`,`zoomingRatio`].reduce(function(e,t){return W(W({},e),{},U({},t,Hr[t]))},{});function Xs(e){return e instanceof PointerEvent&&e.pointerType===`touch`}var Zs=function(e){function t(e,n){var r;return G(this,t),r=q(this,t,[e,n]),U(r,`enabled`,!0),U(r,`draggedEvents`,0),U(r,`downStartTime`,null),U(r,`lastMouseX`,null),U(r,`lastMouseY`,null),U(r,`isMouseDown`,!1),U(r,`isMoving`,!1),U(r,`isPanningStage`,!1),U(r,`movingTimeout`,null),U(r,`startCameraState`,null),U(r,`clicks`,0),U(r,`doubleClickTimeout`,null),U(r,`isRightMouseDown`,!1),U(r,`startRotationAngle`,null),U(r,`startCameraAngle`,null),U(r,`currentWheelDirection`,0),U(r,`lastWheelAnimationId`,0),U(r,`settings`,Ys),r.handleRightClick=r.handleRightClick.bind(r),r.handleDown=r.handleDown.bind(r),r.handleUp=r.handleUp.bind(r),r.handleMove=r.handleMove.bind(r),r.handleWheel=r.handleWheel.bind(r),r.handleLeave=r.handleLeave.bind(r),r.handleEnter=r.handleEnter.bind(r),e.addEventListener(`contextmenu`,r.handleRightClick,{capture:!1}),e.addEventListener(`pointerdown`,r.handleDown,{capture:!1}),e.addEventListener(`wheel`,r.handleWheel,{capture:!1,passive:!1}),e.addEventListener(`pointerleave`,r.handleLeave,{capture:!1}),e.addEventListener(`pointerenter`,r.handleEnter,{capture:!1}),document.addEventListener(`pointermove`,r.handleMove,{capture:!1}),document.addEventListener(`pointerup`,r.handleUp,{capture:!1}),r}return J(t,e),K(t,[{key:`kill`,value:function(){var e=this.container;e.removeEventListener(`contextmenu`,this.handleRightClick),e.removeEventListener(`pointerdown`,this.handleDown),e.removeEventListener(`wheel`,this.handleWheel),e.removeEventListener(`pointerleave`,this.handleLeave),e.removeEventListener(`pointerenter`,this.handleEnter),document.removeEventListener(`pointermove`,this.handleMove),document.removeEventListener(`pointerup`,this.handleUp)}},{key:`handleClick`,value:function(e){var t=this;if(this.enabled){if(this.clicks++,this.clicks===2)return this.clicks=0,typeof this.doubleClickTimeout==`number`&&(clearTimeout(this.doubleClickTimeout),this.doubleClickTimeout=null),this.handleDoubleClick(e);setTimeout(function(){t.clicks=0,t.doubleClickTimeout=null},this.settings.doubleClickTimeout),this.draggedEvents<this.settings.draggedEventsTolerance&&this.emit(`click`,Vs(e,this.container))}}},{key:`handleRightClick`,value:function(e){this.enabled&&(this.settings.enableCameraMouseRotation&&e.preventDefault(),this.emit(`rightClick`,Vs(e,this.container)))}},{key:`handleDoubleClick`,value:function(e){if(this.enabled){e.preventDefault(),e.stopPropagation();var t=Vs(e,this.container);if(this.emit(`doubleClick`,t),!t.sigmaDefaultPrevented){var n=this.renderer.getCamera(),r=n.getBoundedRatio(n.getState().ratio/this.settings.doubleClickZoomingRatio);n.animate(this.renderer.getViewportZoomedState(Bs(e,this.container),r),{easing:`quadraticInOut`,duration:this.settings.doubleClickZoomingDuration})}}}},{key:`handleDown`,value:function(e){if(this.enabled&&!Xs(e)){if(e.button===0){this.startCameraState=this.renderer.getCamera().getState();var t=Bs(e,this.container),n=t.x,r=t.y;this.lastMouseX=n,this.lastMouseY=r,this.draggedEvents=0,this.downStartTime=Date.now(),this.isMouseDown=!0}if(e.button===2&&this.settings.enableCameraMouseRotation){var i=Bs(e,this.container),a=i.x,o=i.y,s=this.container.offsetWidth/2,c=this.container.offsetHeight/2;this.startRotationAngle=Math.atan2(o-c,a-s),this.startCameraAngle=this.renderer.getCamera().getState().angle,this.isRightMouseDown=!0}this.emit(`mousedown`,Vs(e,this.container))}}},{key:`handleUp`,value:function(e){var t=this;if(this.enabled&&!Xs(e)&&(this.isMouseDown||this.isRightMouseDown)){if(this.isRightMouseDown)this.isRightMouseDown=!1,this.startRotationAngle=null,this.startCameraAngle=null,this.emit(`mouseup`,Vs(e,this.container));else{var n=this.renderer.getCamera();this.isMouseDown=!1,this.isPanningStage&&(this.isPanningStage=!1,this.renderer._setPanning(!1)),typeof this.movingTimeout==`number`&&(clearTimeout(this.movingTimeout),this.movingTimeout=null);var r=Bs(e,this.container),i=r.x,a=r.y,o=n.getState(),s=n.getPreviousState();this.isMoving?n.animate({x:o.x+this.settings.inertiaRatio*(o.x-s.x),y:o.y+this.settings.inertiaRatio*(o.y-s.y)},{duration:this.settings.inertiaDuration,easing:`quadraticOut`}):(this.lastMouseX!==i||this.lastMouseY!==a)&&n.setState({x:o.x,y:o.y}),this.isMoving=!1,setTimeout(function(){var e=t.draggedEvents>0;t.draggedEvents=0;var n=t.renderer.getSetting(`hideEdgesOnMove`)||t.renderer.getSetting(`hideLabelsOnMove`);e&&n&&t.renderer.refresh()},0),this.emit(`mouseup`,Vs(e,this.container)),(e.target===this.container||e.composedPath()[0]===this.container)&&this.handleClick(e)}}}},{key:`handleMove`,value:function(e){var t=this;if(this.enabled&&!Xs(e)){var n=Vs(e,this.container);if(this.emit(`mousemovebody`,n),(e.target===this.container||e.composedPath()[0]===this.container)&&this.emit(`mousemove`,n),this.isMouseDown&&this.draggedEvents++,!n.sigmaDefaultPrevented){if(this.isMouseDown){this.isMoving=!0,typeof this.movingTimeout==`number`&&clearTimeout(this.movingTimeout),this.movingTimeout=window.setTimeout(function(){t.movingTimeout=null,t.isMoving=!1},this.settings.dragTimeout);var r=this.renderer.getCamera(),i=Bs(e,this.container),a=i.x,o=i.y,s=this.renderer.viewportToFramedGraph({x:this.lastMouseX,y:this.lastMouseY}),c=this.renderer.viewportToFramedGraph({x:a,y:o}),l=s.x-c.x,u=s.y-c.y,d=r.getState(),f=d.x+l,p=d.y+u;this.isPanningStage||(this.isPanningStage=!0,this.renderer._setPanning(!0)),r.setState({x:f,y:p}),this.lastMouseX=a,this.lastMouseY=o,e.preventDefault(),e.stopPropagation()}if(this.isRightMouseDown){var m=Bs(e,this.container),h=m.x,g=m.y,_=this.container.offsetWidth/2,v=this.container.offsetHeight/2,y=Math.atan2(g-v,h-_)-this.startRotationAngle;this.renderer.getCamera().setState({angle:this.startCameraAngle+y}),e.preventDefault(),e.stopPropagation()}}}}},{key:`handleLeave`,value:function(e){Xs(e)||this.emit(`mouseleave`,Vs(e,this.container))}},{key:`handleEnter`,value:function(e){Xs(e)||this.emit(`mouseenter`,Vs(e,this.container))}},{key:`handleWheel`,value:function(e){var t=this,n=this.renderer.getCamera();if(this.enabled&&n.enabledZooming){var r=Us(e,this.container);if(this.emit(`wheel`,r),!r.sigmaDefaultPrevented){var i=this.settings.gestureTarget;if(i!==`page`){if(i===`shared`&&!e.ctrlKey&&!e.metaKey)this.renderer._showGestureHint(`wheel`);else{var a=qs(e);if(a){e.preventDefault(),e.stopPropagation();var o=n.getState().ratio,s=a>0?1/this.settings.zoomingRatio:this.settings.zoomingRatio,c=n.getBoundedRatio(o*s),l=a>0?1:-1,u=Date.now();if(o!==c&&!(this.currentWheelDirection===l&&this.lastWheelTriggerTime&&u-this.lastWheelTriggerTime<this.settings.zoomDuration/5)){var d=++this.lastWheelAnimationId;n.animate(this.renderer.getViewportZoomedState(Bs(e,this.container),c),{easing:`quadraticOut`,duration:this.settings.zoomDuration}).then(function(){t.lastWheelAnimationId===d&&(t.currentWheelDirection=0)}),this.currentWheelDirection=l,this.lastWheelTriggerTime=u}}}}}}}},{key:`setSettings`,value:function(e){this.settings=e}}])}(Js),Qs=[`dragTimeout`,`gestureTarget`,`inertiaDuration`,`inertiaRatio`,`doubleClickTimeout`,`doubleClickZoomingRatio`,`doubleClickZoomingDuration`,`tapMoveTolerance`].reduce(function(e,t){return W(W({},e),{},U({},t,Hr[t]))},{}),$s=function(e){function t(e,n){var r;return G(this,t),r=q(this,t,[e,n]),U(r,`enabled`,!0),U(r,`isMoving`,!1),U(r,`hasMoved`,!1),U(r,`isPanningStage`,!1),U(r,`isZoomingStage`,!1),U(r,`touchMode`,0),U(r,`startTouchesPositions`,[]),U(r,`lastTouches`,[]),U(r,`lastTap`,null),U(r,`settings`,Qs),r.handleStart=r.handleStart.bind(r),r.handleLeave=r.handleLeave.bind(r),r.handleMove=r.handleMove.bind(r),e.addEventListener(`touchstart`,r.handleStart,{capture:!1}),e.addEventListener(`touchcancel`,r.handleLeave,{capture:!1}),document.addEventListener(`touchend`,r.handleLeave,{capture:!1,passive:!1}),document.addEventListener(`touchmove`,r.handleMove,{capture:!1,passive:!1}),r}return J(t,e),K(t,[{key:`kill`,value:function(){var e=this.container;e.removeEventListener(`touchstart`,this.handleStart),e.removeEventListener(`touchcancel`,this.handleLeave),document.removeEventListener(`touchend`,this.handleLeave),document.removeEventListener(`touchmove`,this.handleMove)}},{key:`getDimensions`,value:function(){return{width:this.container.offsetWidth,height:this.container.offsetHeight}}},{key:`doesCapture`,value:function(e){var t=this.settings.gestureTarget;return t===`graph`||t!==`page`&&e>=2}},{key:`syncStageFlags`,value:function(){var e=this.touchMode===1&&this.hasMoved,t=this.touchMode===2;e!==this.isPanningStage&&(this.isPanningStage=e,this.renderer._setPanning(e)),t!==this.isZoomingStage&&(this.isZoomingStage=t,this.renderer._setZooming(t))}},{key:`handleStart`,value:function(e){var t=this;if(this.enabled){var n=Gs(e.touches);if(this.touchMode=n.length,this.startCameraState=this.renderer.getCamera().getState(),this.startTouchesPositions=n.map(function(e){return Bs(e,t.container)}),this.touchMode===2){var r=V(this.startTouchesPositions,2),i=r[0],a=i.x,o=i.y,s=r[1],c=s.x,l=s.y;this.startTouchesAngle=Math.atan2(l-o,c-a),this.startTouchesDistance=Math.sqrt((c-a)**2+(l-o)**2)}this.syncStageFlags(),this.emit(`touchdown`,Ks(e,this.lastTouches,this.container)),this.lastTouches=n,this.lastTouchesPositions=this.startTouchesPositions,e.cancelable&&(this.doesCapture(e.touches.length)||this.renderer._hasNodeDrag())&&e.preventDefault()}}},{key:`handleLeave`,value:function(e){if(this.enabled&&this.startTouchesPositions.length){switch(e.cancelable&&this.doesCapture(this.touchMode)&&e.preventDefault(),this.movingTimeout&&(this.isMoving=!1,clearTimeout(this.movingTimeout)),this.touchMode){case 2:if(e.touches.length===1){this.handleStart(e);break}case 1:if(this.isMoving){var t=this.renderer.getCamera(),n=t.getState(),r=t.getPreviousState();t.animate({x:n.x+this.settings.inertiaRatio*(n.x-r.x),y:n.y+this.settings.inertiaRatio*(n.y-r.y)},{duration:this.settings.inertiaDuration,easing:`quadraticOut`})}this.hasMoved=!1,this.isMoving=!1,this.touchMode=0}if(this.syncStageFlags(),this.emit(`touchup`,Ks(e,this.lastTouches,this.container)),!e.touches.length){var i=Bs(this.lastTouches[0],this.container),a=this.startTouchesPositions[0],o=(i.x-a.x)**2+(i.y-a.y)**2;if(!e.touches.length&&o<this.settings.tapMoveTolerance**2){if(this.lastTap&&Date.now()-this.lastTap.time<this.settings.doubleClickTimeout){var s=Ks(e,this.lastTouches,this.container);if(this.emit(`doubletap`,s),this.lastTap=null,!s.sigmaDefaultPrevented&&this.settings.gestureTarget!==`page`){var c=this.renderer.getCamera(),l=c.getBoundedRatio(c.getState().ratio/this.settings.doubleClickZoomingRatio);c.animate(this.renderer.getViewportZoomedState(i,l),{easing:`quadraticInOut`,duration:this.settings.doubleClickZoomingDuration})}}else{var u=Ks(e,this.lastTouches,this.container);this.emit(`tap`,u),this.lastTap={time:Date.now(),position:u.touches[0]||u.previousTouches[0]}}}}this.lastTouches=Gs(e.touches),this.startTouchesPositions=[]}}},{key:`handleMove`,value:function(e){var t=this;if(this.enabled&&this.startTouchesPositions.length){var n=this.doesCapture(e.touches.length);n&&e.preventDefault();var r=Gs(e.touches),i=r.map(function(e){return Bs(e,t.container)}),a=this.lastTouches;this.lastTouches=r,this.lastTouchesPositions=i;var o=Ks(e,a,this.container);if(this.emit(`touchmove`,o),!o.sigmaDefaultPrevented&&(this.hasMoved||=i.some(function(e,n){var r=t.startTouchesPositions[n];return r&&(e.x!==r.x||e.y!==r.y)}),this.hasMoved)){if(!n)this.settings.gestureTarget===`shared`&&this.renderer._showGestureHint(`touch`);else{this.isMoving=!0,this.syncStageFlags(),this.movingTimeout&&clearTimeout(this.movingTimeout),this.movingTimeout=window.setTimeout(function(){t.isMoving=!1},this.settings.dragTimeout);var s=this.renderer.getCamera(),c=this.startCameraState,l=this.renderer.getSetting(`stagePadding`);switch(this.touchMode){case 1:var u=this.renderer.viewportToFramedGraph((this.startTouchesPositions||[])[0]),d=u.x,f=u.y,p=this.renderer.viewportToFramedGraph(i[0]),m=p.x,h=p.y;s.setState({x:c.x+d-m,y:c.y+f-h});break;case 2:var g={x:.5,y:.5,angle:0,ratio:1},_=i[0],v=_.x,y=_.y,b=i[1],x=b.x,S=b.y,C=Math.atan2(S-y,x-v)-this.startTouchesAngle,w=Math.hypot(S-y,x-v)/this.startTouchesDistance,T=s.getBoundedRatio(c.ratio/w);g.ratio=T,g.angle=c.angle+C;var E=this.getDimensions(),D=this.renderer.viewportToFramedGraph((this.startTouchesPositions||[])[0],{cameraState:c}),O=Math.min(E.width,E.height)-2*l,k=O/E.width,A=O/E.height,j=T/O,M=v-O/2/k,N=y-O/2/A,P=Ut({x:M,y:N},g.angle);M=P.x,N=P.y,g.x=D.x-M*j,g.y=D.y+N*j,s.setState(g)}}}}}},{key:`setSettings`,value:function(e){this.settings=e}}])}(Js),ec=function(){function e(t,n,r,i){G(this,e),U(this,`pendingNode`,null),U(this,`session`,null),this.graph=t,this.viewportToGraph=n,this.setNodesState=r,this.emit=i}return K(e,[{key:`start`,value:function(e,t,n,r,i){var a=n(e),o=!1;if(this.emit(`nodeDragStart`,{node:e,allDraggedNodes:a,event:t,preventSigmaDefault:function(){o=!0}}),o)return!1;var s=new Map,c=H(a),l;try{for(c.s();!(l=c.n()).done;){var u=l.value;s.set(u,{x:this.graph.getNodeAttribute(u,r),y:this.graph.getNodeAttribute(u,i)})}}catch(e){c.e(e)}finally{c.f()}return this.session={node:e,allNodes:a,startPosition:this.viewportToGraph(t),startNodePositions:s,xAttr:r,yAttr:i},this.setNodesState(a,{isDragged:!0}),!0}},{key:`applyMove`,value:function(e,t){var n=this.session,r=n.allNodes,i=n.startNodePositions,a=n.startPosition,o=n.xAttr,s=n.yAttr,c=this.viewportToGraph(e),l={x:c.x-a.x,y:c.y-a.y},u=H(r),d;try{for(u.s();!(d=u.n()).done;){var f=d.value,p=i.get(f);if(p&&this.graph.hasNode(f)){var m={x:p.x+l.x,y:p.y+l.y};t?this.graph.mergeNodeAttributes(f,t(m,f)):(this.graph.setNodeAttribute(f,o,m.x),this.graph.setNodeAttribute(f,s,m.y))}}}catch(e){u.e(e)}finally{u.f()}}},{key:`end`,value:function(){if(this.pendingNode=null,!this.session)return null;var e=this.session,t=e.node,n=e.allNodes;return this.setNodesState(n,{isDragged:!1}),this.session=null,{node:t,allNodes:n}}},{key:`removeNode`,value:function(e){e===this.pendingNode&&(this.pendingNode=null),this.session&&(this.session.node===e?(this.setNodesState(this.session.allNodes,{isDragged:!1}),this.session=null):this.session.allNodes.includes(e)&&(this.session.allNodes=this.session.allNodes.filter(function(t){return t!==e}),this.session.startNodePositions.delete(e)))}},{key:`clear`,value:function(){this.pendingNode=null,this.session=null}}])}(),tc=function(){function e(t,n){G(this,e),U(this,`groups`,new Map),U(this,`edgeToGroupKey`,new Map),this.graph=t,this.onGroupChanged=n}return K(e,[{key:`getGroupKey`,value:function(e){var t=this.graph.source(e),n=this.graph.target(e);return t<n?`${t}${n}`:`${n}${t}`}},{key:`sortGroup`,value:function(e,t){var n=this,r=t.split(`\0`)[0];e.sort(function(e,t){return(n.graph.source(e)===r||!n.graph.isDirected(e)?0:1)-(n.graph.source(t)===r||!n.graph.isDirected(t)?0:1)})}},{key:`register`,value:function(e){var t=this.getGroupKey(e),n=this.groups.get(t);n||(n=[],this.groups.set(t,n)),n.includes(e)||n.push(e),this.edgeToGroupKey.set(e,t),this.sortGroup(n,t),this.onGroupChanged(n,n.length)}},{key:`unregister`,value:function(e){var t=this.edgeToGroupKey.get(e);if(t){this.edgeToGroupKey.delete(e);var n=this.groups.get(t);if(n){var r=n.indexOf(e);r!==-1&&n.splice(r,1),n.length===0?this.groups.delete(t):this.onGroupChanged(n,n.length)}}}},{key:`getGroup`,value:function(e){var t=this.edgeToGroupKey.get(e);return t?this.groups.get(t)??[]:[]}},{key:`getSiblings`,value:function(e){return this.getGroup(e).filter(function(t){return t!==e})}},{key:`rebuild`,value:function(){var e=this;this.groups.clear(),this.edgeToGroupKey.clear(),this.graph.forEachEdge(function(t){var n=e.getGroupKey(t),r=e.groups.get(n);r||(r=[],e.groups.set(n,r)),r.push(t),e.edgeToGroupKey.set(t,n)});var t=H(this.groups),n;try{for(t.s();!(n=t.n()).done;){var r=V(n.value,2),i=r[0],a=r[1];this.sortGroup(a,i),this.onGroupChanged(a,a.length)}}catch(e){t.e(e)}finally{t.f()}}},{key:`clear`,value:function(){this.groups.clear(),this.edgeToGroupKey.clear()}}])}();function nc(e,t){if(e===!1||e===`extend`||e===`separate`)return e;var n=e[t];return n===void 0?e.default??!1:n}function rc(e){return e===!1?!1:e===`extend`||e===`separate`||Object.values(e).some(function(e){return e===`extend`||e===`separate`})}function ic(e){return e===`separate`?!0:e===!1||e===`extend`?!1:e.default===`separate`||Object.values(e).includes(`separate`)}var $={node:{parent:null,eventSuffix:`Node`,payloadKey:`node`,isEnabled:function(){return!0},writesPickingThisFrame:function(){return!0},setHover:function(e,t,n){return e.setNodeState(t,{isHovered:n})},getCursor:function(e,t){return e.nodeDataCache[t]?.cursor},isHitValid:function(e,t){return e.nodeDataCache[t]?.visibility!==`hidden`}},edge:{parent:null,eventSuffix:`Edge`,payloadKey:`edge`,isEnabled:function(e){return!!e.settings.enableEdgeEvents},writesPickingThisFrame:function(e){return!!e.settings.enableEdgeEvents},setHover:function(e,t,n){return e.setEdgeState(t,{isHovered:n})},getCursor:function(e,t){return e.edgeDataCache[t]?.cursor}},nodeLabel:{parent:`node`,eventSuffix:`NodeLabel`,payloadKey:`node`,isEnabled:function(e){return ic(e.settings.nodeLabelEvents)},writesPickingThisFrame:function(e){return rc(e.settings.nodeLabelEvents)},setHover:function(e,t,n){return e.setNodeState(t,{isLabelHovered:n})},getCursor:function(e,t){return e.nodeDataCache[t]?.labelCursor},resolveForVerb:function(e,t,n){var r=nc(n.settings.nodeLabelEvents,t);return r===!1?null:r===`extend`?{kind:`node`,key:e.key}:e}},edgeLabel:{parent:`edge`,eventSuffix:`EdgeLabel`,payloadKey:`edge`,isEnabled:function(e){return ic(e.settings.edgeLabelEvents)},writesPickingThisFrame:function(e){return rc(e.settings.edgeLabelEvents)},setHover:function(e,t,n){return e.setEdgeState(t,{isLabelHovered:n})},getCursor:function(e,t){return e.edgeDataCache[t]?.labelCursor},resolveForVerb:function(e,t,n){var r=nc(n.settings.edgeLabelEvents,t);return r===!1?null:r===`extend`?{kind:`edge`,key:e.key}:e}}},ac=[`node`,`edge`,`nodeLabel`,`edgeLabel`];function oc(){return{lookup:[null],idsByKind:{node:new Map,edge:new Map,nodeLabel:new Map,edgeLabel:new Map},nextId:1}}function sc(e,t,n){return e.idsByKind[t].get(n)??0}function cc(e,t){var n=H(ac),r;try{for(n.s();!(r=n.n()).done;){var i=r.value;if(i===t||$[i].parent===t){var a=H(e.idsByKind[i].values()),o;try{for(a.s();!(o=a.n()).done;){var s=o.value;e.lookup[s]=null}}catch(e){a.e(e)}finally{a.f()}e.idsByKind[i]=new Map}}}catch(e){n.e(e)}finally{n.f()}var c=1,l=H(ac),u;try{for(l.s();!(u=l.n()).done;){var d=u.value;if(d===t)break;c+=e.idsByKind[d].size}}catch(e){l.e(e)}finally{l.f()}e.nextId=c}function lc(e,t,n){var r=e.nextId++;return e.idsByKind[t].set(n,r),e.lookup[r]={kind:t,key:n},r}function uc(e,t){var n=H(ac),r;try{for(n.s();!(r=n.n()).done;){var i=r.value;if($[i].parent!==null){var a=H(e.idsByKind[i].values()),o;try{for(a.s();!(o=a.n()).done;){var s=o.value;e.lookup[s]=null}}catch(e){a.e(e)}finally{a.f()}e.idsByKind[i]=new Map}}}catch(e){n.e(e)}finally{n.f()}e.nextId=1;var c=H(ac),l;try{for(c.s();!(l=c.n()).done;){var u=l.value;if($[u].parent===null){var d=H(e.idsByKind[u].values()),f;try{for(d.s();!(f=d.n()).done;){var p=f.value;p>=e.nextId&&(e.nextId=p+1)}}catch(e){d.e(e)}finally{d.f()}}}}catch(e){c.e(e)}finally{c.f()}var m=H(ac),h;try{for(m.s();!(h=m.n()).done;){var g=h.value,_=$[g];if(_.parent!==null&&_.isEnabled(t)){var v=H(e.idsByKind[_.parent].keys()),y;try{for(v.s();!(y=v.n()).done;){var b=y.value;e.idsByKind[g].set(b,e.nextId),e.lookup[e.nextId]={kind:g,key:b},e.nextId++}}catch(e){v.e(e)}finally{v.f()}}}}catch(e){m.e(e)}finally{m.f()}}function dc(e,t){var n=H(ac),r;try{for(n.s();!(r=n.n()).done;){var i=r.value,a=e[i],o=t[i];if(a!==o){if(a.size!==o.size)return!1;var s=H(a),c;try{for(s.s();!(c=s.n()).done;){var l=V(c.value,2),u=l[0],d=l[1];if(o.get(u)!==d)return!1}}catch(e){s.e(e)}finally{s.f()}}}}catch(e){n.e(e)}finally{n.f()}return!0}function fc(e,t,n){$[t.kind].setHover(e,t.key,n)}function pc(e,t){return $[t.kind].getCursor(e,t.key)}function mc(e,t){return`${t}${$[e].eventSuffix}`}function hc(e,t){return W(W({},t),{},U({},$[e.kind].payloadKey,e.key))}function gc(e,t,n){var r=$[t.kind].resolveForVerb;return r?r(t,n,e):t}function _c(e,t){var n=$[t.kind].isHitValid;return!n||n(e,t.key)}function vc(e){return ac.filter(function(t){return t===e||$[t].parent===e})}function yc(e,t,n){return t&&=gc(e,t,n),t&&!_c(e,t)&&(t=null),t}function bc(e,t,n){return yc(e,n===`wheel`?e.stateManager.hovered:e.getHitAtPosition(t),n)}function xc(e,t){return!e||!t?e===t:e.kind===t.kind&&e.key===t.key}function Sc(e,t,n){var r={event:n,preventSigmaDefault:function(){return n.preventSigmaDefault()}},i=e.dragManager.session,a=i?{kind:`node`,key:i.node}:yc(e,t,`enter`),o=e.stateManager,s=o.hovered;xc(s,a)||(s&&(fc(e,s,!1),e.emit(mc(s.kind,`leave`),hc(s,r))),o.setHovered(a),a&&(fc(e,a,!0),e.emit(mc(a.kind,`enter`),hc(a,r))),e.updateContainerCursor())}function Cc(e,t,n,r){r.handleResize=function(){return e.scheduleRefresh()},window.addEventListener(`resize`,r.handleResize),r.handleMove=function(t){e.hoverResolver.pointerMoved(Hs(t))},r.handleMoveBody=function(t){var n=Hs(t),r=e.dragManager;if(r.pendingNode&&!r.session){var i=e.nodeStyleAnalysis,a=i.xAttribute,o=i.yAttribute,s=e.settings;r.start(r.pendingNode,n,s.getDraggedNodes,a||`x`,o||`y`),r.pendingNode=null}r.session&&(r.applyMove(n,e.settings.dragPositionToAttributes),e.emit(`nodeDrag`,{node:r.session.node,allDraggedNodes:r.session.allNodes,event:n}),n.preventSigmaDefault()),e.emit(`moveBody`,{event:n,preventSigmaDefault:function(){return n.preventSigmaDefault()}})},r.handleLeave=function(t){var n=Hs(t),r={event:n,preventSigmaDefault:function(){return n.preventSigmaDefault()}};e.hoverResolver.pointerLeft(),Sc(e,null,n),e.emit(`leaveStage`,r)},r.handleEnter=function(t){var n=Hs(t);e.emit(`enterStage`,{event:n,preventSigmaDefault:function(){return n.preventSigmaDefault()}})};var i=function(t){return function(n){var r=Hs(n),i={event:r,preventSigmaDefault:function(){return r.preventSigmaDefault()}},a=bc(e,r,t);a?e.emit(mc(a.kind,t),hc(a,i)):e.emit(`${t}Stage`,i)}};r.handleClick=i(`click`),r.handleRightClick=i(`rightClick`),r.handleDoubleClick=i(`doubleClick`),r.handleWheel=i(`wheel`),r.handleDown=function(t){var n=Hs(t),r={event:n,preventSigmaDefault:function(){return n.preventSigmaDefault()}},i=bc(e,n,`down`);i?(i.kind===`node`&&e.settings.enableNodeDrag&&(e.dragManager.pendingNode=i.key),e.emit(mc(i.kind,`down`),hc(i,r))):e.emit(`downStage`,r)},r.handleUp=function(t){var n=Hs(t),r={event:n,preventSigmaDefault:function(){return n.preventSigmaDefault()}},i=e.dragManager.end();i&&e.emit(`nodeDragEnd`,W({node:i.node,allDraggedNodes:i.allNodes},r));var a=bc(e,n,`up`);a?e.emit(mc(a.kind,`up`),hc(a,r)):e.emit(`upStage`,r)},t.on(`mousemove`,r.handleMove),t.on(`mousemovebody`,r.handleMoveBody),t.on(`click`,r.handleClick),t.on(`rightClick`,r.handleRightClick),t.on(`doubleClick`,r.handleDoubleClick),t.on(`wheel`,r.handleWheel),t.on(`mousedown`,r.handleDown),t.on(`mouseup`,r.handleUp),t.on(`mouseleave`,r.handleLeave),t.on(`mouseenter`,r.handleEnter),n.on(`touchdown`,r.handleDown),n.on(`touchdown`,r.handleMove),n.on(`touchup`,r.handleUp),n.on(`touchmove`,r.handleMove),n.on(`tap`,r.handleClick),n.on(`doubletap`,r.handleDoubleClick),n.on(`touchmove`,r.handleMoveBody)}function wc(e,t){var n=e.graph,r=new Set([`x`,`y`,`zIndex`,`type`]);t.eachNodeAttributesUpdatedGraphUpdate=function(t){var i=t.hints?.attributes,a=!i||i.some(function(e){return r.has(e)});e.refresh({partialGraph:{nodes:n.nodes()},skipIndexation:!a,schedule:!0})},t.eachEdgeAttributesUpdatedGraphUpdate=function(t){var r=t.hints?.attributes,i=r&&[`zIndex`,`type`].some(function(e){return r?.includes(e)});e.refresh({partialGraph:{edges:n.edges()},skipIndexation:!i,schedule:!0})},t.addNodeGraphUpdate=function(t){e.addNode(t.key),e.refresh({partialGraph:{nodes:[t.key]},skipIndexation:!1,schedule:!0})},t.updateNodeGraphUpdate=function(t){e.refresh({partialGraph:{nodes:[t.key]},skipIndexation:!1,schedule:!0})},t.dropNodeGraphUpdate=function(t){e.removeNode(t.key),e.refresh({schedule:!0})},t.addEdgeGraphUpdate=function(t){var n=t.key;e.edgeGroups.register(n),e.addEdge(n);var r=e.edgeGroups.getSiblings(n),i=H(r),a;try{for(i.s();!(a=i.n()).done;){var o=a.value;e.addEdge(o)}}catch(e){i.e(e)}finally{i.f()}e.refresh({partialGraph:{edges:[n].concat(Y(r))},schedule:!0})},t.updateEdgeGraphUpdate=function(t){e.refresh({partialGraph:{edges:[t.key]},skipIndexation:!1,schedule:!0})},t.dropEdgeGraphUpdate=function(t){var n=t.key,r=e.edgeGroups.getSiblings(n);e.edgeGroups.unregister(n),e.removeEdge(n);var i=H(r),a;try{for(i.s();!(a=i.n()).done;){var o=a.value;e.addEdge(o)}}catch(e){i.e(e)}finally{i.f()}e.refresh({schedule:!0})},t.clearEdgesGraphUpdate=function(){e.clearEdgeState(),e.clearEdgeIndices(),e.refresh({schedule:!0})},t.clearGraphUpdate=function(){e.clearEdgeState(),e.clearNodeState(),e.clearEdgeIndices(),e.clearNodeIndices(),e.refresh({schedule:!0})},n.on(`nodeAdded`,t.addNodeGraphUpdate),n.on(`nodeDropped`,t.dropNodeGraphUpdate),n.on(`nodeAttributesUpdated`,t.updateNodeGraphUpdate),n.on(`eachNodeAttributesUpdated`,t.eachNodeAttributesUpdatedGraphUpdate),n.on(`edgeAdded`,t.addEdgeGraphUpdate),n.on(`edgeDropped`,t.dropEdgeGraphUpdate),n.on(`edgeAttributesUpdated`,t.updateEdgeGraphUpdate),n.on(`eachEdgeAttributesUpdated`,t.eachEdgeAttributesUpdatedGraphUpdate),n.on(`edgesCleared`,t.clearEdgesGraphUpdate),n.on(`cleared`,t.clearGraphUpdate)}function Tc(e,t){e.removeListener(`nodeAdded`,t.addNodeGraphUpdate),e.removeListener(`nodeDropped`,t.dropNodeGraphUpdate),e.removeListener(`nodeAttributesUpdated`,t.updateNodeGraphUpdate),e.removeListener(`eachNodeAttributesUpdated`,t.eachNodeAttributesUpdatedGraphUpdate),e.removeListener(`edgeAdded`,t.addEdgeGraphUpdate),e.removeListener(`edgeDropped`,t.dropEdgeGraphUpdate),e.removeListener(`edgeAttributesUpdated`,t.updateEdgeGraphUpdate),e.removeListener(`eachEdgeAttributesUpdated`,t.eachEdgeAttributesUpdatedGraphUpdate),e.removeListener(`edgesCleared`,t.clearEdgesGraphUpdate),e.removeListener(`cleared`,t.clearGraphUpdate)}var Ec={x:.5,y:.5,angle:0,ratio:1},Dc=8,Oc=.001;function kc(e){var t=e.coords,n=e.nodeData,r=e.dimensions,i=e.stagePadding,a=e.zoomToSizeRatioFunction,o=e.itemSizesReference,s=e.fitLabels,c=e.nodeLabelBox,l=Object.keys(t);if(!l.length)return e.extent;for(var u=a(1)||1,d=o===`positions`,f=r.width,p=r.height,m=e.extent,h=0;h<Dc;h++){for(var g=Vr(m),_=Kt(Ec,r,{width:m.x[1]-m.x[0]||1,height:m.y[1]-m.y[0]||1},i),v=Ac(_,g({x:0,y:0}),f,p),y=Ac(_,g({x:1,y:0}),f,p),b=Math.hypot(y.x-v.x,y.y-v.y)||1,x=1/0,S=-1/0,C=1/0,w=-1/0,T=0,E=l.length;T<E;T++){var D=l[T],O=n[D],k=O.size/u*(d?b:1),A=-k,j=k,M=-k,N=k;if(s){var P=c(O,k);P&&(P.minX<A&&(A=P.minX),P.maxX>j&&(j=P.maxX),P.minY<M&&(M=P.minY),P.maxY>N&&(N=P.maxY))}var F=t[D],I=F.x,L=F.y;x=Math.min(x,I+A/b),S=Math.max(S,I+j/b),C=Math.min(C,L-N/b),w=Math.max(w,L-M/b)}var R={x:[x,S],y:[C,w]},z=Math.max(R.x[1]-R.x[0],R.y[1]-R.y[0])||1,ee=Math.max(Math.abs(R.x[0]-m.x[0]),Math.abs(R.x[1]-m.x[1]),Math.abs(R.y[0]-m.y[0]),Math.abs(R.y[1]-m.y[1]));if(m=R,ee/z<Oc)break}return m}function Ac(e,t,n,r){var i=Wt(e,t);return{x:(1+i.x)*n/2,y:(1-i.y)*r/2}}var jc=typeof navigator<`u`&&/Mac|iP(hone|ad|od)/.test(navigator.platform),Mc=1500,Nc=`.sigma-gesture-hint {
|
|
3209
|
+
position: absolute;
|
|
3210
|
+
inset: 0;
|
|
3211
|
+
display: flex;
|
|
3212
|
+
align-items: center;
|
|
3213
|
+
justify-content: center;
|
|
3214
|
+
text-align: center;
|
|
3215
|
+
padding: 1em;
|
|
3216
|
+
background: #00000066;
|
|
3217
|
+
color: #ffffff;
|
|
3218
|
+
font-size: 1em;
|
|
3219
|
+
pointer-events: none;
|
|
3220
|
+
transition: opacity 0.1s;
|
|
3221
|
+
}`;function Pc(e){var t=Jr(`style`);t.textContent=e,document.head.appendChild(t);var n=(t.sheet?.cssRules.length??0)>0;return t.remove(),n}var Fc=null;function Ic(){return Fc===null&&(Fc=Nc,Pc(`@scope {}`)&&(Fc=`@scope {
|
|
3222
|
+
${Fc}
|
|
3223
|
+
}`),Pc(`@layer sigma-gesture-hint {}`)&&(Fc=`@layer sigma-gesture-hint {
|
|
3224
|
+
${Fc}
|
|
3225
|
+
}`)),Fc}var Lc=function(){function e(t){G(this,e),U(this,`hideTimeout`,null),this.styleElement=Jr(`style`),this.styleElement.textContent=Ic(),t.appendChild(this.styleElement),this.element=Jr(`div`,{opacity:`0`},{class:`sigma-gesture-hint`}),t.appendChild(this.element)}return K(e,[{key:`show`,value:function(e,t){var n=this,r=e===`touch`?t.sharedGestureTouchMessage:jc?t.sharedGestureAppleWheelMessage:t.sharedGestureWheelMessage;r&&(this.element.textContent=r,this.element.style.opacity=`1`,typeof this.hideTimeout==`number`&&clearTimeout(this.hideTimeout),this.hideTimeout=window.setTimeout(function(){n.hideTimeout=null,n.element.style.opacity=`0`},Mc))}},{key:`kill`,value:function(){typeof this.hideTimeout==`number`&&clearTimeout(this.hideTimeout),this.styleElement.remove(),this.element.remove()}}])}(),Rc=function(){function e(t){G(this,e),U(this,`readBuffer`,null),U(this,`fence`,null),U(this,`result`,new Uint8Array(4)),U(this,`generation`,0),U(this,`readGeneration`,0),U(this,`lastEvent`,null),U(this,`active`,!1),U(this,`dirty`,!1),U(this,`rafId`,null),U(this,`killed`,!1),this.options=t}return K(e,[{key:`pointerMoved`,value:function(e){this.lastEvent=e,this.active=!0,!this.options.isRenderPending()&&this.request()}},{key:`pointerLeft`,value:function(){this.active=!1,this.dirty=!1}},{key:`frameRendered`,value:function(){this.request()}},{key:`invalidate`,value:function(){this.generation++}},{key:`request`,value:function(){!this.killed&&this.active&&this.lastEvent&&(this.fence?this.dirty=!0:this.startRead())}},{key:`startRead`,value:function(){var e=this.options,t=e.gl,n=e.getFrameBuffer,r=e.getPixelRatio,i=e.getDownSizingRatio;this.readGeneration=this.generation;var a=this.lastEvent,o=V(Jt(t,a.x,a.y,r(),i()),2),s=o[0],c=o[1];this.readBuffer||=t.createBuffer(),t.bindFramebuffer(t.FRAMEBUFFER,n()),t.bindBuffer(t.PIXEL_PACK_BUFFER,this.readBuffer),t.bufferData(t.PIXEL_PACK_BUFFER,4,t.STREAM_READ),t.readPixels(s,c,1,1,t.RGBA,t.UNSIGNED_BYTE,0),t.bindBuffer(t.PIXEL_PACK_BUFFER,null),t.bindFramebuffer(t.FRAMEBUFFER,null),this.fence=t.fenceSync(t.SYNC_GPU_COMMANDS_COMPLETE,0),t.flush(),this.schedulePoll(a)}},{key:`schedulePoll`,value:function(e){var t=this;this.rafId=requestAnimationFrame(function(){t.rafId=null,t.poll(e)})}},{key:`poll`,value:function(e){var t=this.options,n=t.gl,r=t.onIndex;if(!this.killed&&this.fence){var i=n.clientWaitSync(this.fence,0,0);if(i===n.TIMEOUT_EXPIRED)this.schedulePoll(e);else{if(n.deleteSync(this.fence),this.fence=null,i!==n.WAIT_FAILED&&this.readGeneration===this.generation){n.bindBuffer(n.PIXEL_PACK_BUFFER,this.readBuffer),n.getBufferSubData(n.PIXEL_PACK_BUFFER,0,this.result),n.bindBuffer(n.PIXEL_PACK_BUFFER,null);var a=V(this.result,4),o=a[0],s=a[1],c=a[2],l=a[3];this.active&&r(un(o,s,c,l),e)}this.dirty&&(this.dirty=!1,this.active&&this.lastEvent&&!this.options.isRenderPending()&&this.startRead())}}}},{key:`reset`,value:function(){this.rafId!==null&&cancelAnimationFrame(this.rafId),this.rafId=null,this.fence=null,this.readBuffer=null,this.dirty=!1}},{key:`kill`,value:function(){this.killed=!0,this.rafId!==null&&cancelAnimationFrame(this.rafId),this.rafId=null;var e=this.options.gl;this.fence&&e.deleteSync(this.fence),this.fence=null,this.readBuffer&&e.deleteBuffer(this.readBuffer),this.readBuffer=null}}])}(),zc=function(){function e(t,n){G(this,e),this.key=t,this.size=n}return K(e,null,[{key:`compare`,value:function(e,t){return e.size>t.size?-1:e.size<t.size||e.key>t.key?1:-1}}])}(),Bc=function(){function e(){G(this,e),U(this,`width`,0),U(this,`height`,0),U(this,`cellSize`,0),U(this,`columns`,0),U(this,`rows`,0),U(this,`cells`,{})}return K(e,[{key:`resizeAndClear`,value:function(e,t){this.width=e.width,this.height=e.height,this.cellSize=t,this.columns=Math.ceil(e.width/t),this.rows=Math.ceil(e.height/t),this.cells={}}},{key:`getIndex`,value:function(e){var t=Math.floor(e.x/this.cellSize);return Math.floor(e.y/this.cellSize)*this.columns+t}},{key:`add`,value:function(e,t,n){var r=new zc(e,t),i=this.getIndex(n),a=this.cells[i];a||(a=[],this.cells[i]=a),a.push(r)}},{key:`organize`,value:function(){for(var e in this.cells)this.cells[e].sort(zc.compare)}},{key:`getLabelsToDisplay`,value:function(e,t,n){var r=this.cellSize*this.cellSize,i=r/e/e*t/r,a=Math.ceil(i),o=[];if(n)for(var s=Math.max(0,Math.floor(n.x1/this.cellSize)),c=Math.min(this.columns-1,Math.floor(n.x2/this.cellSize)),l=Math.max(0,Math.floor(n.y1/this.cellSize)),u=Math.min(this.rows-1,Math.floor(n.y2/this.cellSize)),d=l;d<=u;d++)for(var f=s;f<=c;f++){var p=d*this.columns+f,m=this.cells[p];if(m)for(var h=0;h<Math.min(a,m.length);h++)o.push(m[h].key)}else for(var g in this.cells)for(var _=this.cells[g],v=0;v<Math.min(a,_.length);v++)o.push(_[v].key);return o}}])}();function Vc(e){var t=e.graph,n=e.hoveredNode,r=e.highlightedNodes,i=e.displayedNodeLabels,a=new Set,o=new Set(r);n&&o.add(n);var s=H(o),c;try{for(s.s();!(c=s.n()).done;){var l=c.value;t.hasNode(l)&&t.forEachEdge(l,function(e){a.add(e)})}}catch(e){s.e(e)}finally{s.f()}var u=H(i),d;try{var f=function(){var e=d.value;if(o.has(e))return 1;t.forEachEdge(e,function(t,n,r,o){var s=r===e?o:r;i.has(s)&&a.add(t)})};for(u.s();!(d=u.n()).done;)if(f())continue}catch(e){u.e(e)}finally{u.f()}return Array.from(a)}var Hc=150,Uc=50,Wc={both:0,node:1,label:2},Gc={over:0,above:1,below:2,auto:3},Kc=12,qc=3,Jc=function(){function e(t){G(this,e),U(this,`labelGrid`,new Bc),U(this,`edgeAnchorGrid`,new Bc),U(this,`displayedNodeLabels`,new Set),U(this,`displayedEdgeLabels`,new Set),U(this,`edgeLabelCandidates`,[]),U(this,`renderedNodeLabels`,new Set),U(this,`labelSizeCache`,new Map),U(this,`framePassPoints`,new Float32Array),U(this,`labelsDirty`,!0),this.internals=t}return K(e,[{key:`resetFrame`,value:function(){this.displayedNodeLabels=new Set,this.renderedNodeLabels=new Set,this.labelSizeCache.clear()}},{key:`clearEdgeLabels`,value:function(){this.displayedEdgeLabels=new Set}},{key:`resetLabelGrid`,value:function(){this.labelGrid=new Bc,this.edgeAnchorGrid=new Bc}},{key:`processWebGLLabels`,value:function(e){for(var t,n=this.internals,r=n.labelProgram,i=n.primitives,a=n.nodeDataCache,o=(i==null||(t=i.nodes)==null||(t=t.label)==null||(t=t.font)==null?void 0:t.family)||`sans-serif`,s=new Map,c=0,l=e.length;c<l;c++){var u=a[e[c]];if(u.visibility!==`hidden`&&u.label){var d=u.labelFont||o,f=s.get(d);f?f.push(u.label):s.set(d,[u.label])}}var p=H(s),m;try{for(p.s();!(m=p.n()).done;){var h=V(m.value,2),g=h[0],_=h[1],v=qr(g),y=v.family,b=v.weight,x=v.style,S=r.registerFont(y,b,x);r.ensureGlyphsReady(_,S)}}catch(e){p.e(e)}finally{p.f()}}},{key:`measureNodeLabel`,value:function(e){var t;if(!e.label)return{width:0,height:0,textHeight:0};var n=this.internals,r=n.labelProgram,i=n.primitives,a=e.labelSize??14,o=e.labelFont||(i==null||(t=i.nodes)==null||(t=t.label)==null||(t=t.font)==null?void 0:t.family)||`sans-serif`,s=`${e.label}|${a}|${o}`;if(this.labelSizeCache.has(s))return this.labelSizeCache.get(s);var c=qr(o),l=c.family,u=c.weight,d=c.style,f=r.registerFont(l,u,d),p=r.measureLabel(e.label,a,f);return this.labelSizeCache.set(s,p),p}},{key:`nodeLabelBox`,value:function(e,t){var n;if(e.visibility===`hidden`||e.labelVisibility===`hidden`)return null;var r=this.measureNodeLabel(e),i=r.width,a=r.height,o=r.textHeight;if(!i)return null;var s=t+(((n=this.internals.primitives)==null||(n=n.nodes)==null||(n=n.label)==null?void 0:n.margin)??5),c=e.labelBackgroundColor?e.labelBackgroundPadding??3:0,l=i/2,u=a/2,d=l+c,f=u+c,p=o/2,m=0,h=0;switch(e.labelPosition??`right`){case`left`:m=-(s+l);break;case`above`:h=-(s+p);break;case`below`:h=s+p;break;case`over`:break;default:m=s+l}var g=e.labelAngle??0,_=Ut({x:m,y:h},g),v=_.x,y=_.y,b=Math.abs(Math.cos(g)),x=Math.abs(Math.sin(g)),S=b*d+x*f,C=x*d+b*f;return{minX:v-S,maxX:v+S,minY:y-C,maxY:y+C}}},{key:`computeDisplayedNodeLabels`,value:function(){var e=this.internals.getCameraState(),t=this.internals.getDimensions(),n=t.width,r=t.height,i=this.internals.viewportToFramedGraph({x:-Hc,y:-Uc}),a=this.internals.viewportToFramedGraph({x:n+Hc,y:-Uc}),o=this.internals.viewportToFramedGraph({x:-Hc,y:r+Uc}),s=this.internals.viewportToFramedGraph({x:n+Hc,y:r+Uc}),c=Math.min(i.x,a.x,o.x,s.x),l=Math.max(i.x,a.x,o.x,s.x),u=Math.min(i.y,a.y,o.y,s.y),d=Math.max(i.y,a.y,o.y,s.y),f=Kt({x:.5,y:.5,ratio:1,angle:0},{width:n,height:r},this.internals.getGraphDimensions(),this.internals.getStagePadding()),p=function(e){var t=Wt(f,e);return{x:(1+t.x)*n/2,y:(1-t.y)*r/2}},m=p({x:c,y:u}),h=p({x:l,y:u}),g=p({x:c,y:d}),_=p({x:l,y:d}),v={x1:Math.min(m.x,h.x,g.x,_.x),y1:Math.min(m.y,h.y,g.y,_.y),x2:Math.max(m.x,h.x,g.x,_.x),y2:Math.max(m.y,h.y,g.y,_.y)},y=this.internals,b=y.settings,x=y.nodeDataCache,S=y.nodesWithForcedLabels,C=this.labelGrid.getLabelsToDisplay(e.ratio,b.labelDensity,v);Or(C,S);for(var w=0,T=C.length;w<T;w++){var E=C[w],D=x[E];if(!this.displayedNodeLabels.has(E)&&D.visibility!==`hidden`&&D.labelVisibility!==`hidden`&&D.label&&!(D.x<c||D.x>l||D.y<u||D.y>d)){var O=this.internals.framedGraphToViewport(D),k=O.x,A=O.y,j=this.internals.scaleSize(D.size);!Fr(D)&&j<b.labelRenderedSizeThreshold||k<-Hc-j||k>n+Hc+j||A<-Uc-j||A>r+Uc+j||this.displayedNodeLabels.add(E)}}}},{key:`buildFramePassPoints`,value:function(){var e=this.internals,t=e.nodeDataCache,n=e.nodeDataTexture;if(!n)return{data:this.framePassPoints,count:0};var r=this.displayedNodeLabels.size*3;this.framePassPoints.length<r&&(this.framePassPoints=new Float32Array(r));var i=this.framePassPoints,a=0,o=H(this.displayedNodeLabels),s;try{for(o.s();!(s=o.n()).done;){var c=s.value,l=t[c];if(l){var u=n.getIndex(c);u<0||(i[a*3]=u,i[a*3+1]=_i[l.labelPosition||fr.labelPosition]??0,i[a*3+2]=l.labelAngle??0,a++)}}}catch(e){o.e(e)}finally{o.f()}return{data:i,count:a}}},{key:`renderWebGLLabels`,value:function(e,t){var n=this.internals,r=n.nodeDataCache,i=n.labelProgram,a=n.primitives,o=n.nodeDataTexture,s=[],c=H(this.displayedNodeLabels),l;try{for(c.s();!(l=c.n()).done;){var u=l.value;if(!this.renderedNodeLabels.has(u)){var d=r[u];t&&d.labelDepth!==t||(this.renderedNodeLabels.add(u),s.push(u))}}}catch(e){c.e(e)}finally{c.f()}if(s.length!==0){if(this.labelsDirty){for(var f,p,m=0,h=0,g=s.length;h<g;h++){var _=r[s[h]];m+=_.label.length}i.reallocate(m);for(var v=14,y=(a==null||(f=a.nodes)==null||(f=f.label)==null?void 0:f.margin)??5,b=fr.labelPosition,x=(a==null||(p=a.nodes)==null||(p=p.label)==null||(p=p.font)==null?void 0:p.family)||`sans-serif`,S=new Map,C=0,w=0,T=s.length;w<T;w++){var E=s[w],D=r[E],O=D.labelFont||x,k=S.get(O);if(k===void 0){var A=qr(O),j=A.family,M=A.weight,N=A.style;k=i.registerFont(j,M,N),S.set(O,k)}var P={text:D.label,x:D.x,y:D.y,size:D.labelSize??v,color:D.labelColor,nodeSize:D.size,margin:y,position:D.labelPosition??b,hidden:!1,forceLabel:Fr(D),type:`default`,zIndex:D.zIndex??0,parentType:`node`,parentKey:E,fontKey:k,labelAngle:D.labelAngle??0,nodeIndex:o.getIndex(E)},F=i.processLabel(E,C,P);C+=F}i.invalidateBuffers()}i.render(e)}}},{key:`renderBackdrops`,value:function(e,t){var n=this.internals,r=n.backdropProgram,i=n.nodeDataCache,a=n.nodesWithBackdrop,o=n.attachmentManager,s=n.pixelRatio,c=n.nodeDataTexture,l=[],u=H(a),d;try{for(u.s();!(d=u.n()).done;){var f=d.value,p=i[f];if(p&&p.visibility!==`hidden`&&!(t&&p.depth!==t)){var m=c?.getIndex(f)??-1;m<0||l.push({key:f,nodeIndex:m})}}}catch(e){u.e(e)}finally{u.f()}if(l.length!==0){r.reallocate(l.length);for(var h=0;h<l.length;h++){var g=l[h],_=g.key,v=g.nodeIndex,y=i[_],b=this.displayedNodeLabels.has(_),x=b?this.measureNodeLabel(y):{width:0,height:0,textHeight:0},S=x.textHeight,C=x.width,w=x.height,T=0,E=0;if(b&&y.labelAttachment&&o){var D=o.getEntry(_,y.labelAttachment);if(D){var O=y.labelAttachmentPlacement||`below`;if(O===`below`||O===`above`){var k=D.height/s;w+=k+2,C=Math.max(C,D.width/s),E=O===`below`?(k+2)/2:-(k+2)/2}else{var A=D.width/s;C+=A+2,w=Math.max(w,D.height/s),T=O===`right`?(A+2)/2:-(A+2)/2}}}var j=y.backdropColor?cn(y.backdropColor):[255,255,255,255],M=y.backdropShadowColor?cn(y.backdropShadowColor):[0,0,0,128],N=j.map(function(e){return e/255}),P=M.map(function(e){return e/255}),F=y.backdropShadowBlur??12,I=y.backdropPadding??6,L=(y.backdropBorderColor?cn(y.backdropBorderColor):[0,0,0,0]).map(function(e){return e/255}),R=y.backdropBorderWidth??0,z=y.backdropCornerRadius??0,ee=y.backdropLabelPadding??-1,te=ee<0?I:ee,ne=Wc[y.backdropArea??`both`]??0,re={key:_,nodeIndex:v,label:y.label,labelWidth:C,labelHeight:w,textHeight:S,type:`default`,position:y.labelPosition||fr.labelPosition,labelAngle:y.labelAngle??0,backdropColor:N,backdropShadowColor:P,backdropShadowBlur:F,backdropPadding:I,backdropBorderColor:L,backdropBorderWidth:R,backdropCornerRadius:z,backdropLabelPadding:te,backdropArea:ne,labelBoxOffset:[T,E]};r.processBackdrop(h,re)}r.invalidateBuffers(),r.render(e)}}},{key:`renderLabelBackgrounds`,value:function(e,t){var n=this.internals,r=n.labelBackgroundProgram,i=n.nodeDataCache,a=n.nodeDataTexture,o=$.nodeLabel.writesPickingThisFrame(this.internals),s=[],c=H(this.displayedNodeLabels),l;try{for(c.s();!(l=c.n()).done;){var u=l.value,d=i[u];d&&d.visibility!==`hidden`&&(t&&d.labelDepth!==t||(o||d.labelBackgroundColor)&&s.push(u))}}catch(e){c.e(e)}finally{c.f()}if(s.length!==0){r.reallocate(s.length);for(var f=0;f<s.length;f++){var p=s[f],m=i[p],h=a?.getIndex(p)??-1;if(!(h<0)){var g=this.measureNodeLabel(m),_=g.width,v=g.height,y=g.textHeight,b=sc(this.internals.pickingState,`nodeLabel`,p)||sc(this.internals.pickingState,`node`,p),x=m.labelBackgroundColor?sn(m.labelBackgroundColor):sn(`transparent`),S={nodeIndex:h,id:ln(b),color:x,labelWidth:_,labelHeight:v,textHeight:y,positionMode:_i[m.labelPosition||fr.labelPosition]??0,labelAngle:m.labelAngle??0,padding:m.labelBackgroundPadding??3};r.processLabelBackground(f,S)}}r.invalidateBuffers(),r.render(e)}}},{key:`cacheAttachments`,value:function(e){var t=this.internals,n=t.attachmentManager,r=t.pixelRatio,i=t.nodeDataCache,a=t.nodesWithBackdrop,o=t.graph;if(n){var s=H(a),c;try{for(s.s();!(c=s.n()).done;){var l=c.value;if(this.displayedNodeLabels.has(l)){var u=i[l];if(u&&u.visibility!==`hidden`&&!(e&&u.depth!==e)&&u.labelAttachment){var d=o.getNodeAttributes(l),f=this.measureNodeLabel(u),p={node:l,attributes:d,pixelRatio:r,labelWidth:f.width,labelHeight:f.height};n.renderAttachment(l,u.labelAttachment,p)}}}}catch(e){s.e(e)}finally{s.f()}n.regenerateAtlas()}}},{key:`renderAttachments`,value:function(e,t){var n=this.internals,r=n.attachmentManager,i=n.attachmentProgram,a=n.nodeDataCache,o=n.nodesWithBackdrop,s=n.pixelRatio,c=n.nodeDataTexture;if(r&&i){var l=0;i.reallocateAttachments(o.size);var u=H(o),d;try{for(u.s();!(d=u.n()).done;){var f=d.value;if(this.displayedNodeLabels.has(f)){var p=a[f];if(p&&p.visibility!==`hidden`&&!(t&&p.labelDepth!==t)&&p.labelAttachment){var m=r.getEntry(f,p.labelAttachment);if(m){var h=c?.getIndex(f)??-1;if(!(h<0)){var g=this.measureNodeLabel(p),_=g.width,v=g.height,y=g.textHeight,b=Yi[p.labelAttachmentPlacement||`below`]??0;i.processAttachment(l,{nodeIndex:h,atlasX:m.x,atlasY:m.y,atlasW:m.width,atlasH:m.height,attachWidth:m.width/s,attachHeight:m.height/s,positionMode:_i[p.labelPosition||fr.labelPosition]??0,attachmentPlacement:b,labelWidth:_,labelHeight:v,textHeight:y,labelAngle:p.labelAngle??0}),l++}}}}}}catch(e){u.e(e)}finally{u.f()}l!==0&&(i.reallocateAttachments(l),r.bindTexture(7),i.invalidateBuffers(),i.render(e))}}},{key:`computeDisplayedEdgeLabels`,value:function(){var e=this.internals,t=e.graph,n=e.stateManager,r=e.settings,i=e.edgesWithForcedLabels,a=n.getHighlightedNodes(),o=r.edgeLabelAnchors===`allNodes`?new Set(this.edgeAnchorGrid.getLabelsToDisplay(this.internals.getCameraState().ratio,r.labelDensity)):this.displayedNodeLabels,s=n.hovered,c=Vc({graph:t,hoveredNode:s?.kind===`node`?s.key:null,displayedNodeLabels:o,highlightedNodes:a});Or(c,i),this.edgeLabelCandidates=c,this.displayedEdgeLabels=new Set}},{key:`filterEdgeLabelsForDepth`,value:function(e){for(var t=this.internals,n=t.graph,r=t.nodeDataCache,i=t.edgeDataCache,a=[],o=new Set,s=0,c=this.edgeLabelCandidates.length;s<c;s++){var l=this.edgeLabelCandidates[s];if(!o.has(l)){o.add(l);var u=n.extremities(l),d=r[u[0]],f=r[u[1]],p=i[l];p&&d&&f&&p.visibility!==`hidden`&&p.labelVisibility!==`hidden`&&d.visibility!==`hidden`&&f.visibility!==`hidden`&&(e&&p.labelDepth!==e||p.label&&a.push(l))}}return a}},{key:`renderEdgeLabels`,value:function(e,t){var n=this.internals,r=n.graph,i=n.nodeDataCache,a=n.edgeDataCache,o=n.primitives,s=n.edgeLabelProgram,c=n.nodeDataTexture,l=n.edgeDataTexture,u=this.filterEdgeLabelsForDepth(t),d=H(u),f;try{for(d.s();!(f=d.n()).done;){var p=f.value;this.displayedEdgeLabels.add(p)}}catch(e){d.e(e)}finally{d.f()}if(u.length!==0){if(this.labelsDirty){var m,h=0,g=H(u),_;try{for(g.s();!(_=g.n()).done;){var v=_.value;h+=a[v].label.length}}catch(e){g.e(e)}finally{g.f()}s.reallocate(h);var y=(o==null||(m=o.edges)==null||(m=m.label)==null?void 0:m.margin)??5,b=`over`,x=0,S=H(u),C;try{for(S.s();!(C=S.n()).done;){var w=C.value,T=r.extremities(w),E=T[0],D=T[1],O=i[E],k=i[D],A=a[w],j=c.getIndex(E),M=c.getIndex(D),N=l.getIndex(w),P={text:A.label,x:(O.x+k.x)/2,y:(O.y+k.y)/2,size:Kc,color:A.labelColor,nodeSize:0,nodeIndex:-1,margin:y,position:A.labelPosition??b,hidden:!1,forceLabel:Fr(A),type:`default`,zIndex:A.zIndex??0,parentType:`edge`,parentKey:w,fontKey:``,labelAngle:0,sourceX:O.x,sourceY:O.y,targetX:k.x,targetY:k.y,sourceSize:O.size,targetSize:k.size,sourceShape:O.shape||`circle`,targetShape:k.shape||`circle`,edgeSize:A.size,offset:0,edgeAttributes:A,sourceNodeIndex:j,targetNodeIndex:M,edgeIndex:N},F=s.processEdgeLabel(w,x,P);x+=F}}catch(e){S.e(e)}finally{S.f()}s.invalidateBuffers()}s.render(e)}}},{key:`renderEdgeLabelBackgrounds`,value:function(e,t){var n,r=this.internals,i=r.edgeLabelBackgroundProgram,a=r.edgeLabelProgram,o=r.edgeDataCache,s=r.primitives,c=r.edgeDataTexture;if(c){var l=$.edgeLabel.writesPickingThisFrame(this.internals),u=(s==null||(n=s.edges)==null||(n=n.label)==null?void 0:n.margin)??5,d=`over`,f=this.filterEdgeLabelsForDepth(t),p=[],m=H(f),h;try{for(m.s();!(h=m.n()).done;){var g=h.value;(l||o[g].labelBackgroundColor)&&p.push(g)}}catch(e){m.e(e)}finally{m.f()}if(p.length!==0){i.reallocate(p.length);for(var _=0;_<p.length;_++){var v=p[_],y=o[v],b=y.label,x=a.measureLabelAtlasWidth(b),S=y.labelPosition??d,C=typeof S==`string`?Gc[S]??0:0,w=sc(this.internals.pickingState,`edgeLabel`,v)||sc(this.internals.pickingState,`edge`,v),T=y.labelBackgroundColor?sn(y.labelBackgroundColor):sn(`transparent`),E={edgeIndex:c.getIndex(v),baseFontSize:Kc,totalTextWidth:x,positionMode:C,margin:u,padding:y.labelBackgroundPadding??qc,color:T,id:ln(w),edgeAttributes:y};i.processEdgeLabelBackground(_,v,E)}i.invalidateBuffers(),i.render(e)}}}}])}(),Yc=function(){function e(t,n,r,i){G(this,e),U(this,`nodeStates`,new Map),U(this,`edgeStates`,new Map),U(this,`hovered`,null),U(this,`dirtyNodes`,new Set),U(this,`dirtyEdges`,new Set),U(this,`graphStateChanged`,!1),U(this,`graphStateFlagsDirty`,!1),this.scheduleRefresh=t,this.customNodeStateDefaults=n,this.customEdgeStateDefaults=r,this.customGraphStateDefaults=i,this.graphState=Qn(i)}return K(e,[{key:`getNodeState`,value:function(e){e=``+e;var t=this.nodeStates.get(e);return t||(t=Xn(this.customNodeStateDefaults),this.nodeStates.set(e,t)),t}},{key:`getEdgeState`,value:function(e){e=``+e;var t=this.edgeStates.get(e);return t||(t=Zn(this.customEdgeStateDefaults),this.edgeStates.set(e,t)),t}},{key:`getGraphState`,value:function(){return this.flushGraphStateFlags(),this.graphState}},{key:`getHighlightedNodes`,value:function(){var e=new Set,t=H(this.nodeStates),n;try{for(t.s();!(n=t.n()).done;){var r=V(n.value,2),i=r[0];r[1].isHighlighted&&e.add(i)}}catch(e){t.e(e)}finally{t.f()}return e}},{key:`setNodeState`,value:function(e,t){e=``+e;var n=this.getNodeState(e);if(Ar(n,t)){var r=W(W({},n),t);this.nodeStates.set(e,r),this.dirtyNodes.add(e),this.updateHoveredNodeTracking(e,n,r),this.graphStateFlagsDirty=!0,this.scheduleRefresh()}}},{key:`setEdgeState`,value:function(e,t){e=``+e;var n=this.getEdgeState(e);if(Ar(n,t)){var r=W(W({},n),t);this.edgeStates.set(e,r),this.dirtyEdges.add(e),this.updateHoveredEdgeTracking(e,n,r),this.graphStateFlagsDirty=!0,this.scheduleRefresh()}}},{key:`setGraphState`,value:function(e){if(Ar(this.graphState,e)){var t=W(W({},this.graphState),e);t.isIdle=!t.isPanning&&!t.isZooming&&!t.isDragging,this.graphState=t,this.graphStateChanged=!0,this.scheduleRefresh()}}},{key:`setNodesState`,value:function(e,t){var n=!1,r=H(e),i;try{for(r.s();!(i=r.n()).done;){var a=i.value;a=``+a;var o=this.getNodeState(a);if(Ar(o,t)){var s=W(W({},o),t);this.nodeStates.set(a,s),this.dirtyNodes.add(a),this.updateHoveredNodeTracking(a,o,s),n=!0}}}catch(e){r.e(e)}finally{r.f()}n&&(this.graphStateFlagsDirty=!0,this.scheduleRefresh())}},{key:`setEdgesState`,value:function(e,t){var n=!1,r=H(e),i;try{for(r.s();!(i=r.n()).done;){var a=i.value;a=``+a;var o=this.getEdgeState(a);if(Ar(o,t)){var s=W(W({},o),t);this.edgeStates.set(a,s),this.dirtyEdges.add(a),this.updateHoveredEdgeTracking(a,o,s),n=!0}}}catch(e){r.e(e)}finally{r.f()}n&&(this.graphStateFlagsDirty=!0,this.scheduleRefresh())}},{key:`removeNode`,value:function(e){this.nodeStates.delete(e),this.dirtyNodes.delete(e),this.clearHoveredFor(`node`,e)}},{key:`removeEdge`,value:function(e){this.edgeStates.delete(e),this.dirtyEdges.delete(e),this.clearHoveredFor(`edge`,e)}},{key:`pruneNodes`,value:function(e){var t=H(this.nodeStates.keys()),n;try{for(t.s();!(n=t.n()).done;){var r=n.value;e(r)||this.removeNode(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:`pruneEdges`,value:function(e){var t=H(this.edgeStates.keys()),n;try{for(t.s();!(n=t.n()).done;){var r=n.value;e(r)||this.removeEdge(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:`clearNodes`,value:function(){this.nodeStates.clear(),this.dirtyNodes.clear(),this.clearHoveredForKinds(vc(`node`))}},{key:`clearEdges`,value:function(){this.edgeStates.clear(),this.dirtyEdges.clear(),this.clearHoveredForKinds(vc(`edge`))}},{key:`resetGraphState`,value:function(){this.graphState=Qn(this.customGraphStateDefaults),this.graphStateChanged=!1,this.graphStateFlagsDirty=!1}},{key:`clearDirtyTracking`,value:function(){this.dirtyNodes.clear(),this.dirtyEdges.clear(),this.graphStateChanged=!1}},{key:`setHovered`,value:function(e){this.hovered=e}},{key:`clearHoveredFor`,value:function(e,t){this.hovered&&this.hovered.key===t&&vc(e).includes(this.hovered.kind)&&(this.hovered=null)}},{key:`clearHoveredForKinds`,value:function(e){this.hovered&&e.includes(this.hovered.kind)&&(this.hovered=null)}},{key:`updateGraphStateFromNodes`,value:function(){var e=!1,t=!1,n=!1,r=H(this.nodeStates),i;try{for(r.s();!(i=r.n()).done;){var a=V(i.value,2)[1];if(a.isHovered&&(e=!0),a.isHighlighted&&(t=!0),a.isDragged&&(n=!0),e&&t&&n)break}}catch(e){r.e(e)}finally{r.f()}!e&&this.hovered?.kind===`edge`&&(e=!0);var o=!this.graphState.isPanning&&!this.graphState.isZooming&&!n;(this.graphState.hasHovered!==e||this.graphState.hasHighlighted!==t||this.graphState.isDragging!==n||this.graphState.isIdle!==o)&&(this.graphStateChanged=!0),this.graphState=W(W({},this.graphState),{},{hasHovered:e,hasHighlighted:t,isDragging:n,isIdle:o})}},{key:`updateGraphStateFromEdges`,value:function(){var e=this.hovered?.kind===`node`;if(!e){var t=H(this.edgeStates),n;try{for(t.s();!(n=t.n()).done;)if(V(n.value,2)[1].isHovered){e=!0;break}}catch(e){t.e(e)}finally{t.f()}}this.graphState.hasHovered!==e&&(this.graphStateChanged=!0),this.graphState=W(W({},this.graphState),{},{hasHovered:e})}},{key:`flushGraphStateFlags`,value:function(){this.graphStateFlagsDirty&&=(this.updateGraphStateFromNodes(),this.updateGraphStateFromEdges(),!1)}},{key:`updateHoveredNodeTracking`,value:function(e,t,n){if(t.isHovered!==n.isHovered){if(n.isHovered){if(this.hovered?.kind===`node`&&this.hovered.key!==e){var r=this.hovered.key,i=this.getNodeState(r);this.nodeStates.set(r,W(W({},i),{},{isHovered:!1})),this.dirtyNodes.add(r)}this.hovered={kind:`node`,key:e}}else this.hovered?.kind===`node`&&this.hovered.key===e&&(this.hovered=null)}}},{key:`updateHoveredEdgeTracking`,value:function(e,t,n){if(t.isHovered!==n.isHovered){if(n.isHovered){if(this.hovered?.kind===`edge`&&this.hovered.key!==e){var r=this.hovered.key,i=this.getEdgeState(r);this.edgeStates.set(r,W(W({},i),{},{isHovered:!1})),this.dirtyEdges.add(r)}this.hovered={kind:`edge`,key:e}}else this.hovered?.kind===`edge`&&this.hovered.key===e&&(this.hovered=null)}}}])}(),Xc=1,Zc=2,Qc=3,$c=4,el=function(e){function t(e,n){var r,i,a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};G(this,t),i=q(this,t),U(i,`nodeReducer`,null),U(i,`edgeReducer`,null),U(i,`stageCanvas`,null),U(i,`mouseLayer`,null),U(i,`gestureHint`,null),U(i,`extraElements`,{}),U(i,`webGLContext`,null),U(i,`pickingFrameBuffer`,null),U(i,`pickingTexture`,null),U(i,`pickingDepthBuffer`,null),U(i,`activeListeners`,{}),U(i,`nodeVariableEntries`,[]),U(i,`edgeVariableEntries`,[]),U(i,`edgePathsByName`,new Map),U(i,`nodeProgramIndex`,{}),U(i,`edgeProgramIndex`,{}),U(i,`edgeTextureIndexCache`,{}),U(i,`nodeGraphCoords`,{}),U(i,`nodeExtent`,{x:[0,1],y:[0,1]}),U(i,`matrix`,Rt()),U(i,`invMatrix`,Rt()),U(i,`correctionRatio`,1),U(i,`frameId`,0),U(i,`customBBox`,null),U(i,`gpuTimerExt`,void 0),U(i,`activeGpuTimerQuery`,null),U(i,`pendingGpuTimerQueries`,[]),U(i,`normalizationFunction`,Vr({x:[0,1],y:[0,1]})),U(i,`graphToViewportRatio`,1),U(i,`pickingState`,oc()),U(i,`prevNodeVisibilities`,{}),U(i,`width`,0),U(i,`height`,0),U(i,`autoRescaleFrozen`,!1),U(i,`stylesDeclaration`,null),U(i,`resolvedStageStyle`,{}),U(i,`renderFrame`,null),U(i,`contextLost`,!1),U(i,`pendingProcess`,`full`),U(i,`needToRefreshState`,!1),U(i,`checkEdgesEventsFrame`,null),U(i,`edgeStyleAnalysis`,{dependency:`static`,xAttribute:null,yAttribute:null}),U(i,`depthLayers`,Y(Rn)),U(i,`customLayerPrograms`,new Map),U(i,`nodeShapeSlug`,null),U(i,`sdfAtlas`,null),U(i,`depthRanges`,{nodes:{},edges:{}}),U(i,`nodeBaseDepth`,{}),U(i,`edgeBaseDepth`,{});var o=a.primitives,s=a.styles,c=a.settings,l=c===void 0?{}:c,u=a.nodeReducer,d=a.edgeReducer,f=a.customNodeState,p=a.customEdgeState,m=a.customGraphState;i.stateManager=new Yc(function(){return i.scheduleStateRefresh()},f,p,m);var h=o??Dr;i.stylesDeclaration=s?{nodes:s.nodes??$n.nodes,edges:s.edges??$n.edges,stage:s.stage}:$n,i.nodeReducer=u??null,i.edgeReducer=d??null;var g=dr(i.stylesDeclaration.nodes);i.nodeReducer&&(g.dependency=`graph-state`),i.edgeStyleAnalysis=dr(i.stylesDeclaration.edges),i.edgeReducer&&(i.edgeStyleAnalysis.dependency=`graph-state`),i.stylesDeclaration.stage&&(i.resolvedStageStyle=wr(i.stylesDeclaration.stage,i.stateManager.graphState));var _=Wr(l);if(Ur(_),_.enableNodeDrag){var v=g.xAttribute,y=g.yAttribute;if((!v||!y)&&!_.dragPositionToAttributes)throw Error('Sigma: `enableNodeDrag` is true but position attribute names could not be inferred from styles. Either use attribute bindings for x/y in your node styles (e.g. `x: { attribute: "x" }`), or provide a `dragPositionToAttributes` setting.')}if(Br(e),!(n instanceof HTMLElement))throw Error(`Sigma: container should be an html element.`);i.container=n,i.edgeGroups=new tc(e,function(e,t){for(var n=0;n<e.length;n++){var r=i.stateManager.getEdgeState(e[n]);r.parallelIndex=n,r.parallelCount=t}});var b=new ec(e,i.viewportToGraph.bind(i),i.setNodesState.bind(i),function(e,t){return i.emit(e,t)});if(i.depthLayers=h.depthLayers??Y(Rn),!(s!=null&&s.nodes)&&!In.every(function(e){return i.depthLayers.includes(e)}))throw Error(`Sigma: depthLayers must include ${In.join(`, `)} for the built-in node styles.`);if(!(s!=null&&s.edges)&&!Ln.every(function(e){return i.depthLayers.includes(e)}))throw Error(`Sigma: depthLayers must include ${Ln.join(`, `)} for the built-in edge styles.`);i.itemBuckets={nodes:new Es(i.depthLayers),edges:new Es(i.depthLayers)},i.initWebGLContext(),i.mouseLayer=Jr(`div`,{position:`absolute`,touchAction:`none`,userSelect:`none`},{class:`sigma-mouse`}),i.container.appendChild(i.mouseLayer),i.resolvedStageStyle.background&&(i.container.style.backgroundColor=i.resolvedStageStyle.background),i.resolvedStageStyle.cursor&&(i.container.style.cursor=i.resolvedStageStyle.cursor);var x=new Ds(i.webGLContext),S=new js(i.webGLContext,{channels:1}),C=new Ms(i.webGLContext),w=new js(i.webGLContext,{channels:4}),T=i.webGLContext,E=new Rc({gl:T,getFrameBuffer:function(){return i.pickingFrameBuffer},getPixelRatio:function(){return i.internals.pixelRatio},getDownSizingRatio:function(){return i.internals.settings.pickingDownSizingRatio},isRenderPending:function(){return i.renderFrame!==null},onIndex:function(e,t){return Sc(i.internals,i.pickingState.lookup[e]??null,t)}}),D=i.initPrograms(h,_),O=h==null||(r=h.nodes)==null?void 0:r.labelAttachments,k=null;return O&&Object.keys(O).length>0&&(k=new Ts(T,O,function(){return i.scheduleRender()})),i.internals=W(W({nodeDataCache:{},edgeDataCache:{},nodesWithForcedLabels:new Set,nodesWithBackdrop:new Set,edgesWithForcedLabels:new Set,settings:_,primitives:h,pixelRatio:Yr(),graph:e,stateManager:i.stateManager,dragManager:b,hoverResolver:E,nodeStyleAnalysis:g,pickingState:i.pickingState},D),{},{attachmentManager:k,nodeDataTexture:x,nodeFrameTexture:S,edgeDataTexture:C,edgeFrameTexture:w,getDimensions:function(){return i.getDimensions()},getGraphDimensions:function(){return i.getGraphDimensions()},getStagePadding:function(){return i.getStagePadding()},getCameraState:function(){return i.camera.getState()},getHitAtPosition:function(e){return i.getHitAtPosition(e)},setNodeState:function(e,t){return i.setNodeState(e,t)},setEdgeState:function(e,t){return i.setEdgeState(e,t)},updateContainerCursor:function(){return i.updateContainerCursor()},scheduleRefresh:function(){return i.scheduleRefresh()},viewportToFramedGraph:function(e){return i.viewportToFramedGraph(e)},viewportToGraph:function(e){return i.viewportToGraph(e)},framedGraphToViewport:function(e){return i.framedGraphToViewport(e)},scaleSize:function(e){return i.scaleSize(e)},emit:function(e,t){return i.emit(e,t)}}),i.labelRenderer=new Jc(i.internals),i.resize(),i.initializeWebGLLabels(),i.camera=new zs,i.bindCameraHandlers(),i.mouseCaptor=new Zs(i.mouseLayer,i),i.mouseCaptor.setSettings(i.internals.settings),i.touchCaptor=new $s(i.mouseLayer,i),i.touchCaptor.setSettings(i.internals.settings),i.bindEventHandlers(),i.bindGraphHandlers(),i.handleSettingsUpdate(),i.refresh(),i}return J(t,e),K(t,[{key:`initializeWebGLLabels`,value:function(){this.sdfAtlas=new wa,this.sdfAtlas.registerFont({family:`sans-serif`,weight:`normal`,style:`normal`})}},{key:`resetWebGLTexture`,value:function(){var e=this.webGLContext;if(!this.pickingFrameBuffer)return this;var t=Math.ceil(this.width*this.internals.pixelRatio/this.internals.settings.pickingDownSizingRatio),n=Math.ceil(this.height*this.internals.pixelRatio/this.internals.settings.pickingDownSizingRatio);e.bindFramebuffer(e.FRAMEBUFFER,this.pickingFrameBuffer),this.pickingTexture&&e.deleteTexture(this.pickingTexture);var r=e.createTexture();r&&(e.bindTexture(e.TEXTURE_2D,r),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,n,0,e.RGBA,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,r,0),this.pickingTexture=r),this.pickingDepthBuffer&&e.deleteRenderbuffer(this.pickingDepthBuffer);var i=e.createRenderbuffer();return i&&(e.bindRenderbuffer(e.RENDERBUFFER,i),e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,t,n),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,i),this.pickingDepthBuffer=i),e.bindFramebuffer(e.FRAMEBUFFER,null),this}},{key:`bindCameraHandlers`,value:function(){var e=this;return this.activeListeners.camera=function(){e.refreshMatrices(),e.labelRenderer.labelsDirty=!0,e.scheduleRender()},this.activeListeners.cameraAnimationStart=function(t){var n=t.from,r=t.to;n.ratio!==r.ratio&&e.stateManager.setGraphState({isZooming:!0})},this.activeListeners.cameraAnimationEnd=function(){e.stateManager.setGraphState({isZooming:!1})},this.camera.on(`updated`,this.activeListeners.camera),this.camera.on(`animationStart`,this.activeListeners.cameraAnimationStart),this.camera.on(`animationEnd`,this.activeListeners.cameraAnimationEnd),this}},{key:`unbindCameraHandlers`,value:function(){return this.camera.removeListener(`updated`,this.activeListeners.camera),this.camera.removeListener(`animationStart`,this.activeListeners.cameraAnimationStart),this.camera.removeListener(`animationEnd`,this.activeListeners.cameraAnimationEnd),this}},{key:`getHitAtPosition`,value:function(e){if(this.contextLost)return null;var t=this.webGLContext;t.bindFramebuffer(t.FRAMEBUFFER,this.pickingFrameBuffer);var n=dn(t,this.pickingFrameBuffer,e.x,e.y,this.internals.pixelRatio,this.internals.settings.pickingDownSizingRatio),r=un.apply(void 0,Y(n));return this.pickingState.lookup[r]??null}},{key:`bindEventHandlers`,value:function(){return Cc(this.internals,this.mouseCaptor,this.touchCaptor,this.activeListeners),this}},{key:`bindGraphHandlers`,value:function(){return wc({graph:this.internals.graph,edgeGroups:this.edgeGroups,addNode:this.addNode.bind(this),updateNode:this.updateNode.bind(this),removeNode:this.removeNode.bind(this),addEdge:this.addEdge.bind(this),updateEdge:this.updateEdge.bind(this),removeEdge:this.removeEdge.bind(this),clearEdgeState:this.clearEdgeState.bind(this),clearNodeState:this.clearNodeState.bind(this),clearEdgeIndices:this.clearEdgeIndices.bind(this),clearNodeIndices:this.clearNodeIndices.bind(this),refresh:this.refresh.bind(this)},this.activeListeners),this}},{key:`unbindGraphHandlers`,value:function(){Tc(this.internals.graph,this.activeListeners)}},{key:`getNodeShapeId`,value:function(e){return this.internals.nodeShapeMap&&this.internals.nodeGlobalShapeIds&&e.shape&&e.shape in this.internals.nodeShapeMap?this.internals.nodeGlobalShapeIds[this.internals.nodeShapeMap[e.shape]]:ui(e.shape||`circle`)}},{key:`processNodes`,value:function(){var e=this,t=this.internals.graph,n=this.internals.settings,r=this.getDimensions(),i=n.autoRescale,a=n.autoRescaleContent,o=this.nodeExtent;if(i===!1){var s=r.width,c=r.height;o={x:[-s/2,s/2],y:[-c/2,c/2]}}else(i!==`once`||!this.autoRescaleFrozen)&&(o=this.computeNodeExtent(),a!==`positions`&&!this.customBBox&&(o=kc({extent:o,coords:this.nodeGraphCoords,nodeData:this.internals.nodeDataCache,dimensions:r,stagePadding:this.getStagePadding(),zoomToSizeRatioFunction:n.zoomToSizeRatioFunction,itemSizesReference:n.itemSizesReference,fitLabels:a===`labels`,nodeLabelBox:function(t,n){return e.labelRenderer.nodeLabelBox(t,n)}})),i===`once`&&(this.autoRescaleFrozen=!0));this.nodeExtent=o,this.normalizationFunction=Vr(this.customBBox||this.nodeExtent);var l=Kt(new zs().getState(),r,this.getGraphDimensions(),this.getStagePadding());this.labelRenderer.labelGrid.resizeAndClear(r,n.labelGridCellSize),this.labelRenderer.edgeAnchorGrid.resizeAndClear(r,n.labelGridCellSize);var u=n.renderEdgeLabels&&n.edgeLabelAnchors===`allNodes`,d=!1;cc(this.pickingState,`node`);for(var f=t.nodes(),p=0,m=f.length;p<m;p++){var h=f[p],g=this.internals.nodeDataCache[h],_=this.nodeGraphCoords[h];g.x=_.x,g.y=_.y,this.normalizationFunction.applyTo(g),g.visibility!==this.prevNodeVisibilities[h]&&(d=!0),typeof g.label==`string`&&g.visibility!==`hidden`&&g.labelVisibility!==`hidden`&&this.labelRenderer.labelGrid.add(h,g.size,this.framedGraphToViewport(g,{matrix:l})),u&&g.visibility!==`hidden`&&this.labelRenderer.edgeAnchorGrid.add(h,g.size,this.framedGraphToViewport(g,{matrix:l}))}this.labelRenderer.labelGrid.organize(),this.labelRenderer.edgeAnchorGrid.organize(),this.nodeProgram.reallocate(f.length);var v=0;this.depthRanges.nodes={},this.nodeBaseDepth={};var y=this.internals.nodeDataCache,b=H(this.depthLayers),x;try{for(b.s();!(x=b.n()).done;){var S=x.value,C=this.itemBuckets.nodes.getSorted(S,function(e){return y[e].zIndex});if(C.length!==0){this.depthRanges.nodes[S]=[{offset:v,count:C.length}];var w=H(C),T;try{for(w.s();!(T=w.n()).done;){var E=T.value;this.nodeBaseDepth[E]=S,this.nodeProgram.allocateNode(E),lc(this.pickingState,`node`,E),this.addNodeToProgram(E,v++)}}catch(e){w.e(e)}finally{w.f()}}}}catch(e){b.e(e)}finally{b.f()}this.nodeProgram.invalidateBuffers();for(var D=0,O=f.length;D<O;D++)this.prevNodeVisibilities[f[D]]=this.internals.nodeDataCache[f[D]].visibility;this.labelRenderer.processWebGLLabels(f);var k=H(this.customLayerPrograms.values()),A;try{for(k.s();!(A=k.n()).done;){var j=A.value.program;j.cacheData&&j.cacheData()}}catch(e){k.e(e)}finally{k.f()}return d}},{key:`processEdges`,value:function(){var e=this.internals.graph.edges();this.edgeProgram.reallocate(e.length);var t=0;cc(this.pickingState,`edge`),this.depthRanges.edges={},this.edgeBaseDepth={};var n=this.internals.edgeDataCache,r=H(this.depthLayers),i;try{for(r.s();!(i=r.n()).done;){var a=i.value,o=this.itemBuckets.edges.getSorted(a,function(e){return n[e].zIndex});if(o.length!==0){this.depthRanges.edges[a]=[{offset:t,count:o.length}];var s=H(o),c;try{for(s.s();!(c=s.n()).done;){var l=c.value;this.edgeBaseDepth[l]=a,lc(this.pickingState,`edge`,l),this.addEdgeToProgram(l,t++)}}catch(e){s.e(e)}finally{s.f()}}}}catch(e){r.e(e)}finally{r.f()}this.edgeProgram.invalidateBuffers()}},{key:`updateNodeDepthRanges`,value:function(e,t,n){var r=this.nodeProgramIndex[e];r!==void 0&&(Rr(this.depthRanges.nodes,t,r),zr(this.depthRanges.nodes,n,r))}},{key:`updateEdgeDepthRanges`,value:function(e,t,n){var r=this.edgeProgramIndex[e];r!==void 0&&(Rr(this.depthRanges.edges,t,r),zr(this.depthRanges.edges,n,r))}},{key:`handleSettingsUpdate`,value:function(){var e=this,t=this.internals.settings;return this.camera.minRatio=t.minCameraRatio,this.camera.maxRatio=t.maxCameraRatio,this.camera.enabledZooming=t.enableCameraZooming,this.camera.enabledPanning=t.enableCameraPanning,this.camera.enabledRotation=t.enableCameraRotation,t.cameraPanBoundaries?this.camera.constrainState=function(n){return e.cleanCameraState(n,t.cameraPanBoundaries&&X(t.cameraPanBoundaries)===`object`?t.cameraPanBoundaries:{})}:this.camera.constrainState=null,this.camera.setState(this.camera.getState()),this.mouseLayer.style.touchAction=t.gestureTarget===`graph`?`none`:t.gestureTarget===`shared`?`pan-x pan-y`:`auto`,t.gestureTarget!==`shared`&&this.gestureHint&&(this.gestureHint.kill(),this.gestureHint=null),this.mouseCaptor.setSettings(this.internals.settings),this.touchCaptor.setSettings(this.internals.settings),this}},{key:`cleanCameraState`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.tolerance,r=n===void 0?0:n,i=t.boundaries,a=W({},e),o=i||this.nodeExtent,s=V(o.x,2),c=s[0],l=s[1],u=V(o.y,2),d=u[0],f=u[1],p=[this.graphToViewport({x:c,y:d},{cameraState:e}),this.graphToViewport({x:l,y:d},{cameraState:e}),this.graphToViewport({x:c,y:f},{cameraState:e}),this.graphToViewport({x:l,y:f},{cameraState:e})],m=1/0,h=-1/0,g=1/0,_=-1/0;p.forEach(function(e){var t=e.x,n=e.y;m=Math.min(m,t),h=Math.max(h,t),g=Math.min(g,n),_=Math.max(_,n)});var v=h-m,y=_-g,b=this.getDimensions(),x=b.width,S=b.height,C=0,w=0;if(v>=x?h<x-r?C=h-(x-r):m>r&&(C=m-r):h>x+r?C=h-(x+r):m<-r&&(C=m+r),y>=S?_<S-r?w=_-(S-r):g>r&&(w=g-r):_>S+r?w=_-(S+r):g<-r&&(w=g+r),C||w){var T=this.viewportToFramedGraph({x:0,y:0},{cameraState:e}),E=this.viewportToFramedGraph({x:C,y:w},{cameraState:e});C=E.x-T.x,w=E.y-T.y,a.x+=C,a.y+=w}return a}},{key:`refreshMatrices`,value:function(){var e=this.camera.getState(),t=this.getDimensions(),n=this.getGraphDimensions(),r=this.getStagePadding();this.matrix=Kt(e,t,n,r),this.invMatrix=Kt(e,t,n,r,!0),this.correctionRatio=qt(this.matrix,e,t),this.graphToViewportRatio=this.getGraphToViewportRatio()}},{key:`processData`,value:function(){var e;this.emit(`beforeProcess`),(e=this.internals.attachmentManager)==null||e.clear();var t=W({},this.pickingState.idsByKind),n=this.processNodes();(this.pendingProcess===`full`||n)&&this.processEdges(),uc(this.pickingState,this.internals),dc(t,this.pickingState.idsByKind)||this.internals.hoverResolver.invalidate(),this.pendingProcess=`none`,this.emit(`afterProcess`)}},{key:`render`,value:function(){var e=this;if(this.contextLost)return this;this.emit(`beforeRender`);var t=function(){return e.internals.hoverResolver.frameRendered(),e.emit(`afterRender`),e};if(this.renderFrame&&=(cancelAnimationFrame(this.renderFrame),null),this.resize(),(this.pendingProcess!==`none`||this.needToRefreshState)&&(this.labelRenderer.labelsDirty=!0),this.pendingProcess!==`none`&&this.processData(),this.needToRefreshState&&this.refreshState(),this.needToRefreshState=!1,this.stateManager.clearDirtyTracking(),this.pendingProcess!==`none`&&this.processData(),this.clear(),this.resetWebGLTexture(),!this.internals.graph.order)return t();var n=this.mouseCaptor,r=this.camera.isAnimating()||n.isMoving||n.draggedEvents||n.currentWheelDirection;this.refreshMatrices(),this.frameId++;var i=this.internals.settings.DEBUG_logRenderStats?this.getDebugPrograms():null;i&&i.forEach(function(e){return e.resetDebugStats()}),this.internals.settings.DEBUG_gpuTimerQueries&&this.beginGpuTimerQuery(),this.internals.nodeFrameTexture.ensureCapacity(this.internals.nodeDataTexture.getCapacity()),this.internals.edgeFrameTexture.ensureCapacity(this.internals.edgeDataTexture.getCapacity());var a=this.getRenderParams(),o=$.edge.writesPickingThisFrame(this.internals)?a:W(W({},a),{},{pickingFrameBuffer:null});this.labelRenderer.resetFrame();var s=this.webGLContext,c=Math.ceil(this.width*this.internals.pixelRatio/this.internals.settings.pickingDownSizingRatio),l=Math.ceil(this.height*this.internals.pixelRatio/this.internals.settings.pickingDownSizingRatio);if(s.bindFramebuffer(s.FRAMEBUFFER,this.pickingFrameBuffer),s.viewport(0,0,c,l),s.clear(s.COLOR_BUFFER_BIT|s.DEPTH_BUFFER_BIT),s.bindFramebuffer(s.FRAMEBUFFER,null),s.viewport(0,0,this.width*this.internals.pixelRatio,this.height*this.internals.pixelRatio),s.clear(s.COLOR_BUFFER_BIT|s.DEPTH_BUFFER_BIT),this.internals.nodeDataTexture.upload(),this.internals.edgeDataTexture.upload(),this.nodeProgram.uploadLayerTexture(),this.edgeProgram.uploadAttributeTexture(),this.emit(`afterTexturesUpload`),this.internals.nodeDataTexture.bind(Qc),this.internals.edgeDataTexture.bind($c),this.edgeFramePass.run(a,this.internals.edgeFrameTexture,this.internals.edgeDataTexture.getHighWaterMark(),this.edgeProgram.getAttributeTexture(),this.nodeProgram.getAttributeTexture()),this.internals.edgeFrameTexture.bind(Xc),this.internals.settings.renderLabels){this.labelRenderer.computeDisplayedNodeLabels();var u=this.labelRenderer.buildFramePassPoints(),d=u.data,f=u.count;this.nodeFramePass.run(d,f,this.internals.nodeFrameTexture,a,this.nodeProgram.getAttributeTexture()),this.internals.nodeFrameTexture.bind(Zc)}this.internals.settings.renderEdgeLabels&&this.labelRenderer.computeDisplayedEdgeLabels();var p=H(this.customLayerPrograms.values()),m;try{for(p.s();!(m=p.n()).done;){var h=m.value.program;h.preRender&&h.preRender(a)}}catch(e){p.e(e)}finally{p.f()}s.bindFramebuffer(s.FRAMEBUFFER,null),s.viewport(0,0,this.width*this.internals.pixelRatio,this.height*this.internals.pixelRatio),s.blendFunc(s.ONE,s.ONE_MINUS_SRC_ALPHA);var g=!this.internals.settings.hideLabelsOnMove||!r,_=H(this.depthLayers),v;try{for(_.s();!(v=_.n()).done;){var y=v.value,b=H(this.customLayerPrograms.values()),x;try{for(b.s();!(x=b.n()).done;){var S=x.value;S.depth===y&&S.program.render(a)}}catch(e){b.e(e)}finally{b.f()}var C=this.depthRanges.edges[y];if(C&&(!this.internals.settings.hideEdgesOnMove||!r)){var w=H(C),T;try{for(w.s();!(T=w.n()).done;){var E=T.value,D=E.offset,O=E.count;O>0&&this.edgeProgram.render(o,D,O)}}catch(e){w.e(e)}finally{w.f()}}this.internals.settings.renderEdgeLabels&&g&&(this.labelRenderer.renderEdgeLabelBackgrounds($.edgeLabel.writesPickingThisFrame(this.internals)?a:W(W({},a),{},{pickingFrameBuffer:null}),y),this.labelRenderer.renderEdgeLabels(a,y)),this.labelRenderer.cacheAttachments(y),this.labelRenderer.renderBackdrops(W(W({},a),{},{pickingFrameBuffer:null}),y);var k=this.depthRanges.nodes[y];if(k){var A=H(k),j;try{for(A.s();!(j=A.n()).done;){var M=j.value,N=M.offset,P=M.count;P>0&&this.nodeProgram.render(a,N,P)}}catch(e){A.e(e)}finally{A.f()}}g&&(this.labelRenderer.renderAttachments(W(W({},a),{},{pickingFrameBuffer:null}),y),this.labelRenderer.renderLabelBackgrounds($.nodeLabel.writesPickingThisFrame(this.internals)?a:W(W({},a),{},{pickingFrameBuffer:null}),y),this.internals.settings.renderLabels&&this.labelRenderer.renderWebGLLabels(a,y))}}catch(e){_.e(e)}finally{_.f()}return this.labelRenderer.labelsDirty=!1,this.internals.settings.DEBUG_displayPickingLayer&&(s.bindFramebuffer(s.READ_FRAMEBUFFER,this.pickingFrameBuffer),s.bindFramebuffer(s.DRAW_FRAMEBUFFER,null),s.blitFramebuffer(0,0,c,l,0,0,this.width*this.internals.pixelRatio,this.height*this.internals.pixelRatio,s.COLOR_BUFFER_BIT,s.NEAREST)),this.internals.settings.DEBUG_gpuTimerQueries&&this.endGpuTimerQuery(),this.pollGpuTimerQueries(),i&&this.logRenderStats(i),t()}},{key:`getDebugPrograms`,value:function(){return[this.nodeProgram,this.edgeProgram,this.internals.labelProgram,this.internals.edgeLabelProgram,this.internals.edgeLabelBackgroundProgram,this.internals.backdropProgram,this.internals.labelBackgroundProgram,this.internals.attachmentProgram].filter(function(e){return e!==null})}},{key:`logRenderStats`,value:function(e){var t={},n=H(e),r;try{for(n.s();!(r=n.n()).done;){var i=r.value;t[i.constructor.name]=W({},i.debugStats)}}catch(e){n.e(e)}finally{n.f()}console.log(`[sigma] DEBUG_logRenderStats: frame #${this.frameId}`),console.table(t)}},{key:`getGpuTimerExtension`,value:function(){return this.gpuTimerExt===void 0&&(this.gpuTimerExt=this.webGLContext.getExtension(`EXT_disjoint_timer_query_webgl2`),this.gpuTimerExt||console.warn(`Sigma: DEBUG_gpuTimerQueries is enabled, but this browser/driver doesn't support EXT_disjoint_timer_query_webgl2.`)),this.gpuTimerExt}},{key:`beginGpuTimerQuery`,value:function(){var e=this.getGpuTimerExtension();if(e){var t=this.webGLContext,n=t.createQuery();n&&(t.beginQuery(e.TIME_ELAPSED_EXT,n),this.activeGpuTimerQuery=n)}}},{key:`endGpuTimerQuery`,value:function(){this.gpuTimerExt&&this.activeGpuTimerQuery&&(this.webGLContext.endQuery(this.gpuTimerExt.TIME_ELAPSED_EXT),this.pendingGpuTimerQueries.push({query:this.activeGpuTimerQuery,frameId:this.frameId}),this.activeGpuTimerQuery=null)}},{key:`pollGpuTimerQueries`,value:function(){if(this.pendingGpuTimerQueries.length!==0){var e=this.webGLContext,t=this.gpuTimerExt;if(!t)this.pendingGpuTimerQueries.forEach(function(t){var n=t.query;return e.deleteQuery(n)}),this.pendingGpuTimerQueries=[];else{var n=e.getParameter(t.GPU_DISJOINT_EXT),r=[],i=H(this.pendingGpuTimerQueries),a;try{for(i.s();!(a=i.n()).done;){var o=a.value;if(!e.getQueryParameter(o.query,e.QUERY_RESULT_AVAILABLE))r.push(o);else{if(!n){var s=e.getQueryParameter(o.query,e.QUERY_RESULT);console.log(`[sigma] DEBUG_gpuTimerQueries: frame #${o.frameId} GPU time = ${(s/1e6).toFixed(2)}ms`)}e.deleteQuery(o.query)}}}catch(e){i.e(e)}finally{i.f()}this.pendingGpuTimerQueries=r}}}},{key:`postEvaluateNode`,value:function(e,t,n){var r=e;r.x===void 0&&(r.x=t.x),r.y===void 0&&(r.y=t.y),e.highlighted=n.isHighlighted;for(var i=0,a=this.nodeVariableEntries.length;i<a;i++){var o=V(this.nodeVariableEntries[i],2),s=o[0],c=o[1];r[s]=r[s]??t[s]??c.default}}},{key:`addNode`,value:function(e){var t=this.internals.graph.getNodeAttributes(e),n=this.stateManager.getNodeState(e),r=this.internals.nodeDataCache[e]||{};if(xr(this.stylesDeclaration.nodes,t,n,this.stateManager.graphState,this.internals.graph,r),this.postEvaluateNode(r,t,n),this.nodeReducer){var i=this.nodeReducer(e,r,t,n,this.stateManager.graphState,this.internals.graph);r=W(W({},r),i)}if(typeof r.x!=`number`||typeof r.y!=`number`)throw Error(`Sigma: could not find a valid position (x, y) for node "${e}". Provide coordinates via node attributes, styles, or a nodeReducer.`);this.internals.nodeShapeMap?(!r.shape||!(r.shape in this.internals.nodeShapeMap))&&(r.shape=Object.keys(this.internals.nodeShapeMap)[0]):this.nodeShapeSlug&&(r.shape=this.nodeShapeSlug),this.internals.nodeDataCache[e]=r,this.nodeGraphCoords[e]={x:r.x,y:r.y},Mr(this.internals.nodesWithForcedLabels,e,Fr(r)),Mr(this.internals.nodesWithBackdrop,e,Ir(r)),this.itemBuckets.nodes.set(e,r.depth)}},{key:`updateNode`,value:function(e){this.addNode(e);var t=this.internals.nodeDataCache[e];this.normalizationFunction.applyTo(t)}},{key:`removeNode`,value:function(e){this.itemBuckets.nodes.remove(e),delete this.internals.nodeDataCache[e],delete this.nodeGraphCoords[e],delete this.nodeProgramIndex[e],this.internals.dragManager.removeNode(e),this.stateManager.removeNode(e),this.internals.nodesWithForcedLabels.delete(e),this.internals.nodesWithBackdrop.delete(e)}},{key:`postEvaluateEdge`,value:function(e,t){for(var n=e,r=0,i=this.edgeVariableEntries.length;r<i;r++){var a=V(this.edgeVariableEntries[r],2),o=a[0],s=a[1];n[o]=n[o]??t[o]??s.default}}},{key:`applyEdgeSpread`,value:function(e,t,n){if(!(n.parallelCount<=1)){var r=this.internals.graph.source(e),i=this.internals.graph.target(e),a=r===i,o=a?t.selfLoopPath||t.path:t.parallelPath||t.path,s=o?this.edgePathsByName.get(o):void 0;if(s!=null&&s.spread){var c=t.parallelSpread??.25,l=s.spread.compute(n.parallelIndex,n.parallelCount,c);!a&&this.internals.graph.isDirected(e)&&r>i&&(l=-l),t[s.spread.variable]=l}}}},{key:`addEdge`,value:function(e){var t=this.internals.graph.getEdgeAttributes(e),n=this.stateManager.getEdgeState(e),r={};if(Sr(this.stylesDeclaration.edges,t,n,this.stateManager.graphState,this.internals.graph,r),this.postEvaluateEdge(r,t),this.edgeReducer){var i=this.edgeReducer(e,r,t,n,this.stateManager.graphState,this.internals.graph);r=W(W({},r),i)}this.applyEdgeSpread(e,r,n),this.internals.edgeDataCache[e]=r,Mr(this.internals.edgesWithForcedLabels,e,Fr(r)),this.itemBuckets.edges.set(e,r.depth)}},{key:`updateEdge`,value:function(e){this.addEdge(e)}},{key:`removeEdge`,value:function(e){this.itemBuckets.edges.remove(e),delete this.internals.edgeDataCache[e],delete this.edgeProgramIndex[e],delete this.edgeTextureIndexCache[e],this.internals.edgeDataTexture.free(e),this.stateManager.removeEdge(e),this.internals.edgesWithForcedLabels.delete(e)}},{key:`clearNodeIndices`,value:function(){this.labelRenderer.resetLabelGrid(),this.autoRescaleFrozen||(this.nodeExtent={x:[0,1],y:[0,1]}),this.internals.nodeDataCache={},this.nodeGraphCoords={},this.edgeProgramIndex={},this.internals.nodesWithForcedLabels.clear(),this.internals.nodesWithBackdrop.clear(),this.prevNodeVisibilities={},this.itemBuckets.nodes.clearAll(),this.depthRanges.nodes={},this.nodeBaseDepth={}}},{key:`clearEdgeIndices`,value:function(){this.internals.edgeDataCache={},this.edgeProgramIndex={},this.edgeTextureIndexCache={},this.internals.edgesWithForcedLabels.clear(),cc(this.pickingState,`edge`),this.itemBuckets.edges.clearAll(),this.depthRanges.edges={},this.edgeBaseDepth={},this.edgeGroups.clear()}},{key:`clearIndices`,value:function(){this.clearEdgeIndices(),this.clearNodeIndices()}},{key:`clearNodeState`,value:function(){this.labelRenderer.resetFrame(),this.internals.nodesWithBackdrop.clear(),this.internals.dragManager.clear(),this.autoRescaleFrozen=!1,this.stateManager.clearNodes()}},{key:`clearEdgeState`,value:function(){this.labelRenderer.clearEdgeLabels(),this.stateManager.clearEdges()}},{key:`clearState`,value:function(){this.clearEdgeState(),this.clearNodeState(),this.stateManager.resetGraphState()}},{key:`addNodeToProgram`,value:function(e,t){var n,r=this.internals.nodeDataCache[e];this.internals.nodeDataTexture.allocate(e),(n=this.internals.nodeDataTexture).updateNode.apply(n,[e,r.x,r.y,r.size,this.getNodeShapeId(r)].concat(Y(Lr(r)),[r.color]));var i=this.internals.nodeDataTexture.getIndex(e);this.nodeProgram.process(sc(this.pickingState,`node`,e),t,r,i,e),this.nodeProgramIndex[e]=t}},{key:`addEdgeToProgram`,value:function(e,t){var n=this.internals.edgeDataCache[e],r=this.internals.graph.source(e),i=this.internals.graph.target(e),a=this.internals.edgeDataTexture.allocate(e);this.edgeTextureIndexCache[e]=a;var o=r===i,s=!o&&(this.stateManager.getEdgeState(e)?.parallelCount??1)>1,c=this.edgeProgram.resolveEdgeIds(n,o,s),l=c.pathId,u=c.headId,d=c.tailId,f=c.headLengthRatio,p=c.tailLengthRatio;this.internals.edgeDataTexture.updateEdge(e,this.internals.nodeDataTexture.getIndex(r),this.internals.nodeDataTexture.getIndex(i),n.size,f,p,l,u,d),this.edgeProgram.process(sc(this.pickingState,`edge`,e),t,this.internals.nodeDataCache[r],this.internals.nodeDataCache[i],n,a),this.edgeProgramIndex[e]=t}},{key:`getRenderParams`,value:function(){return{frameId:this.frameId,matrix:this.matrix,invMatrix:this.invMatrix,width:this.width,height:this.height,pixelRatio:this.internals.pixelRatio,zoomRatio:this.camera.ratio,cameraAngle:this.camera.angle,sizeRatio:1/this.scaleSize(),correctionRatio:this.correctionRatio,downSizingRatio:this.internals.settings.pickingDownSizingRatio,minEdgeThickness:this.internals.settings.minEdgeThickness,antiAliasingFeather:this.internals.settings.antiAliasingFeather,nodePickingPadding:this.internals.settings.nodePickingPadding,edgePickingPadding:this.internals.settings.edgePickingPadding,labelPickingPadding:this.internals.settings.labelPickingPadding,nodeDataTextureUnit:Qc,nodeDataTextureWidth:this.internals.nodeDataTexture.getTextureWidth(),nodeFrameTextureUnit:Zc,nodeFrameTextureWidth:this.internals.nodeFrameTexture.getTextureWidth(),edgeDataTextureUnit:$c,edgeDataTextureWidth:this.internals.edgeDataTexture.getTextureWidth(),edgeFrameTextureUnit:Xc,edgeFrameTextureWidth:this.internals.edgeFrameTexture.getTextureWidth(),pickingFrameBuffer:this.pickingFrameBuffer,labelPixelSnapping:+!!this.internals.settings.labelPixelSnapping}}},{key:`getStagePadding`,value:function(){var e=this.internals.settings,t=e.stagePadding;return e.autoRescale&&t||0}},{key:`getLayerElement`,value:function(e){if(e===`mouse`)return this.mouseLayer;var t=this.extraElements[e];if(!t)throw Error(`Sigma: layer "${e}" does not exist`);return t}},{key:`initWebGLContext`,value:function(){var e=this,t=this.createWebGLContext(`stage`);this.stageCanvas=this.extraElements.stage,this.webGLContext=t,this.stageCanvas.addEventListener(`webglcontextlost`,function(t){e.webGLContext&&(t.preventDefault(),e.contextLost=!0,e.renderFrame&&=(cancelAnimationFrame(e.renderFrame),null),e.gpuTimerExt=void 0,e.activeGpuTimerQuery=null,e.pendingGpuTimerQueries=[],e.emit(`webglContextLost`))}),this.stageCanvas.addEventListener(`webglcontextrestored`,function(){requestAnimationFrame(function(){e.webGLContext&&!e.webGLContext.isContextLost()&&e.restoreWebGLContext()})}),this.initPickingFramebuffer()}},{key:`initPickingFramebuffer`,value:function(){var e=this.webGLContext,t=e.createFramebuffer();if(!t)throw Error(`Sigma: cannot create picking frame buffer`);e.bindFramebuffer(e.FRAMEBUFFER,t);var n=e.createTexture();if(!n)throw Error(`Sigma: cannot create picking texture`);e.bindTexture(e.TEXTURE_2D,n),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,1,1,0,e.RGBA,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,n,0);var r=e.createRenderbuffer();if(!r)throw Error(`Sigma: cannot create picking depth buffer`);if(e.bindRenderbuffer(e.RENDERBUFFER,r),e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,1,1),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,r),e.checkFramebufferStatus(e.FRAMEBUFFER)!==e.FRAMEBUFFER_COMPLETE)throw Error(`Sigma: picking framebuffer is not complete`);e.bindFramebuffer(e.FRAMEBUFFER,null),this.pickingFrameBuffer=t,this.pickingTexture=n,this.pickingDepthBuffer=r}},{key:`initPrograms`,value:function(e,t){var n=this,r=this.webGLContext,i=rs(r,this.pickingFrameBuffer,n,e?.nodes,t.antialiasNodes),a=i.nodeProgram,o=i.labelProgram,s=i.backdropProgram,c=i.labelBackgroundProgram,l=i.attachmentProgram,u=i.framePass,d=i.shapeSlug,f=i.shapeNameToIndex,p=i.shapeGlobalIds,m=i.variables;this.nodeProgram=a,this.nodeFramePass=u,this.nodeVariableEntries=Object.entries(m),d&&(this.nodeShapeSlug=d);var h=is(r,this.pickingFrameBuffer,n,e?.edges,t.antialiasEdges,e?.nodes),g=h.edgeProgram,_=h.labelProgram,v=h.labelBackgroundProgram,y=h.framePass,b=h.variables,x=h.paths;return this.edgeProgram=g,this.edgeFramePass=y,this.edgeVariableEntries=Object.entries(b),this.edgePathsByName=new Map(x.map(function(e){return[e.name,e]})),{labelProgram:o,edgeLabelProgram:_,edgeLabelBackgroundProgram:v,backdropProgram:s,labelBackgroundProgram:c,attachmentProgram:l,nodeShapeMap:f??null,nodeGlobalShapeIds:p??null}}},{key:`restoreWebGLContext`,value:function(){var e,t,n,r,i,a=this.internals;this.initPickingFramebuffer(),(e=a.nodeDataTexture)==null||e.restore(),(t=a.nodeFrameTexture)==null||t.restore(),(n=a.edgeDataTexture)==null||n.restore(),(r=a.edgeFrameTexture)==null||r.restore(),(i=a.attachmentManager)==null||i.restore(),a.hoverResolver.reset(),Object.assign(a,this.initPrograms(a.primitives,a.settings));var o=H(this.customLayerPrograms.values()),s;try{for(o.s();!(s=o.n()).done;){var c=s.value;c.program.kill(),c.program=c.factory(this.webGLContext)}}catch(e){o.e(e)}finally{o.f()}this.contextLost=!1,this.emit(`webglContextRestored`),this.refresh()}},{key:`createLayer`,value:function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};if(this.extraElements[e])throw Error(`Sigma: a layer named "${e}" already exists`);var r=Jr(t,{position:`absolute`},{class:`sigma-${e}`});return n.style&&Object.assign(r.style,n.style),this.extraElements[e]=r,`beforeLayer`in n&&n.beforeLayer?this.getLayerElement(n.beforeLayer).before(r):`afterLayer`in n&&n.afterLayer?this.getLayerElement(n.afterLayer).after(r):this.container.appendChild(r),r}},{key:`createCanvas`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return this.createLayer(e,`canvas`,t)}},{key:`createWebGLContext`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=this.createCanvas(e,t);t.hidden&&n.remove();var r=n.getContext(`webgl2`,W({preserveDrawingBuffer:!1,antialias:!1,depth:!0},t));if(!r)throw Error(`Sigma: WebGL 2 is not supported by your browser. Please use a modern browser (Chrome 56+, Firefox 51+, Safari 15+, Edge 79+).`);return r.blendFunc(r.ONE,r.ONE_MINUS_SRC_ALPHA),r}},{key:`killLayer`,value:function(e){if(e===`stage`||e===`mouse`)throw Error(`Sigma: cannot kill built-in layer "${e}"`);var t=this.extraElements[e];if(!t)throw Error(`Sigma: cannot kill layer ${e}, which does not exist`);return t.remove(),delete this.extraElements[e],this}},{key:`getWebGLContext`,value:function(){if(!this.webGLContext)throw Error(`Sigma: WebGL context is not available`);return this.webGLContext}},{key:`getNodeDataTexture`,value:function(){if(!this.internals.nodeDataTexture)throw Error(`Sigma: node data texture is not available`);return this.internals.nodeDataTexture}},{key:`getNormalizationFunction`,value:function(){return this.normalizationFunction}},{key:`addCustomLayerProgram`,value:function(e,t,n){var r;if(!this.depthLayers.includes(t))throw Error(`Sigma: cannot add custom layer program at depth "${t}", it must be declared in primitives.depthLayers. Current layers: ${this.depthLayers.join(`, `)}`);return(r=this.customLayerPrograms.get(e))==null||r.program.kill(),this.customLayerPrograms.set(e,{depth:t,factory:n,program:n(this.webGLContext)}),this.refresh(),this}},{key:`removeCustomLayerProgram`,value:function(e){var t=this.customLayerPrograms.get(e);return t&&(t.program.kill(),this.customLayerPrograms.delete(e),this.scheduleRender()),this}},{key:`getCamera`,value:function(){return this.camera}},{key:`setCamera`,value:function(e){return this.camera.cancelAnimation(),this.unbindCameraHandlers(),this.camera=e,this.bindCameraHandlers(),this.scheduleRender(),this}},{key:`getContainer`,value:function(){return this.container}},{key:`getGraph`,value:function(){return this.internals.graph}},{key:`setGraph`,value:function(e){return e===this.internals.graph||(this.stateManager.pruneNodes(function(t){return e.hasNode(t)}),this.stateManager.pruneEdges(function(t){return e.hasEdge(t)}),this.unbindGraphHandlers(),this.checkEdgesEventsFrame!==null&&(cancelAnimationFrame(this.checkEdgesEventsFrame),this.checkEdgesEventsFrame=null),this.internals.graph=e,this.autoRescaleFrozen=!1,this.bindGraphHandlers(),this.refresh()),this}},{key:`getMouseCaptor`,value:function(){return this.mouseCaptor}},{key:`getTouchCaptor`,value:function(){return this.touchCaptor}},{key:`getDimensions`,value:function(){return{width:this.width,height:this.height}}},{key:`getGraphDimensions`,value:function(){var e=this.customBBox||this.nodeExtent;return{width:e.x[1]-e.x[0]||1,height:e.y[1]-e.y[0]||1}}},{key:`getNodeDisplayData`,value:function(e){var t=this.internals.nodeDataCache[e];return t?Object.assign({},t):void 0}},{key:`getEdgeDisplayData`,value:function(e){var t=this.internals.edgeDataCache[e];return t?Object.assign({},t):void 0}},{key:`getNodeState`,value:function(e){return this.stateManager.getNodeState(e)}},{key:`getEdgeState`,value:function(e){return this.stateManager.getEdgeState(e)}},{key:`getGraphState`,value:function(){return this.stateManager.getGraphState()}},{key:`setNodeState`,value:function(e,t){return this.stateManager.setNodeState(e,t),this}},{key:`setEdgeState`,value:function(e,t){return this.stateManager.setEdgeState(e,t),this}},{key:`setGraphState`,value:function(e){return this.stateManager.setGraphState(e),this}},{key:`_setPanning`,value:function(e){this.stateManager.setGraphState({isPanning:e})}},{key:`_setZooming`,value:function(e){this.stateManager.setGraphState({isZooming:e})}},{key:`_hasNodeDrag`,value:function(){var e=this.internals.dragManager;return!!(e.pendingNode||e.session)}},{key:`_showGestureHint`,value:function(e){var t=this.internals.settings;t.gestureTarget===`shared`&&(this.gestureHint=this.gestureHint||new Lc(this.container),this.gestureHint.show(e,t))}},{key:`setNodesState`,value:function(e,t){return this.stateManager.setNodesState(e,t),this}},{key:`setEdgesState`,value:function(e,t){return this.stateManager.setEdgesState(e,t),this}},{key:`updateContainerCursor`,value:function(){var e=this.stateManager.hovered,t=this.resolvedStageStyle.cursor||``;this.container.style.cursor=e&&pc(this.internals,e)||t}},{key:`refreshStageStyle`,value:function(){this.resolvedStageStyle=wr(this.stylesDeclaration.stage,this.stateManager.graphState),this.resolvedStageStyle.background!==void 0&&(this.container.style.backgroundColor=this.resolvedStageStyle.background),this.updateContainerCursor()}},{key:`getNodeDisplayedLabels`,value:function(){return new Set(this.labelRenderer.displayedNodeLabels)}},{key:`getEdgeDisplayedLabels`,value:function(){return new Set(this.labelRenderer.displayedEdgeLabels)}},{key:`getSettings`,value:function(){return W({},this.internals.settings)}},{key:`getSetting`,value:function(e){return this.internals.settings[e]}},{key:`getStyles`,value:function(){return W({},this.stylesDeclaration)}},{key:`getPrimitives`,value:function(){return W({},this.internals.primitives)}},{key:`setSetting`,value:function(e,t){return this.internals.settings[e]=t,Ur(this.internals.settings),this.handleSettingsUpdate(),this.scheduleRefresh(),this}},{key:`updateSetting`,value:function(e,t){return this.setSetting(e,t(this.internals.settings[e])),this}},{key:`setSettings`,value:function(e){return this.internals.settings=W(W({},this.internals.settings),e),Ur(this.internals.settings),this.handleSettingsUpdate(),this.scheduleRefresh(),this}},{key:`resize`,value:function(e){var t=this.width,n=this.height;if(this.width=this.container.offsetWidth,this.height=this.container.offsetHeight,this.internals.pixelRatio=Yr(),this.width===0){if(this.internals.settings.allowInvalidContainer)this.width=1;else throw Error(`Sigma: Container has no width. You can set the allowInvalidContainer setting to true to stop seeing this error.`)}if(this.height===0){if(this.internals.settings.allowInvalidContainer)this.height=1;else throw Error(`Sigma: Container has no height. You can set the allowInvalidContainer setting to true to stop seeing this error.`)}if(!e&&t===this.width&&n===this.height)return this;this.labelRenderer.labelsDirty=!0;for(var r=0,i=[this.mouseLayer].concat(Y(Object.values(this.extraElements)));r<i.length;r++){var a=i[r];a.style.width=this.width+`px`,a.style.height=this.height+`px`}return this.webGLContext&&(this.stageCanvas.setAttribute(`width`,this.width*this.internals.pixelRatio+`px`),this.stageCanvas.setAttribute(`height`,this.height*this.internals.pixelRatio+`px`),this.webGLContext.viewport(0,0,this.width*this.internals.pixelRatio,this.height*this.internals.pixelRatio)),this.emit(`resize`),this}},{key:`clear`,value:function(){return this.emit(`beforeClear`),this.webGLContext.bindFramebuffer(WebGLRenderingContext.FRAMEBUFFER,null),this.webGLContext.clear(WebGLRenderingContext.COLOR_BUFFER_BIT),this.emit(`afterClear`),this}},{key:`scheduleStateRefresh`,value:function(){this.needToRefreshState=!0,this.scheduleRender()}},{key:`refreshState`,value:function(){var e=this,t;this.stateManager.flushGraphStateFlags();var n=this.stateManager.graphStateChanged&&this.internals.nodeStyleAnalysis.dependency===`graph-state`,r=this.stateManager.graphStateChanged&&this.edgeStyleAnalysis.dependency===`graph-state`,i=!1;if(n)this.internals.graph.forEachNode(function(t){e.refreshNodeState(t)&&(i=!0)});else if(this.internals.nodeStyleAnalysis.dependency!==`static`){var a=H(this.stateManager.dirtyNodes),o;try{for(a.s();!(o=a.n()).done;){var s=o.value;this.refreshNodeState(s)&&(i=!0)}}catch(e){a.e(e)}finally{a.f()}}if(r)this.internals.graph.forEachEdge(function(t){e.refreshEdgeState(t)&&(i=!0)});else if(this.edgeStyleAnalysis.dependency!==`static`){var c=H(this.stateManager.dirtyEdges),l;try{for(c.s();!(l=c.n()).done;){var u=l.value;this.refreshEdgeState(u)&&(i=!0)}}catch(e){c.e(e)}finally{c.f()}}this.stateManager.graphStateChanged&&(t=this.stylesDeclaration)!=null&&t.stage&&this.refreshStageStyle(),this.stateManager.clearDirtyTracking(),i&&(this.pendingProcess=`full`)}},{key:`refreshNodeState`,value:function(e){var t=this.internals.nodeDataCache[e];if(!t||this.nodeReducer){var n,r=this.internals.nodeDataCache[e]?.depth,i=this.internals.nodeDataCache[e]?.zIndex,a=this.internals.nodeDataCache[e]?.labelAttachment;this.updateNode(e);var o=this.internals.nodeDataCache[e];this.internals.attachmentManager&&o.labelAttachment!==a&&this.internals.attachmentManager.invalidateNode(e);var s=this.internals.nodeShapeMap&&this.internals.nodeGlobalShapeIds&&o.shape&&o.shape in this.internals.nodeShapeMap?this.internals.nodeGlobalShapeIds[this.internals.nodeShapeMap[o.shape]]:ui(o.shape||`circle`);(n=this.internals.nodeDataTexture).updateNode.apply(n,[e,o.x,o.y,o.size,s].concat(Y(Lr(o)),[o.color])),r&&o.depth!==r&&this.updateNodeDepthRanges(e,r,o.depth);var c=this.nodeProgramIndex[e];return c!==void 0&&(this.addNodeToProgram(e,c),this.nodeProgram.invalidateBuffers()),i!==void 0&&o.zIndex!==i}var l=this.internals.graph.getNodeAttributes(e),u=this.stateManager.getNodeState(e),d=t.size,f=t.shape,p=t.depth,m=t.zIndex,h=t.labelAttachment,g=t.rotationAlignment,_=t.labelRotationAlignment,v=t.color;xr(this.stylesDeclaration.nodes,l,u,this.stateManager.graphState,this.internals.graph,t),this.postEvaluateNode(t,l,u);var y=this.nodeGraphCoords[e],b=t.x!==y.x||t.y!==y.y;if(b&&(y.x=t.x,y.y=t.y),this.normalizationFunction.applyTo(t),this.internals.nodeShapeMap?(!t.shape||!(t.shape in this.internals.nodeShapeMap))&&(t.shape=Object.keys(this.internals.nodeShapeMap)[0]):this.nodeShapeSlug&&(t.shape=this.nodeShapeSlug),this.internals.attachmentManager&&t.labelAttachment!==h&&this.internals.attachmentManager.invalidateNode(e),Mr(this.internals.nodesWithForcedLabels,e,Fr(t)),Mr(this.internals.nodesWithBackdrop,e,Ir(t)),b||t.size!==d||t.shape!==f||t.rotationAlignment!==g||t.labelRotationAlignment!==_||t.color!==v){var x,S=this.internals.nodeShapeMap&&this.internals.nodeGlobalShapeIds&&t.shape&&t.shape in this.internals.nodeShapeMap?this.internals.nodeGlobalShapeIds[this.internals.nodeShapeMap[t.shape]]:ui(t.shape||`circle`);(x=this.internals.nodeDataTexture).updateNode.apply(x,[e,t.x,t.y,t.size,S].concat(Y(Lr(t)),[t.color]))}this.itemBuckets.nodes.set(e,t.depth),t.depth!==p&&this.updateNodeDepthRanges(e,p,t.depth);var C=this.nodeProgramIndex[e];return C!==void 0&&(this.addNodeToProgram(e,C),this.nodeProgram.invalidateBuffers()),t.zIndex!==m}},{key:`refreshEdgeState`,value:function(e){var t=this.internals.edgeDataCache[e];if(!t||this.edgeReducer){var n=t?.depth,r=t?.zIndex;this.updateEdge(e);var i=this.internals.edgeDataCache[e];n&&i.depth!==n&&this.updateEdgeDepthRanges(e,n,i.depth);var a=this.edgeProgramIndex[e];return a!==void 0&&(this.addEdgeToProgram(e,a),this.edgeProgram.invalidateBuffers()),r!==void 0&&i.zIndex!==r}var o=this.internals.graph.getEdgeAttributes(e),s=this.stateManager.getEdgeState(e),c=t.depth,l=t.zIndex,u=t.size,d=t.path,f=t.selfLoopPath,p=t.parallelPath,m=t.head,h=t.tail;Sr(this.stylesDeclaration.edges,o,s,this.stateManager.graphState,this.internals.graph,t),this.postEvaluateEdge(t,o),this.applyEdgeSpread(e,t,s),Mr(this.internals.edgesWithForcedLabels,e,Fr(t)),this.itemBuckets.edges.set(e,t.depth),t.depth!==c&&this.updateEdgeDepthRanges(e,c,t.depth);var g=this.edgeProgramIndex[e];if(g!==void 0){if(t.size!==u||t.path!==d||t.selfLoopPath!==f||t.parallelPath!==p||t.head!==m||t.tail!==h)this.addEdgeToProgram(e,g),this.edgeProgram.invalidateBuffers();else{var _=this.internals.graph.source(e),v=this.internals.graph.target(e),y=this.internals.nodeDataCache[_],b=this.internals.nodeDataCache[v],x=this.edgeTextureIndexCache[e];this.edgeProgram.process(sc(this.pickingState,`edge`,e),g,y,b,t,x),this.edgeProgram.invalidateBuffers()}}return t.zIndex!==l}},{key:`refresh`,value:function(e){var t=this,n=e?.skipIndexation!==void 0&&e?.skipIndexation,r=e?.schedule!==void 0&&e.schedule;if(!e||!e.partialGraph)this.clearEdgeIndices(),this.clearNodeIndices(),this.internals.graph.forEachNode(function(e){return t.addNode(e)}),this.edgeGroups.rebuild(),this.internals.graph.forEachEdge(function(e){return t.addEdge(e)}),this.pendingProcess=`full`;else{for(var i,a=e.partialGraph?.nodes||[],o=0,s=a?.length||0;o<s;o++){var c,l=``+a[o],u=this.internals.nodeDataCache[l]?.labelAttachment;if(this.updateNode(l),this.internals.attachmentManager&&((c=this.internals.nodeDataCache[l])!=null&&c.labelAttachment||u)&&this.internals.attachmentManager.invalidateNode(l),n){var d=this.nodeProgramIndex[l];if(d===void 0)throw Error(`Sigma: node "${l}" can't be repaint`);this.addNodeToProgram(l,d)}}n&&a.length>0&&(this.nodeProgram.invalidateBuffers(),this.labelRenderer.labelsDirty=!0);for(var f=(e==null||(i=e.partialGraph)==null?void 0:i.edges)||[],p=0,m=f.length;p<m;p++){var h=``+f[p];if(this.updateEdge(h),n){var g=this.edgeProgramIndex[h];if(g===void 0)throw Error(`Sigma: edge "${h}" can't be repaint`);this.addEdgeToProgram(h,g)}}n&&f.length>0&&(this.edgeProgram.invalidateBuffers(),this.labelRenderer.labelsDirty=!0),!n&&this.pendingProcess!==`full`&&(this.pendingProcess=f.length>0?`full`:`nodes`)}return r?this.scheduleRender():this.render(),this}},{key:`scheduleRender`,value:function(){var e=this;return this.renderFrame||=requestAnimationFrame(function(){e.render()}),this}},{key:`scheduleRefresh`,value:function(e){return this.refresh(W(W({},e),{},{schedule:!0}))}},{key:`getViewportZoomedState`,value:function(e,t){var n=this.camera.getState(),r=n.ratio,i=n.angle,a=n.x,o=n.y,s=this.internals.settings,c=s.minCameraRatio,l=s.maxCameraRatio;typeof l==`number`&&(t=Math.min(t,l)),typeof c==`number`&&(t=Math.max(t,c));var u=t/r,d={x:this.width/2,y:this.height/2},f=this.viewportToFramedGraph(e),p=this.viewportToFramedGraph(d);return{angle:i,x:(f.x-p.x)*(1-u)+a,y:(f.y-p.y)*(1-u)+o,ratio:t}}},{key:`viewRectangle`,value:function(){var e=this.viewportToFramedGraph({x:0,y:0}),t=this.viewportToFramedGraph({x:this.width,y:0}),n=this.viewportToFramedGraph({x:0,y:this.height});return{x1:e.x,y1:e.y,x2:t.x,y2:t.y,height:t.y-n.y}}},{key:`framedGraphToViewport`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=!!t.cameraState||!!t.viewportDimensions||!!t.graphDimensions||!!t.padding,r=Wt(t.matrix||(n?Kt(t.cameraState||this.camera.getState(),t.viewportDimensions||this.getDimensions(),t.graphDimensions||this.getGraphDimensions(),t.padding||this.getStagePadding()):this.matrix),e);return{x:(1+r.x)*this.width/2,y:(1-r.y)*this.height/2}}},{key:`viewportToFramedGraph`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=!!t.cameraState||!!t.viewportDimensions||!!t.graphDimensions||!!t.padding,r=Wt(t.matrix||(n?Kt(t.cameraState||this.camera.getState(),t.viewportDimensions||this.getDimensions(),t.graphDimensions||this.getGraphDimensions(),t.padding||this.getStagePadding(),!0):this.invMatrix),{x:e.x/this.width*2-1,y:1-e.y/this.height*2});return isNaN(r.x)&&(r.x=0),isNaN(r.y)&&(r.y=0),r}},{key:`viewportToGraph`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return this.normalizationFunction.inverse(this.viewportToFramedGraph(e,t))}},{key:`graphToViewport`,value:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return this.framedGraphToViewport(this.normalizationFunction(e),t)}},{key:`graphToFramedGraph`,value:function(e){return this.normalizationFunction(e)}},{key:`framedGraphToGraph`,value:function(e){return this.normalizationFunction.inverse(e)}},{key:`getGraphToViewportRatio`,value:function(){var e={x:0,y:0},t={x:1,y:1},n=Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2),r=this.graphToViewport(e),i=this.graphToViewport(t);return Math.sqrt((r.x-i.x)**2+(r.y-i.y)**2)/n}},{key:`computeNodeExtent`,value:function(){var e=this.nodeGraphCoords,t=Object.keys(e);if(!t.length)return{x:[0,1],y:[0,1]};for(var n=1/0,r=-1/0,i=1/0,a=-1/0,o=0,s=t.length;o<s;o++){var c=e[t[o]],l=c.x,u=c.y;l<n&&(n=l),l>r&&(r=l),u<i&&(i=u),u>a&&(a=u)}return{x:[n,r],y:[i,a]}}},{key:`getBBox`,value:function(){return this.nodeExtent}},{key:`getCustomBBox`,value:function(){return this.customBBox}},{key:`setCustomBBox`,value:function(e){return this.customBBox=e,this.scheduleRender(),this}},{key:`kill`,value:function(){var e,t,n;this.emit(`kill`),this.removeAllListeners(),this.camera.cancelAnimation(),this.unbindCameraHandlers(),window.removeEventListener(`resize`,this.activeListeners.handleResize),this.mouseCaptor.kill(),this.touchCaptor.kill(),this.internals.hoverResolver.kill(),this.unbindGraphHandlers(),this.clearIndices(),this.clearState(),this.internals.nodeDataCache={},this.internals.edgeDataCache={},this.renderFrame&&=(cancelAnimationFrame(this.renderFrame),null);for(var r=this.container;r.firstChild;)r.removeChild(r.firstChild);this.nodeProgram.kill(),this.nodeFramePass.kill(),this.edgeProgram.kill(),this.edgeFramePass.kill(),this.internals.labelProgram.kill(),this.internals.edgeLabelProgram.kill(),this.internals.edgeLabelBackgroundProgram.kill(),this.internals.backdropProgram.kill(),this.internals.labelBackgroundProgram.kill(),(e=this.internals.attachmentProgram)==null||e.kill(),(t=this.internals.attachmentManager)==null||t.kill(),this.internals.attachmentProgram=null,this.internals.attachmentManager=null;var i=H(this.customLayerPrograms.values()),a;try{for(i.s();!(a=i.n()).done;)a.value.program.kill()}catch(e){i.e(e)}finally{i.f()}if(this.customLayerPrograms.clear(),this.sdfAtlas&&=null,this.internals.nodeDataTexture&&(this.internals.nodeDataTexture.kill(),this.internals.nodeDataTexture=null),this.internals.nodeFrameTexture&&(this.internals.nodeFrameTexture.kill(),this.internals.nodeFrameTexture=null),this.internals.edgeDataTexture&&(this.internals.edgeDataTexture.kill(),this.internals.edgeDataTexture=null),this.internals.edgeFrameTexture&&(this.internals.edgeFrameTexture.kill(),this.internals.edgeFrameTexture=null),this.webGLContext){var o;(o=this.webGLContext.getExtension(`WEBGL_lose_context`))==null||o.loseContext(),this.webGLContext=null}for(var s in(n=this.gestureHint)==null||n.kill(),this.gestureHint=null,this.mouseLayer.remove(),this.extraElements)this.extraElements[s].remove();this.extraElements={}}},{key:`scaleSize`,value:function(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:1,t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:this.camera.ratio;return e/this.internals.settings.zoomToSizeRatioFunction(t)*(this.getSetting(`itemSizesReference`)===`positions`?t*this.graphToViewportRatio:1)}},{key:`getStageCanvas`,value:function(){return this.stageCanvas}},{key:`getMouseLayer`,value:function(){return this.mouseLayer}}])}(Er),tl=[`cuisine`,`dish`,`protein`,`diet`,`starch`,`flavor`,`allergen`,`technique`,`equipment`,`chef`],nl={recipe:`#c2410c`,ingredient:`#3f7d4a`,cuisine:`#2563eb`,dish:`#7c3aed`,protein:`#b45309`,diet:`#0d9488`,starch:`#a16207`,flavor:`#db2777`,allergen:`#b42318`,technique:`#4b5563`,equipment:`#64748b`,chef:`#0369a1`},rl=`rgba(150,140,130,0.18)`;function il(e){return e.kind===`recipe`?nl.recipe??`#c2410c`:e.kind===`ingredient`?nl.ingredient??`#3f7d4a`:nl[e.group??``]??`#6b7280`}function al(){let d=c(),[f,p]=n([`cuisine`,`dish`,`protein`,`diet`]),[m,h]=n(!0),[g,_]=n(2),[v,y]=n(!1),[b,x]=n(``),[S,C]=n(null),w=i(null),T=i(null),E=i(null),D=s(()=>e.graph({categories:f,ingredients:m,min_degree:g,similar:v?3:void 0}),[f.join(`,`),m,g,v]),O=u(()=>new Map((D.data?.nodes??[]).map(e=>[e.id,e])),[D.data]);t(()=>{let e=D.data;if(!e||!w.current)return;let t=new B({multi:!1,type:`undirected`});for(let n of e.nodes){let e=n.kind===`recipe`?6:3+Math.sqrt(n.degree)*2;t.addNode(n.id,{label:n.kind===`tag`?a(n.label):n.label,size:e,color:il(n),baseColor:il(n),x:Math.random()*100,y:Math.random()*100})}for(let n of e.edges){if(!t.hasNode(n.source)||!t.hasNode(n.target)||t.hasEdge(n.source,n.target))continue;let e=n.kind===`similar`?`rgba(194,65,12,0.45)`:n.kind===`derived_from`?`rgba(124,58,237,0.6)`:`rgba(150,140,130,0.25)`;t.addEdge(n.source,n.target,{size:n.kind===`similar`||n.kind===`derived_from`?1.5:.6,color:e,baseColor:e})}t.order>1&&Mt.default.assign(t,{iterations:t.order>800?150:300,settings:{...Mt.default.inferSettings(t),barnesHutOptimize:t.order>400}}),E.current?.kill(),T.current=t;let n=getComputedStyle(document.documentElement),r=n.getPropertyValue(`--text`).trim()||`#2b2420`,i=n.getPropertyValue(`--surface`).trim()||`#ffffff`,o=new el(t,w.current,{settings:{labelRenderedSizeThreshold:7,autoRescaleContent:`nodes`},styles:{...$n,nodes:{...$n.nodes,labelColor:r,backdropColor:i}}});E.current=o;let s=e=>{let n=e?new Set([e,...t.neighbors(e)]):null;t.forEachNode((e,r)=>t.setNodeAttribute(e,`color`,!n||n.has(e)?r.baseColor:rl)),t.forEachEdge((n,r,i,a)=>t.setEdgeAttribute(n,`color`,!e||i===e||a===e?r.baseColor:`rgba(150,140,130,0.06)`))};return o.on(`enterNode`,({node:e})=>s(e)),o.on(`leaveNode`,()=>s(null)),o.on(`clickNode`,({node:e})=>C(e)),o.on(`clickStage`,()=>C(null)),()=>{o.kill(),E.current=null}},[D.data]);let k=e=>{let t=E.current,n=t?.getNodeDisplayData(e);t&&n&&t.getCamera().animate({x:n.x,y:n.y,ratio:.35},{duration:500}),C(e)},A=S?O.get(S):void 0,j=S&&T.current?.hasNode(S)?T.current.neighbors(S).map(e=>O.get(e)).filter(e=>!!e):[],M=b.trim().length>=2?(D.data?.nodes??[]).filter(e=>e.label.toLowerCase().includes(b.trim().toLowerCase())).slice(0,8):[];return r(`div`,{class:`graph-wrap`,children:[r(`aside`,{class:`panel stack side`,children:[r(`div`,{children:[r(`h3`,{children:`Find`}),r(`input`,{type:`search`,placeholder:`Recipe, ingredient, tag…`,value:b,onInput:e=>x(e.target.value)}),M.map(e=>r(`div`,{children:r(`button`,{type:`button`,class:`ghost small`,onClick:()=>k(e.id),children:[r(`span`,{class:`dot`,style:{background:il(e)}}),e.label]})},e.id))]}),r(`div`,{children:[r(`h3`,{children:`Show`}),r(`label`,{class:`row small`,children:[r(`input`,{type:`checkbox`,checked:m,onChange:e=>h(e.target.checked)}),`Ingredients`]}),r(`label`,{class:`row small`,children:[r(`input`,{type:`checkbox`,checked:v,onChange:e=>y(e.target.checked)}),`Similar-recipe links`]}),r(`div`,{class:`row`,style:{marginTop:`0.5rem`},children:tl.map(e=>r(l,{tone:f.includes(e)?`on`:void 0,onClick:()=>p(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e]),children:[r(`span`,{class:`dot`,style:{background:nl[e]}}),e]},e))})]}),r(`div`,{children:[r(`h3`,{children:[`Hide nodes linked to fewer than `,g,` recipes`]}),r(`input`,{type:`range`,min:1,max:10,value:g,onInput:e=>_(Number(e.target.value))})]}),D.data&&r(`div`,{class:`muted small`,children:[D.data.stats.recipes,` recipes · `,D.data.stats.ingredients,` ingredients ·`,` `,D.data.stats.tags,` tags · `,D.data.stats.edges,` links`]}),r(`div`,{class:`legend`,children:[r(`span`,{children:[r(`span`,{class:`dot`,style:{background:nl.recipe}}),`recipe`]}),r(`span`,{children:[r(`span`,{class:`dot`,style:{background:nl.ingredient}}),`ingredient`]})]})]}),r(`div`,{class:`graph-canvas`,children:[r(`div`,{class:`sigma`,ref:w}),D.loading&&!D.data&&r(`div`,{class:`empty`,children:`Laying out the graph…`}),D.data&&D.data.nodes.length===0&&r(`div`,{class:`empty`,children:`No recipes yet.`})]}),r(`aside`,{class:`panel side`,children:A?r(`div`,{class:`stack`,children:[r(`div`,{class:`muted small`,children:A.kind===`tag`?A.group:A.kind}),r(`h2`,{children:A.kind===`tag`?a(A.label):A.label}),A.kind===`recipe`&&A.image&&r(`img`,{src:o(A.image,400),alt:``,style:{width:`100%`,borderRadius:`10px`}}),A.kind===`recipe`?r(`button`,{type:`button`,class:`primary`,onClick:()=>d.route(`/recipe/${A.slug}`),children:`Open recipe`}):r(`a`,{href:`/?${A.kind===`tag`?`tags=${encodeURIComponent(JSON.stringify({[A.group??`other`]:[A.label]}))}`:`q=${encodeURIComponent(A.label)}`}`,children:`Search recipes with this →`}),r(`div`,{children:[r(`h3`,{children:[`Connected (`,j.length,`)`]}),j.sort((e,t)=>e.kind===t.kind?e.label.localeCompare(t.label):e.kind===`recipe`?-1:1).map(e=>r(`div`,{children:r(`button`,{type:`button`,class:`ghost small`,onClick:()=>k(e.id),children:[r(`span`,{class:`dot`,style:{background:il(e)}}),e.kind===`tag`?a(e.label):e.label]})},e.id))]})]}):r(`div`,{class:`muted small`,children:`Hover a node to highlight its neighbourhood; click it for details. Ingredients shared by many recipes and tags like cuisine and dish pull related recipes together.`})})]})}export{al as GraphPage};
|