@expofp/renderer 2.2.0 → 2.3.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/dist/index.d.ts +10 -0
- package/dist/index.js +168 -73
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -691,6 +691,16 @@ export declare interface ViewportAPI {
|
|
|
691
691
|
* @param dynamicTransformMatrix dynamic transform matrix (changes every frame)
|
|
692
692
|
*/
|
|
693
693
|
setDynamicTransform: (dynamicTransformMatrix: number[]) => void;
|
|
694
|
+
/**
|
|
695
|
+
* Set the maximum zoom factor. Default is 35.
|
|
696
|
+
* @param maxZoom Maximum zoom factor
|
|
697
|
+
*/
|
|
698
|
+
setMaxZoom: (maxZoom: number) => void;
|
|
699
|
+
/**
|
|
700
|
+
* Set the minimum zoom factor. Default is 0.1.
|
|
701
|
+
* @param minZoom Minimum zoom factor
|
|
702
|
+
*/
|
|
703
|
+
setMinZoom: (minZoom: number) => void;
|
|
694
704
|
}
|
|
695
705
|
|
|
696
706
|
/** Options for the {@link ControlsAPI.zoomTo} method. */
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
var _a;
|
|
5
|
-
import { DataTexture, FloatType, UnsignedIntType, IntType, RGBAFormat, RGBAIntegerFormat, RGFormat, RGIntegerFormat, RedFormat, RedIntegerFormat, BatchedMesh as BatchedMesh$1, BufferAttribute, StreamDrawUsage, Color, Matrix4, Vector3, Vector4, AlwaysDepth, DoubleSide, MeshBasicMaterial, Texture, Group, PlaneGeometry, SRGBColorSpace, Vector2, Quaternion, BufferGeometry, Mesh, LessEqualDepth, LinearSRGBColorSpace, Plane, Raycaster,
|
|
5
|
+
import { DataTexture, FloatType, UnsignedIntType, IntType, RGBAFormat, RGBAIntegerFormat, RGFormat, RGIntegerFormat, RedFormat, RedIntegerFormat, BatchedMesh as BatchedMesh$1, BufferAttribute, StreamDrawUsage, Color, Matrix4, Vector3, Frustum, Sphere, Box3, Vector4, AlwaysDepth, DoubleSide, MeshBasicMaterial, Texture, Group, PlaneGeometry, SRGBColorSpace, Vector2, Quaternion, BufferGeometry, Mesh, LessEqualDepth, LinearSRGBColorSpace, Plane, Raycaster, Spherical, PerspectiveCamera, Camera, Scene, MathUtils, Clock, WebGLRenderer } from "three";
|
|
6
6
|
import { traverseAncestorsGenerator } from "three/examples/jsm/utils/SceneUtils.js";
|
|
7
7
|
import createLog from "debug";
|
|
8
8
|
import { BatchedText as BatchedText$1, Text as Text$1 } from "troika-three-text";
|
|
@@ -551,9 +551,12 @@ class BatchedText extends BatchedText$1 {
|
|
|
551
551
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
552
552
|
constructor() {
|
|
553
553
|
super();
|
|
554
|
-
__publicField(this, "mapInstanceIdToText", /* @__PURE__ */ new Map());
|
|
555
554
|
__publicField(this, "textArray", []);
|
|
556
555
|
__publicField(this, "textureNeedsUpdate", false);
|
|
556
|
+
__publicField(this, "boundsNeedsUpdate", false);
|
|
557
|
+
this.addEventListener("synccomplete", () => {
|
|
558
|
+
this.boundsNeedsUpdate = true;
|
|
559
|
+
});
|
|
557
560
|
}
|
|
558
561
|
/** Number of texts in the batch */
|
|
559
562
|
get size() {
|
|
@@ -569,7 +572,13 @@ class BatchedText extends BatchedText$1 {
|
|
|
569
572
|
* @returns Text object
|
|
570
573
|
*/
|
|
571
574
|
getText(instanceId) {
|
|
572
|
-
return this.
|
|
575
|
+
return this.textArray[instanceId];
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Mark this BatchedText as needing bounds update. This should be called when changing text transforms.
|
|
579
|
+
*/
|
|
580
|
+
invalidateBounds() {
|
|
581
|
+
this.boundsNeedsUpdate = true;
|
|
573
582
|
}
|
|
574
583
|
/**
|
|
575
584
|
* Set the visibility of the {@link Text} object by instance id.
|
|
@@ -583,17 +592,39 @@ class BatchedText extends BatchedText$1 {
|
|
|
583
592
|
}
|
|
584
593
|
addText(text, instanceId) {
|
|
585
594
|
super.addText(text);
|
|
586
|
-
if (instanceId !== void 0)
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
595
|
+
if (instanceId !== void 0) this.textArray[instanceId] = text;
|
|
596
|
+
this.boundsNeedsUpdate = true;
|
|
597
|
+
}
|
|
598
|
+
removeText(text) {
|
|
599
|
+
super.removeText(text);
|
|
600
|
+
this.textArray.splice(this.textArray.indexOf(text), 1);
|
|
601
|
+
this.boundsNeedsUpdate = true;
|
|
590
602
|
}
|
|
591
603
|
dispose() {
|
|
592
604
|
super.dispose();
|
|
605
|
+
this.textArray.length = 0;
|
|
593
606
|
this.dispatchEvent({ type: "dispose" });
|
|
594
607
|
}
|
|
595
|
-
|
|
596
|
-
|
|
608
|
+
updateBounds() {
|
|
609
|
+
if (this.boundsNeedsUpdate) {
|
|
610
|
+
const bbox = this.geometry.boundingBox.makeEmpty();
|
|
611
|
+
for (const text of this.textArray) {
|
|
612
|
+
if (!text.visible) continue;
|
|
613
|
+
if (text.matrixAutoUpdate) text.updateMatrix();
|
|
614
|
+
_box$1.copy(text.geometry.boundingBox).applyMatrix4(text.matrix);
|
|
615
|
+
bbox.union(_box$1);
|
|
616
|
+
}
|
|
617
|
+
bbox.getBoundingSphere(this.geometry.boundingSphere);
|
|
618
|
+
this.boundsNeedsUpdate = false;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
onBeforeRender(renderer, scene, camera, geometry, material) {
|
|
622
|
+
this.sync();
|
|
623
|
+
if ("isTroikaTextMaterial" in material && material.isTroikaTextMaterial) {
|
|
624
|
+
this.prepareForRender(material, scene, camera);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
prepareForRender(material, scene, camera) {
|
|
597
628
|
var _a2;
|
|
598
629
|
const isOutline = material.isTextOutlineMaterial;
|
|
599
630
|
material.uniforms.uTroikaIsOutline.value = isOutline;
|
|
@@ -612,12 +643,15 @@ class BatchedText extends BatchedText$1 {
|
|
|
612
643
|
}
|
|
613
644
|
const texData = texture.image.data;
|
|
614
645
|
this.textureNeedsUpdate = false;
|
|
646
|
+
_matrix$1.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse).multiply(scene.matrixWorld);
|
|
647
|
+
_frustum$1.setFromProjectionMatrix(_matrix$1, camera.coordinateSystem);
|
|
615
648
|
for (const text of this.textArray) {
|
|
616
649
|
const index = ((_a2 = this._members.get(text)) == null ? void 0 : _a2.index) ?? -1;
|
|
617
650
|
const textRenderInfo = text.textRenderInfo;
|
|
618
651
|
if (index < 0 || !textRenderInfo) continue;
|
|
619
652
|
const startIndex = index * floatsPerMember;
|
|
620
|
-
|
|
653
|
+
const isHidden = !text.visible || !_frustum$1.intersectsSphere(_sphere$1.copy(text.geometry.boundingSphere).applyMatrix4(text.matrix));
|
|
654
|
+
if (isHidden) {
|
|
621
655
|
for (let i = 0; i < 16; i++) {
|
|
622
656
|
this.setTexData(startIndex + i, 0, texData);
|
|
623
657
|
}
|
|
@@ -732,7 +766,6 @@ class Text extends Text$1 {
|
|
|
732
766
|
blockBounds[3] + pad
|
|
733
767
|
);
|
|
734
768
|
}
|
|
735
|
-
this.geometry.applyClipRect(uniforms.uTroikaClipRect.value);
|
|
736
769
|
}
|
|
737
770
|
uniforms.uTroikaSDFDebug.value = !!this.debugSDF;
|
|
738
771
|
material.polygonOffset = !!this.depthOffset;
|
|
@@ -764,6 +797,10 @@ class Text extends Text$1 {
|
|
|
764
797
|
}
|
|
765
798
|
}
|
|
766
799
|
}
|
|
800
|
+
const _matrix$1 = new Matrix4();
|
|
801
|
+
const _frustum$1 = new Frustum();
|
|
802
|
+
const _sphere$1 = new Sphere();
|
|
803
|
+
const _box$1 = new Box3();
|
|
767
804
|
function setDimming(root, dim) {
|
|
768
805
|
root.userData["uDim"] = dim === void 0 ? void 0 : +dim;
|
|
769
806
|
}
|
|
@@ -1842,7 +1879,8 @@ class MeshSystem extends RenderableSystem {
|
|
|
1842
1879
|
}
|
|
1843
1880
|
updateShape(shapeDef, mesh, instanceId) {
|
|
1844
1881
|
const geometryId = mesh.getGeometryIdAt(instanceId);
|
|
1845
|
-
const
|
|
1882
|
+
const key = `${mesh.uuid}-${instanceId}`;
|
|
1883
|
+
const expectedShapeType = this.mapInstanceIdToShapeType.get(key);
|
|
1846
1884
|
const shape = shapeDef.shape;
|
|
1847
1885
|
const isPolygon = shape instanceof Polygon;
|
|
1848
1886
|
const isRect = shape instanceof Rect;
|
|
@@ -1898,16 +1936,19 @@ class MeshSystem extends RenderableSystem {
|
|
|
1898
1936
|
batchedMesh.setCustomSort((list) => this.sortInstances(batchedMesh, list));
|
|
1899
1937
|
for (const shapeDef of shapes) {
|
|
1900
1938
|
let instanceId;
|
|
1939
|
+
let type;
|
|
1901
1940
|
if (shapeDef.shape instanceof Rect && rectGeometryId !== void 0) {
|
|
1902
1941
|
instanceId = batchedMesh.addInstance(rectGeometryId);
|
|
1903
|
-
|
|
1942
|
+
type = "rect";
|
|
1904
1943
|
} else {
|
|
1905
1944
|
const geometry = shapeDefToGeometry.get(shapeDef);
|
|
1906
1945
|
const { vertices, indices } = countGeometry(geometry);
|
|
1907
1946
|
const polygonGeometryId = batchedMesh.addGeometry(this.placeholderPolygonGeometry, vertices, indices);
|
|
1908
1947
|
instanceId = batchedMesh.addInstance(polygonGeometryId);
|
|
1909
|
-
|
|
1948
|
+
type = "polygon";
|
|
1910
1949
|
}
|
|
1950
|
+
const key = `${batchedMesh.uuid}-${instanceId}`;
|
|
1951
|
+
this.mapInstanceIdToShapeType.set(key, type);
|
|
1911
1952
|
this.registerDefObject(shapeDef, batchedMesh, instanceId);
|
|
1912
1953
|
}
|
|
1913
1954
|
return batchedMesh;
|
|
@@ -1997,19 +2038,30 @@ class TextSystem extends RenderableSystem {
|
|
|
1997
2038
|
group.add(newBatchedText);
|
|
1998
2039
|
}
|
|
1999
2040
|
updateDefImpl(textDef, mesh, instanceIds) {
|
|
2000
|
-
|
|
2041
|
+
const lines = [];
|
|
2042
|
+
for (let i = 0; i < textDef.lines.length; i++) {
|
|
2043
|
+
const line = textDef.lines[i];
|
|
2001
2044
|
const text = mesh.getText(instanceIds[i]);
|
|
2002
|
-
if (
|
|
2003
|
-
text.
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2045
|
+
if (line.fontSize === 0) {
|
|
2046
|
+
text.visible = false;
|
|
2047
|
+
continue;
|
|
2048
|
+
}
|
|
2049
|
+
text.visible = true;
|
|
2050
|
+
text.text = line.text;
|
|
2051
|
+
text.color = this.textColor.set(line.color).getHex(LinearSRGBColorSpace);
|
|
2052
|
+
text.font = line.fontUrl;
|
|
2053
|
+
if (line.stroke) {
|
|
2054
|
+
text.outlineColor = line.stroke.color;
|
|
2055
|
+
text.outlineWidth = line.fontSize == 0 ? 0 : line.stroke.width / line.fontSize;
|
|
2010
2056
|
}
|
|
2057
|
+
const fontSize = line.fontSize;
|
|
2058
|
+
const height = line.text.split("\n").length * text.lineHeight * fontSize;
|
|
2059
|
+
lines.push({ text, fontSize, height });
|
|
2060
|
+
}
|
|
2061
|
+
if (lines.length > 0) {
|
|
2062
|
+
if (textDef.alignment.vertical === "bottom") lines.reverse();
|
|
2063
|
+
this.updateScale(textDef, mesh, lines);
|
|
2011
2064
|
}
|
|
2012
|
-
this.updateScale(textDef);
|
|
2013
2065
|
}
|
|
2014
2066
|
buildBatchedText(layer) {
|
|
2015
2067
|
const textDefs = layer.children;
|
|
@@ -2024,6 +2076,7 @@ class TextSystem extends RenderableSystem {
|
|
|
2024
2076
|
text.fontSize = 1;
|
|
2025
2077
|
text.lineHeight = 1.1;
|
|
2026
2078
|
text.whiteSpace = "nowrap";
|
|
2079
|
+
text.clipRect = [0, 0, 0, 0];
|
|
2027
2080
|
batchedText.addText(text, instanceId);
|
|
2028
2081
|
instanceIds.push(instanceId);
|
|
2029
2082
|
instanceId++;
|
|
@@ -2043,9 +2096,8 @@ class TextSystem extends RenderableSystem {
|
|
|
2043
2096
|
return batchedText;
|
|
2044
2097
|
}
|
|
2045
2098
|
// TODO: Simplify
|
|
2046
|
-
updateScale(textDef) {
|
|
2099
|
+
updateScale(textDef, mesh, lines) {
|
|
2047
2100
|
const dpr = this.renderer.context.getPixelRatio();
|
|
2048
|
-
const lines = this.getTextLines(textDef);
|
|
2049
2101
|
this.calculateStartInBoundsPosition(
|
|
2050
2102
|
textDef,
|
|
2051
2103
|
lines,
|
|
@@ -2053,41 +2105,18 @@ class TextSystem extends RenderableSystem {
|
|
|
2053
2105
|
this.alignmentOffset,
|
|
2054
2106
|
this.localPosition
|
|
2055
2107
|
);
|
|
2056
|
-
for (const { text, fontSize, height
|
|
2057
|
-
|
|
2058
|
-
text.visible = false;
|
|
2059
|
-
continue;
|
|
2060
|
-
}
|
|
2061
|
-
text.visible = true;
|
|
2062
|
-
setAnchorsAndAlignment(text, alignment);
|
|
2108
|
+
for (const { text, fontSize, height } of lines) {
|
|
2109
|
+
setAnchorsAndAlignment(text, textDef.alignment);
|
|
2063
2110
|
this.worldPosition.copy(this.localPosition).rotateAround({ x: 0, y: 0 }, textDef.bounds.rotation).add(textDef.bounds.center);
|
|
2064
2111
|
this.textScale.copy(this.initialTextScale).multiplyScalar(fontSize * dpr);
|
|
2065
2112
|
text.scale.set(this.textScale.x, this.textScale.y, 1);
|
|
2066
2113
|
text.position.set(this.worldPosition.x, this.worldPosition.y, 0);
|
|
2067
2114
|
text.rotation.set(0, 0, textDef.bounds.rotation);
|
|
2068
|
-
text.
|
|
2069
|
-
textDef,
|
|
2070
|
-
this.localPosition,
|
|
2071
|
-
this.textScale,
|
|
2072
|
-
this.localToMin,
|
|
2073
|
-
this.localToMax
|
|
2074
|
-
);
|
|
2115
|
+
this.calculateClipRect(text, textDef, this.localPosition, this.textScale, this.localToMin, this.localToMax);
|
|
2075
2116
|
this.localPosition.y += height * dpr;
|
|
2117
|
+
mesh.invalidateBounds();
|
|
2076
2118
|
}
|
|
2077
2119
|
}
|
|
2078
|
-
getTextLines(textDef) {
|
|
2079
|
-
const { object: mesh, instanceIds } = this.getObjectInstanceByDef(textDef);
|
|
2080
|
-
const alignment = textDef.alignment;
|
|
2081
|
-
const lines = instanceIds.map((instanceId, i) => {
|
|
2082
|
-
const text = mesh.getText(instanceId);
|
|
2083
|
-
const line = textDef.lines[i];
|
|
2084
|
-
const fontSize = line.fontSize;
|
|
2085
|
-
const height = fontSize ? text.text.split("\n").length * text.lineHeight * fontSize : 0;
|
|
2086
|
-
return { text, fontSize, height, alignment };
|
|
2087
|
-
});
|
|
2088
|
-
if (alignment.vertical === "bottom") lines.reverse();
|
|
2089
|
-
return lines;
|
|
2090
|
-
}
|
|
2091
2120
|
calculateStartInBoundsPosition(textDef, lines, alignmentDirection, alignmentOffset, inBoundsPosition) {
|
|
2092
2121
|
const padding = textDef.padding;
|
|
2093
2122
|
const alignment = textDef.alignment;
|
|
@@ -2102,10 +2131,13 @@ class TextSystem extends RenderableSystem {
|
|
|
2102
2131
|
}
|
|
2103
2132
|
inBoundsPosition.multiply(alignmentDirection);
|
|
2104
2133
|
}
|
|
2105
|
-
calculateClipRect(textDef, inBoundsPosition, textScale, toMin, toMax) {
|
|
2134
|
+
calculateClipRect(text, textDef, inBoundsPosition, textScale, toMin, toMax) {
|
|
2106
2135
|
toMin.subVectors(textDef.bounds.min, textDef.bounds.center).multiply(this.initialTextScale).sub(inBoundsPosition).divide(textScale);
|
|
2107
2136
|
toMax.subVectors(textDef.bounds.max, textDef.bounds.center).multiply(this.initialTextScale).sub(inBoundsPosition).divide(textScale);
|
|
2108
|
-
|
|
2137
|
+
text.clipRect[0] = toMin.x;
|
|
2138
|
+
text.clipRect[1] = toMin.y;
|
|
2139
|
+
text.clipRect[2] = toMax.x;
|
|
2140
|
+
text.clipRect[3] = toMax.y;
|
|
2109
2141
|
}
|
|
2110
2142
|
}
|
|
2111
2143
|
function getAlignmentDirection(alignment) {
|
|
@@ -2143,7 +2175,8 @@ class LayerSystem {
|
|
|
2143
2175
|
__publicField(this, "mapLayerDefToParent", /* @__PURE__ */ new Map());
|
|
2144
2176
|
__publicField(this, "layerDefRenderOrder", []);
|
|
2145
2177
|
__publicField(this, "pendingDefs", /* @__PURE__ */ new Set());
|
|
2146
|
-
__publicField(this, "
|
|
2178
|
+
__publicField(this, "culledDefs", /* @__PURE__ */ new Set());
|
|
2179
|
+
__publicField(this, "useUpdateBuffering", true);
|
|
2147
2180
|
this.renderer = renderer;
|
|
2148
2181
|
this.materialSystem = new MaterialSystem();
|
|
2149
2182
|
this.meshSystem = new MeshSystem(this.materialSystem, this.renderer);
|
|
@@ -2177,30 +2210,57 @@ class LayerSystem {
|
|
|
2177
2210
|
*/
|
|
2178
2211
|
updateDefs(defs) {
|
|
2179
2212
|
for (const def of defs) {
|
|
2180
|
-
if (this.useUpdateBuffering)
|
|
2181
|
-
|
|
2213
|
+
if (this.useUpdateBuffering) {
|
|
2214
|
+
this.pendingDefs.add(def);
|
|
2215
|
+
this.culledDefs.delete(def);
|
|
2216
|
+
} else this.updateDef(def);
|
|
2182
2217
|
}
|
|
2183
2218
|
}
|
|
2184
2219
|
/**
|
|
2185
2220
|
* Drain the queued updates within a time budget.
|
|
2186
2221
|
* Returns true if any def was updated during this call.
|
|
2222
|
+
* @param scene {@link Scene} instance to get the world matrix from
|
|
2223
|
+
* @param camera {@link Camera} instance to do frustum culling against
|
|
2187
2224
|
* @param timeBudgetMs frame time budget to perform updates in milliseconds
|
|
2188
2225
|
* @returns true if any def was updated during this call
|
|
2189
2226
|
*/
|
|
2190
|
-
processPendingUpdates(timeBudgetMs =
|
|
2227
|
+
processPendingUpdates(scene, camera, timeBudgetMs = -1) {
|
|
2191
2228
|
if (!this.useUpdateBuffering) return false;
|
|
2192
|
-
if (this.pendingDefs.size === 0) return false;
|
|
2229
|
+
if (this.pendingDefs.size === 0 && this.culledDefs.size === 0) return false;
|
|
2193
2230
|
const startTime = performance.now();
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2231
|
+
_matrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse).multiply(scene.matrixWorld);
|
|
2232
|
+
_frustum.setFromProjectionMatrix(_matrix, camera.coordinateSystem);
|
|
2233
|
+
let processedCount = 0;
|
|
2234
|
+
const overBudget = () => timeBudgetMs > 0 && performance.now() - startTime >= timeBudgetMs;
|
|
2235
|
+
for (const def of this.pendingDefs) {
|
|
2236
|
+
if (overBudget()) break;
|
|
2237
|
+
let culled = false;
|
|
2197
2238
|
this.pendingDefs.delete(def);
|
|
2239
|
+
if (isTextDef(def) || isImageDef(def)) {
|
|
2240
|
+
const bounds = def.bounds;
|
|
2241
|
+
_box.min.set(bounds.min.x, bounds.min.y, 0);
|
|
2242
|
+
_box.max.set(bounds.max.x, bounds.max.y, 0);
|
|
2243
|
+
culled = !_frustum.intersectsBox(_box);
|
|
2244
|
+
}
|
|
2245
|
+
if (culled) this.culledDefs.add(def);
|
|
2246
|
+
else {
|
|
2247
|
+
this.updateDef(def);
|
|
2248
|
+
processedCount++;
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
for (const def of this.culledDefs) {
|
|
2252
|
+
if (overBudget()) break;
|
|
2253
|
+
this.culledDefs.delete(def);
|
|
2198
2254
|
this.updateDef(def);
|
|
2199
|
-
|
|
2255
|
+
processedCount++;
|
|
2200
2256
|
}
|
|
2201
2257
|
const took = (performance.now() - startTime).toFixed(2);
|
|
2202
|
-
if (
|
|
2203
|
-
|
|
2258
|
+
if (processedCount > 0) {
|
|
2259
|
+
const culled = this.culledDefs.size;
|
|
2260
|
+
const remaining = this.pendingDefs.size;
|
|
2261
|
+
logger$5.debug(`processed ${processedCount} defs (${culled} culled, ${remaining} remaining) in ${took}ms`);
|
|
2262
|
+
}
|
|
2263
|
+
return processedCount > 0;
|
|
2204
2264
|
}
|
|
2205
2265
|
/**
|
|
2206
2266
|
* Build the scene graph from the given scene definition.
|
|
@@ -2333,6 +2393,9 @@ class LayerSystem {
|
|
|
2333
2393
|
return fullName;
|
|
2334
2394
|
}
|
|
2335
2395
|
}
|
|
2396
|
+
const _matrix = new Matrix4();
|
|
2397
|
+
const _frustum = new Frustum();
|
|
2398
|
+
const _box = new Box3();
|
|
2336
2399
|
/*!
|
|
2337
2400
|
* camera-controls
|
|
2338
2401
|
* https://github.com/yomotsu/camera-controls
|
|
@@ -4943,6 +5006,17 @@ class CameraSystem {
|
|
|
4943
5006
|
if (zoomFactor <= 0) return this.zoomIdentityDistance;
|
|
4944
5007
|
return this.zoomIdentityDistance / zoomFactor;
|
|
4945
5008
|
}
|
|
5009
|
+
/**
|
|
5010
|
+
* Set the zoom factor bounds.
|
|
5011
|
+
* @param minZoom Minimum zoom factor. Default is 0.1.
|
|
5012
|
+
* @param maxZoom Maximum zoom factor. Default is 35.
|
|
5013
|
+
*/
|
|
5014
|
+
setZoomBounds(minZoom, maxZoom) {
|
|
5015
|
+
if (!this.zoomBounds) return;
|
|
5016
|
+
if (minZoom) this.zoomBounds[0] = minZoom;
|
|
5017
|
+
if (maxZoom) this.zoomBounds[1] = maxZoom;
|
|
5018
|
+
this.updateCamera();
|
|
5019
|
+
}
|
|
4946
5020
|
/**
|
|
4947
5021
|
* Initializes the camera with the given zoom bounds.
|
|
4948
5022
|
* @param zoomBounds [minZoom, maxZoom]
|
|
@@ -5288,7 +5362,7 @@ class ViewportSystem {
|
|
|
5288
5362
|
*/
|
|
5289
5363
|
initViewport(sceneDef) {
|
|
5290
5364
|
if (!this.renderer.isExternalMode) this.sceneSystem.initScene(sceneDef.viewbox);
|
|
5291
|
-
this.cameraSystem.initCamera([0.1, sceneDef.viewbox.size.x >
|
|
5365
|
+
this.cameraSystem.initCamera([0.1, sceneDef.viewbox.size.x > 1e4 ? 100 : 35]);
|
|
5292
5366
|
}
|
|
5293
5367
|
/** Updates the viewport when the renderer size changes. */
|
|
5294
5368
|
updateViewport() {
|
|
@@ -5393,12 +5467,28 @@ class ViewportSystem {
|
|
|
5393
5467
|
zoomFactorToDistance(zoomFactor) {
|
|
5394
5468
|
return this.cameraSystem.zoomFactorToDistance(zoomFactor);
|
|
5395
5469
|
}
|
|
5470
|
+
/**
|
|
5471
|
+
* Set the maximum zoom factor. Default is 35.
|
|
5472
|
+
* @param maxZoom Maximum zoom factor
|
|
5473
|
+
*/
|
|
5474
|
+
setMaxZoom(maxZoom) {
|
|
5475
|
+
this.cameraSystem.setZoomBounds(void 0, maxZoom);
|
|
5476
|
+
}
|
|
5477
|
+
/**
|
|
5478
|
+
* Set the minimum zoom factor. Default is 0.1.
|
|
5479
|
+
* @param minZoom Minimum zoom factor
|
|
5480
|
+
*/
|
|
5481
|
+
setMinZoom(minZoom) {
|
|
5482
|
+
this.cameraSystem.setZoomBounds(minZoom, void 0);
|
|
5483
|
+
}
|
|
5396
5484
|
}
|
|
5397
5485
|
function asViewportAPI(viewportSystem) {
|
|
5398
5486
|
return {
|
|
5399
5487
|
canvasToSvg: viewportSystem.canvasToSvg.bind(viewportSystem),
|
|
5400
5488
|
setStaticTransform: viewportSystem.setStaticTransform.bind(viewportSystem),
|
|
5401
|
-
setDynamicTransform: viewportSystem.setDynamicTransform.bind(viewportSystem)
|
|
5489
|
+
setDynamicTransform: viewportSystem.setDynamicTransform.bind(viewportSystem),
|
|
5490
|
+
setMaxZoom: viewportSystem.setMaxZoom.bind(viewportSystem),
|
|
5491
|
+
setMinZoom: viewportSystem.setMinZoom.bind(viewportSystem)
|
|
5402
5492
|
};
|
|
5403
5493
|
}
|
|
5404
5494
|
function eventToCanvas(event) {
|
|
@@ -6414,10 +6504,13 @@ class Renderer {
|
|
|
6414
6504
|
const api = asViewportAPI(this.viewportSystem);
|
|
6415
6505
|
const guard = (name) => this.assertInitialized(`viewport.${name}`) && this.assertNotDisposed(`viewport.${name}`);
|
|
6416
6506
|
const guardExternal = (name) => guard(name) && this.assertExternalMode(`viewport.${name}`);
|
|
6507
|
+
const guardNotExternal = (name) => guard(name) && this.assertNotExternalMode(`viewport.${name}`);
|
|
6417
6508
|
this.viewportAPI = {
|
|
6418
6509
|
canvasToSvg: guardFn(guard, api.canvasToSvg, { x: 0, y: 0 }),
|
|
6419
6510
|
setStaticTransform: guardFn(guardExternal, api.setStaticTransform),
|
|
6420
|
-
setDynamicTransform: guardFn(guardExternal, api.setDynamicTransform)
|
|
6511
|
+
setDynamicTransform: guardFn(guardExternal, api.setDynamicTransform),
|
|
6512
|
+
setMaxZoom: guardFn(guardNotExternal, api.setMaxZoom),
|
|
6513
|
+
setMinZoom: guardFn(guardNotExternal, api.setMinZoom)
|
|
6421
6514
|
};
|
|
6422
6515
|
return this.viewportAPI;
|
|
6423
6516
|
}
|
|
@@ -6517,12 +6610,13 @@ class Renderer {
|
|
|
6517
6610
|
(_b = (_a2 = this.ui) == null ? void 0 : _a2.stats) == null ? void 0 : _b.begin();
|
|
6518
6611
|
if (this.isExternalMode) this.renderer.resetState();
|
|
6519
6612
|
else this.resizeCanvasToDisplaySize();
|
|
6520
|
-
this.viewportSystem
|
|
6521
|
-
const hasDefsUpdated = this.layerSystem.processPendingUpdates();
|
|
6613
|
+
const { scene, camera } = this.viewportSystem;
|
|
6522
6614
|
const hasControlsUpdated = this.interactionsSystem.updateControls(this.clock.getDelta());
|
|
6615
|
+
this.viewportSystem.updatePtScale();
|
|
6616
|
+
const hasDefsUpdated = this.layerSystem.processPendingUpdates(scene, camera, 3);
|
|
6523
6617
|
const needsRedraw = this.needsRedraw || hasControlsUpdated || hasDefsUpdated || this.isExternalMode || this.ui;
|
|
6524
6618
|
if (needsRedraw) {
|
|
6525
|
-
this.renderer.render(
|
|
6619
|
+
this.renderer.render(scene, camera);
|
|
6526
6620
|
this.needsRedraw = false;
|
|
6527
6621
|
}
|
|
6528
6622
|
(_d = (_c = this.ui) == null ? void 0 : _c.stats) == null ? void 0 : _d.end();
|
|
@@ -6558,7 +6652,8 @@ class Renderer {
|
|
|
6558
6652
|
// https://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
|
|
6559
6653
|
resizeCanvasToDisplaySize() {
|
|
6560
6654
|
const dpr = window.devicePixelRatio;
|
|
6561
|
-
const
|
|
6655
|
+
const width = this.canvas.clientWidth;
|
|
6656
|
+
const height = this.canvas.clientHeight;
|
|
6562
6657
|
const displayWidth = Math.floor(width * dpr);
|
|
6563
6658
|
const displayHeight = Math.floor(height * dpr);
|
|
6564
6659
|
if (this.canvas.width !== displayWidth || this.canvas.height !== displayHeight || this.renderer.getPixelRatio() !== dpr) {
|