@@ -11162,7 +11162,11 @@ elesfn$b.updateCompoundBounds = function () {
1116211162 return;
1116311163 }
1116411164 var _p = parent._private;
11165- var children = parent.children();
11165+ // SM customization: allow parent nodes to specify a selector that filters which children
11166+ // are used for compound bounds calculation via data('childrenSelectorForBounds').
11167+ // If not set, all children are used (default upstream behavior).
11168+ var childrenSelectorForBounds = parent.data('childrenSelectorForBounds');
11169+ var children = parent.children(childrenSelectorForBounds);
1116611170 var includeLabels = parent.pstyle('compound-sizing-wrt-labels').value === 'include';
1116711171 var min = {
1116811172 width: {
@@ -25645,7 +25649,10 @@ BRp$3.load = function () {
2564525649 var isMultSelKeyDown = function isMultSelKeyDown(e) {
2564625650 return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey
2564725651 };
25648- var allowPanningPassthrough = function allowPanningPassthrough(down, downs) {
25652+
25653+ // SM customization: default panning passthrough logic extracted so it can be overridden
25654+ // via cy.options().overrides.allowPanningPassthrough to customize compound node panning behavior.
25655+ var allowPanningPassthroughDefault = function allowPanningPassthroughDefault(down, downs) {
2564925656 var allowPassthrough = true;
2565025657 if (r.cy.hasCompoundNodes() && down && down.pannable()) {
2565125658 // a grabbable compound node below the ele => no passthrough panning
@@ -25663,6 +25670,12 @@ BRp$3.load = function () {
2566325670 }
2566425671 return allowPassthrough;
2566525672 };
25673+ var allowPanningPassthrough = function allowPanningPassthrough(down, downs) {
25674+ var _ref = r.cy.options().overrides || {},
25675+ _ref$allowPanningPass = _ref.allowPanningPassthrough,
25676+ allowPanningPassthrough = _ref$allowPanningPass === undefined ? allowPanningPassthroughDefault : _ref$allowPanningPass;
25677+ return allowPanningPassthrough(down, downs);
25678+ };
2566625679 var setGrabbed = function setGrabbed(ele) {
2566725680 ele[0]._private.grabbed = true;
2566825681 };
@@ -28890,7 +28903,9 @@ var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing
2889028903var deqFastCost = 0.9; // % of frame time to be used when >60fps
2889128904var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch
2889228905var invalidThreshold = 250; // time threshold for disabling b/c of invalidations
28893- var maxLayerArea = 4000 * 4000; // layers can't be bigger than this
28906+ // SM customization: increased from 4000*4000 to 10000*10000 to support larger graphs
28907+ // without falling back to direct rendering (which is slower for complex scenes).
28908+ var maxLayerArea = 10000 * 10000; // layers can't be bigger than this
2889428909var maxLayerDim = 32767; // maximum size for the width/height of layer canvases
2889528910var useHighQualityEleTxrReqs = true; // whether to use high quality ele txr requests (generally faster and cheaper in the longterm)
2889628911
@@ -28902,6 +28917,9 @@ var LayeredTextureCache = function LayeredTextureCache(renderer) {
2890228917 var cy = r.cy;
2890328918 self.layersByLevel = {}; // e.g. 2 => [ layer1, layer2, ..., layerN ]
2890428919
28920+ // SM customization: persist the bounding box across getLayers() calls so it doesn't
28921+ // need to be recomputed from scratch each time. Cleared on invalidation.
28922+ self.bb = null;
2890528923 self.firstGet = true;
2890628924 self.lastInvalidationTime = performanceNow() - 2 * invalidThreshold;
2890728925 self.skipping = false;
@@ -28978,7 +28996,6 @@ LTCp.getLayers = function (eles, pxRatio, lvl) {
2897828996 var layersByLvl = self.layersByLevel;
2897928997 var scale = Math.pow(2, lvl);
2898028998 var layers = layersByLvl[lvl] = layersByLvl[lvl] || [];
28981- var bb;
2898228999 var lvlComplete = self.levelIsComplete(lvl, eles);
2898329000 var tmpLayers;
2898429001 var checkTempLevels = function checkTempLevels() {
@@ -29019,19 +29036,28 @@ LTCp.getLayers = function (eles, pxRatio, lvl) {
2901929036 // log('level complete, using existing layers\n--');
2902029037 return layers;
2902129038 }
29022- var getBb = function getBb() {
29023- if (!bb) {
29024- bb = makeBoundingBox();
29025- for (var i = 0; i < eles.length; i++) {
29026- updateBoundingBox(bb, eles[i].boundingBox());
29039+
29040+ // SM customization: use self.bb (persistent across calls) instead of a local bb variable.
29041+ // Also adds early-exit if the accumulated layer area exceeds maxLayerArea during incremental
29042+ // bounding box computation, preventing massive texture allocation for very large graphs.
29043+ function getBb() {
29044+ if (!self.bb) {
29045+ self.bb = makeBoundingBox();
29046+ }
29047+ for (var i = 0; i < eles.length; i++) {
29048+ var area = self.bb.w * scale * (self.bb.h * scale);
29049+ if (area > maxLayerArea) {
29050+ return null;
2902729051 }
29052+ updateBoundingBox(self.bb, eles[i].boundingBox());
2902829053 }
29029- return bb;
29030- };
29054+ return self. bb;
29055+ }
2903129056 var makeLayer = function makeLayer(opts) {
2903229057 opts = opts || {};
2903329058 var after = opts.after;
29034- getBb();
29059+ var bb = getBb();
29060+ if (!bb) return null;
2903529061 var w = Math.ceil(bb.w * scale);
2903629062 var h = Math.ceil(bb.h * scale);
2903729063 if (w > maxLayerDim || h > maxLayerDim) {
@@ -29619,19 +29645,37 @@ var getOpacity = function getOpacity(r, ele) {
2961929645var getTextOpacity = function getTextOpacity(e, ele) {
2962029646 return ele.pstyle('text-opacity').pfValue * ele.effectiveOpacity();
2962129647};
29648+
29649+ // SM customization: faster extent check using node position instead of full bounding box intersection.
29650+ // Uses a padding of 150px to account for node size / labels near the viewport edge.
29651+ var EXTENT_PADDING = 150;
29652+ function isPosInExtent(pos, extent) {
29653+ return extent.x1 - EXTENT_PADDING <= pos.x && pos.x <= extent.x2 + EXTENT_PADDING && extent.y1 - EXTENT_PADDING <= pos.y && pos.y <= extent.y2 + EXTENT_PADDING;
29654+ }
29655+
29656+ // SM customization: default extent check for elements. Edges always pass (their endpoints
29657+ // handle visibility). Nodes use the simpler position-based check for better pan/zoom perf.
29658+ // Can be overridden via cy.options().overrides.isElementInExtent.
29659+ function isElementInExtentDefault(ele, extent) {
29660+ if (!ele.isNode()) return true;
29661+ return isPosInExtent(ele.position(), extent);
29662+ }
2962229663CRp$a.drawCachedElement = function (context, ele, pxRatio, extent, lvl, requestHighQuality) {
29664+ // SM customization: allow overriding the extent check via cy.options().overrides.isElementInExtent
29665+ var _ref = ele.cy().options().overrides || {},
29666+ _ref$isElementInExten = _ref.isElementInExtent,
29667+ isElementInExtent = _ref$isElementInExten === undefined ? isElementInExtentDefault : _ref$isElementInExten;
2962329668 var r = this;
2962429669 var _r$data = r.data,
2962529670 eleTxrCache = _r$data.eleTxrCache,
2962629671 lblTxrCache = _r$data.lblTxrCache,
2962729672 slbTxrCache = _r$data.slbTxrCache,
2962829673 tlbTxrCache = _r$data.tlbTxrCache;
29629- var bb = ele.boundingBox();
2963029674 var reason = requestHighQuality === true ? eleTxrCache.reasons.highQuality : null;
29631- if (bb.w === 0 || bb.h === 0 || !ele.visible()) {
29675+ if (!ele.visible()) {
2963229676 return;
2963329677 }
29634- if (!extent || boundingBoxesIntersect(bb , extent)) {
29678+ if (!extent || isElementInExtent(ele , extent)) {
2963529679 var isEdge = ele.isEdge();
2963629680 var badLine = ele.element()._private.rscratch.badLine;
2963729681 r.drawElementUnderlay(context, ele);
@@ -35552,7 +35596,7 @@ sheetfn.appendToStyle = function (style) {
3555235596 return style;
3555335597};
3555435598
35555- var version = "3.33.2 ";
35599+ var version = "snapshot ";
3555635600
3555735601var cytoscape = function cytoscape(options) {
3555835602 // if no options specified, use default
0 commit comments