@idetik/core 0.26.0 → 0.27.1

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 CHANGED
@@ -386,6 +386,7 @@ declare abstract class Layer {
386
386
  abstract readonly type: string;
387
387
  private objects_;
388
388
  private state_;
389
+ private attached_;
389
390
  private readonly callbacks_;
390
391
  private opacity_;
391
392
  blendMode: BlendMode;
@@ -394,8 +395,10 @@ declare abstract class Layer {
394
395
  set opacity(value: number);
395
396
  abstract update(context?: RenderContext): void;
396
397
  onEvent(_: EventContext): void;
397
- onAttached(_context: IdetikContext): void;
398
- onDetached(_context: IdetikContext): void;
398
+ onAttached(context: IdetikContext): void;
399
+ onDetached(context: IdetikContext): void;
400
+ protected attach(_context: IdetikContext): void;
401
+ protected detach(_context: IdetikContext): void;
399
402
  get objects(): RenderableObject[];
400
403
  get state(): LayerState;
401
404
  addStateChangeCallback(callback: StateChangeCallback): void;
@@ -563,6 +566,8 @@ declare abstract class Renderer {
563
566
  get renderedObjects(): number;
564
567
  abstract get gpuTextureBytes(): number;
565
568
  abstract get gpuTextureCount(): number;
569
+ abstract uploadTexture(texture: Texture): void;
570
+ abstract disposeTexture(texture: Texture): void;
566
571
  set backgroundColor(color: ColorLike);
567
572
  }
568
573
 
@@ -1365,8 +1370,8 @@ declare class ImageLayer extends Layer implements ChannelsEnabled {
1365
1370
  private lastPresentationTimeCoord_?;
1366
1371
  private readonly wireframeColors_;
1367
1372
  constructor({ source, sliceCoords, policy, channelProps, onPickValue, ...layerOptions }: ImageLayerProps);
1368
- onAttached(context: IdetikContext): void;
1369
- onDetached(_context: IdetikContext): void;
1373
+ protected attach(context: IdetikContext): void;
1374
+ protected detach(_context: IdetikContext): void;
1370
1375
  update(context?: RenderContext): void;
1371
1376
  private updateChunks;
1372
1377
  hasMultipleLODs(): boolean;
@@ -1432,8 +1437,8 @@ declare class VolumeLayer extends Layer implements ChannelsEnabled {
1432
1437
  removeChannelChangeCallback(callback: () => void): void;
1433
1438
  constructor({ source, sliceCoords, policy, channelProps }: VolumeLayerProps);
1434
1439
  private getOrCreateVolume;
1435
- onAttached(context: IdetikContext): void;
1436
- onDetached(_context: IdetikContext): void;
1440
+ protected attach(context: IdetikContext): void;
1441
+ protected detach(_context: IdetikContext): void;
1437
1442
  private updateChunks;
1438
1443
  private updateVolumeTransform;
1439
1444
  private releaseAndRemoveVolume;
@@ -1476,8 +1481,8 @@ declare class LabelLayer extends Layer {
1476
1481
  private lastPresentationTimeStamp_?;
1477
1482
  private lastPresentationTimeCoord_?;
1478
1483
  constructor({ source, sliceCoords, policy, colorMap, onPickValue, outlineSelected, ...layerOptions }: LabelLayerProps);
1479
- onAttached(context: IdetikContext): void;
1480
- onDetached(_context: IdetikContext): void;
1484
+ protected attach(context: IdetikContext): void;
1485
+ protected detach(_context: IdetikContext): void;
1481
1486
  update(context?: RenderContext): void;
1482
1487
  private updateChunks;
1483
1488
  private isPresentationStale;
package/dist/index.js CHANGED
@@ -1267,13 +1267,8 @@ class ti {
1267
1267
  throw new Error(
1268
1268
  `Texture index ${I} must be in [0, ${this.maxTextureUnits_ - 1}]`
1269
1269
  );
1270
- this.gl_.activeTexture(this.gl_.TEXTURE0 + I);
1271
- const g = this.getTextureType(A), B = this.getDataFormatInfo(A.dataFormat, A.dataType);
1272
- this.textures_.has(A) || this.generateTexture(A, B, g);
1273
- const Q = this.textures_.get(A);
1274
- if (!Q)
1275
- throw new Error("Failed to retrieve texture ID");
1276
- this.gl_.bindTexture(g, Q), A.needsUpdate && A.data !== null && (this.configureTextureParameters(A, g), this.uploadTextureData(A, B, g), A.needsUpdate = !1), this.currentTexture_ = A;
1270
+ const g = this.textures_.get(A);
1271
+ g && !A.needsUpdate ? (this.gl_.activeTexture(this.gl_.TEXTURE0 + I), this.gl_.bindTexture(this.getTextureType(A), g)) : this.uploadTexture(A, I), this.currentTexture_ = A;
1277
1272
  }
1278
1273
  readTexel(A, I, g, B) {
1279
1274
  const Q = this.gl_, E = this.textures_.get(A);
@@ -1312,7 +1307,18 @@ class ti {
1312
1307
  return { format: I.RGBA, type: I.FLOAT, out: new Float32Array(4) };
1313
1308
  }
1314
1309
  }
1315
- disposeTexture(A) {
1310
+ uploadTexture(A, I = 0) {
1311
+ if (this.textures_.has(A) && !A.needsUpdate) return;
1312
+ if (A.data === null)
1313
+ throw new Error("Cannot upload a texture that has no CPU data");
1314
+ const g = this.getTextureType(A), B = this.getDataFormatInfo(A.dataFormat, A.dataType);
1315
+ this.gl_.activeTexture(this.gl_.TEXTURE0 + I), this.textures_.has(A) || this.generateTexture(A, B, g);
1316
+ const Q = this.textures_.get(A);
1317
+ if (!Q)
1318
+ throw new Error("Failed to retrieve texture ID");
1319
+ this.gl_.bindTexture(g, Q), this.configureTextureParameters(A, g), this.uploadTextureData(A, B, g), A.needsUpdate = !1;
1320
+ }
1321
+ dispose(A) {
1316
1322
  const I = this.textures_.get(A);
1317
1323
  if (I) {
1318
1324
  this.gl_.deleteTexture(I), this.textures_.delete(A), A.readTexel = void 0, this.currentTexture_ === A && (this.currentTexture_ = null);
@@ -1322,7 +1328,7 @@ class ti {
1322
1328
  }
1323
1329
  disposeAll() {
1324
1330
  for (const A of Array.from(this.textures_.keys()))
1325
- this.disposeTexture(A);
1331
+ this.dispose(A);
1326
1332
  this.gpuTextureBytes_ = 0, this.textureCount_ = 0;
1327
1333
  }
1328
1334
  alreadyActive(A) {
@@ -1740,7 +1746,7 @@ class eC extends cQ {
1740
1746
  renderObject(A, I, g) {
1741
1747
  const B = A.objects[I];
1742
1748
  if (B.popStaleTextures().forEach((E) => {
1743
- this.textures_.disposeTexture(E);
1749
+ this.textures_.dispose(E);
1744
1750
  }), !B.programName) return;
1745
1751
  this.state_.setCullFaceMode(B.cullFaceMode), this.state_.setDepthTesting(B.depthTest), this.state_.setDepthMask(B.depthTest), this.bindings_.bindGeometry(B.geometry), B.textures.forEach((E, i) => {
1746
1752
  this.textures_.bindTexture(E, i);
@@ -1810,6 +1816,12 @@ class eC extends cQ {
1810
1816
  const n = this.glGetPrimitive(A.primitive), D = A.indexData;
1811
1817
  D.length ? this.gl_.drawElements(n, D.length, this.gl_.UNSIGNED_INT, 0) : this.gl_.drawArrays(n, 0, A.vertexCount);
1812
1818
  }
1819
+ uploadTexture(A) {
1820
+ this.textures_.uploadTexture(A);
1821
+ }
1822
+ disposeTexture(A) {
1823
+ this.textures_.dispose(A);
1824
+ }
1813
1825
  glGetPrimitive(A) {
1814
1826
  switch (A) {
1815
1827
  case "points":
@@ -2160,16 +2172,20 @@ class ki {
2160
2172
  this.device_ = A, this.textures_ = [];
2161
2173
  }
2162
2174
  get(A) {
2163
- const I = this.textures_.find((B) => B.entry === A);
2164
- if (I)
2165
- return A.needsUpdate && this.upload(A, I.texture), I.texture;
2166
- const g = this.device_.createTexture({
2167
- size: nC(A),
2168
- dimension: A instanceof TA ? "3d" : "2d",
2169
- format: di(A),
2170
- usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC
2171
- });
2172
- return this.upload(A, g), this.textures_.push({ entry: A, texture: g }), A.readTexel = (B, Q, E) => this.readTexel(g, A.dataType, B, Q, E), g;
2175
+ let I = this.textures_.find((g) => g.entry === A);
2176
+ if (I && !A.needsUpdate) return I.texture;
2177
+ if (A.data === null)
2178
+ throw new Error("Cannot upload a texture that has no CPU data");
2179
+ if (!I) {
2180
+ const g = this.device_.createTexture({
2181
+ size: nC(A),
2182
+ dimension: A instanceof TA ? "3d" : "2d",
2183
+ format: di(A),
2184
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC
2185
+ });
2186
+ this.textures_.push({ entry: A, texture: g }), I = this.textures_[this.textures_.length - 1];
2187
+ }
2188
+ return this.upload(A, I.texture), A.readTexel = (g, B, Q) => this.readTexel(I.texture, A.dataType, g, B, Q), I.texture;
2173
2189
  }
2174
2190
  async readTexel(A, I, g, B, Q) {
2175
2191
  const E = this.device_.createBuffer({
@@ -8582,6 +8598,12 @@ class Mo extends cQ {
8582
8598
  }
8583
8599
  clear() {
8584
8600
  }
8601
+ uploadTexture(A) {
8602
+ this.texturePool_.get(A);
8603
+ }
8604
+ disposeTexture(A) {
8605
+ this.texturePool_.dispose(A);
8606
+ }
8585
8607
  setUniformsForObject(A, I, g) {
8586
8608
  _A(
8587
8609
  this.currentModelView_,
@@ -9439,7 +9461,7 @@ class Oo {
9439
9461
  return this.layers_;
9440
9462
  }
9441
9463
  addLayer(A) {
9442
- this.layers_.push(A), A.onAttached(this.context_);
9464
+ A.onAttached(this.context_), this.layers_.push(A);
9443
9465
  }
9444
9466
  removeLayer(A) {
9445
9467
  const I = this.layers_.indexOf(A);
@@ -18455,6 +18477,7 @@ class MI {
18455
18477
  class Jg {
18456
18478
  objects_ = [];
18457
18479
  state_ = "initialized";
18480
+ attached_ = !1;
18458
18481
  callbacks_ = [];
18459
18482
  opacity_;
18460
18483
  blendMode;
@@ -18473,8 +18496,18 @@ class Jg {
18473
18496
  onEvent(A) {
18474
18497
  }
18475
18498
  onAttached(A) {
18499
+ if (this.attached_)
18500
+ throw new Error(
18501
+ `${this.type} cannot be attached to multiple viewports simultaneously.`
18502
+ );
18503
+ this.attach(A), this.attached_ = !0;
18476
18504
  }
18477
18505
  onDetached(A) {
18506
+ this.attached_ && (this.detach(A), this.attached_ = !1);
18507
+ }
18508
+ attach(A) {
18509
+ }
18510
+ detach(A) {
18478
18511
  }
18479
18512
  get objects() {
18480
18513
  return this.objects_;
@@ -18953,11 +18986,7 @@ class DE extends Jg {
18953
18986
  }) {
18954
18987
  super(E), this.setState("initialized"), this.source_ = A, this.policy_ = g, this.sliceCoords_ = I, this.channelProps_ = B, this.initialChannelProps_ = B, this.onPickValue_ = Q;
18955
18988
  }
18956
- onAttached(A) {
18957
- if (this.chunkStoreView_)
18958
- throw new Error(
18959
- "ImageLayer cannot be attached to multiple viewports simultaneously."
18960
- );
18989
+ attach(A) {
18961
18990
  this.chunkStoreView_ = A.chunkManager.addView(
18962
18991
  this.source_,
18963
18992
  this.policy_
@@ -18968,8 +18997,8 @@ class DE extends Jg {
18968
18997
  `ImageLayer requires exactly one channel in sliceCoords.c for multi-channel sources (found ${I} channels). Use one layer per channel.`
18969
18998
  );
18970
18999
  }
18971
- onDetached(A) {
18972
- this.chunkStoreView_ && (this.releaseAndRemoveChunks(this.visibleChunks_.keys()), this.clearObjects(), this.chunkStoreView_.dispose(), this.chunkStoreView_ = void 0);
19000
+ detach(A) {
19001
+ this.releaseAndRemoveChunks(this.visibleChunks_.keys()), this.clearObjects(), this.chunkStoreView_?.dispose(), this.chunkStoreView_ = void 0;
18973
19002
  }
18974
19003
  update(A) {
18975
19004
  if (!(!A || !this.chunkStoreView_)) {
@@ -19377,11 +19406,7 @@ class Ua extends Jg {
19377
19406
  for (const E of I) Q.updateVolumeWithChunk(E);
19378
19407
  return this.updateVolumeTransform(Q, I[0]), Q;
19379
19408
  }
19380
- onAttached(A) {
19381
- if (this.chunkStoreView_)
19382
- throw new Error(
19383
- "VolumeLayer cannot be attached to multiple viewports simultaneously."
19384
- );
19409
+ attach(A) {
19385
19410
  this.chunkStoreView_ = A.chunkManager.addView(
19386
19411
  this.source_,
19387
19412
  this.sourcePolicy_
@@ -19390,12 +19415,10 @@ class Ua extends Jg {
19390
19415
  this.chunkStoreView_.channelCount
19391
19416
  );
19392
19417
  }
19393
- onDetached(A) {
19394
- if (this.chunkStoreView_) {
19395
- for (const I of this.currentVolumes_.values())
19396
- this.releaseAndRemoveVolume(I);
19397
- this.clearObjects(), this.chunkStoreView_.dispose(), this.chunkStoreView_ = void 0;
19398
- }
19418
+ detach(A) {
19419
+ for (const I of this.currentVolumes_.values())
19420
+ this.releaseAndRemoveVolume(I);
19421
+ this.clearObjects(), this.chunkStoreView_?.dispose(), this.chunkStoreView_ = void 0;
19399
19422
  }
19400
19423
  updateChunks() {
19401
19424
  if (!this.chunkStoreView_) return;
@@ -19633,11 +19656,7 @@ class hE extends Jg {
19633
19656
  }) {
19634
19657
  super(i), this.setState("initialized"), this.source_ = A, this.policy_ = g, this.sliceCoords_ = I, this.colorMap_ = new aQ(B), this.onPickValue_ = Q, this.outlineSelected_ = E;
19635
19658
  }
19636
- onAttached(A) {
19637
- if (this.chunkStoreView_)
19638
- throw new Error(
19639
- "LabelLayer cannot be attached to multiple viewports simultaneously."
19640
- );
19659
+ attach(A) {
19641
19660
  if (this.chunkStoreView_ = A.chunkManager.addView(
19642
19661
  this.source_,
19643
19662
  this.policy_
@@ -19646,8 +19665,8 @@ class hE extends Jg {
19646
19665
  `LabelLayer does not support multi-channel sources (found ${this.chunkStoreView_.channelCount} channels). Label data must be single-channel.`
19647
19666
  );
19648
19667
  }
19649
- onDetached(A) {
19650
- this.chunkStoreView_ && (this.releaseAndRemoveChunks(this.visibleChunks_.keys()), this.clearObjects(), this.chunkStoreView_.dispose(), this.chunkStoreView_ = void 0);
19668
+ detach(A) {
19669
+ this.releaseAndRemoveChunks(this.visibleChunks_.keys()), this.clearObjects(), this.chunkStoreView_?.dispose(), this.chunkStoreView_ = void 0;
19651
19670
  }
19652
19671
  update(A) {
19653
19672
  if (!(!A || !this.chunkStoreView_)) {