@itwin/core-frontend 5.4.0-dev.7 → 5.5.0-dev.2

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/lib/cjs/IModelApp.d.ts +12 -0
  3. package/lib/cjs/IModelApp.d.ts.map +1 -1
  4. package/lib/cjs/IModelApp.js +9 -0
  5. package/lib/cjs/IModelApp.js.map +1 -1
  6. package/lib/cjs/IModelConnection.d.ts.map +1 -1
  7. package/lib/cjs/IModelConnection.js +6 -2
  8. package/lib/cjs/IModelConnection.js.map +1 -1
  9. package/lib/cjs/SheetViewState.d.ts +7 -5
  10. package/lib/cjs/SheetViewState.d.ts.map +1 -1
  11. package/lib/cjs/SheetViewState.js +52 -683
  12. package/lib/cjs/SheetViewState.js.map +1 -1
  13. package/lib/cjs/internal/SheetViewAttachments.d.ts +57 -0
  14. package/lib/cjs/internal/SheetViewAttachments.d.ts.map +1 -0
  15. package/lib/cjs/internal/SheetViewAttachments.js +336 -0
  16. package/lib/cjs/internal/SheetViewAttachments.js.map +1 -0
  17. package/lib/cjs/internal/ViewAttachmentRenderer.d.ts +32 -0
  18. package/lib/cjs/internal/ViewAttachmentRenderer.d.ts.map +1 -0
  19. package/lib/cjs/internal/ViewAttachmentRenderer.js +462 -0
  20. package/lib/cjs/internal/ViewAttachmentRenderer.js.map +1 -0
  21. package/lib/cjs/internal/render/webgl/SceneCompositor.js +1 -1
  22. package/lib/cjs/internal/render/webgl/SceneCompositor.js.map +1 -1
  23. package/lib/cjs/internal/render/webgl/ShaderBuilder.d.ts.map +1 -1
  24. package/lib/cjs/internal/render/webgl/ShaderBuilder.js +8 -1
  25. package/lib/cjs/internal/render/webgl/ShaderBuilder.js.map +1 -1
  26. package/lib/cjs/properties/AngleDescription.js +4 -4
  27. package/lib/cjs/properties/AngleDescription.js.map +1 -1
  28. package/lib/cjs/properties/LengthDescription.js +9 -9
  29. package/lib/cjs/properties/LengthDescription.js.map +1 -1
  30. package/lib/cjs/quantity-formatting/QuantityFormatter.d.ts.map +1 -1
  31. package/lib/cjs/quantity-formatting/QuantityFormatter.js +9 -8
  32. package/lib/cjs/quantity-formatting/QuantityFormatter.js.map +1 -1
  33. package/lib/cjs/tools/EventController.js +1 -1
  34. package/lib/cjs/tools/EventController.js.map +1 -1
  35. package/lib/cjs/tools/MeasureTool.js +21 -21
  36. package/lib/cjs/tools/MeasureTool.js.map +1 -1
  37. package/lib/esm/IModelApp.d.ts +12 -0
  38. package/lib/esm/IModelApp.d.ts.map +1 -1
  39. package/lib/esm/IModelApp.js +9 -0
  40. package/lib/esm/IModelApp.js.map +1 -1
  41. package/lib/esm/IModelConnection.d.ts.map +1 -1
  42. package/lib/esm/IModelConnection.js +7 -3
  43. package/lib/esm/IModelConnection.js.map +1 -1
  44. package/lib/esm/SheetViewState.d.ts +7 -5
  45. package/lib/esm/SheetViewState.d.ts.map +1 -1
  46. package/lib/esm/SheetViewState.js +55 -686
  47. package/lib/esm/SheetViewState.js.map +1 -1
  48. package/lib/esm/internal/SheetViewAttachments.d.ts +57 -0
  49. package/lib/esm/internal/SheetViewAttachments.d.ts.map +1 -0
  50. package/lib/esm/internal/SheetViewAttachments.js +332 -0
  51. package/lib/esm/internal/SheetViewAttachments.js.map +1 -0
  52. package/lib/esm/internal/ViewAttachmentRenderer.d.ts +32 -0
  53. package/lib/esm/internal/ViewAttachmentRenderer.d.ts.map +1 -0
  54. package/lib/esm/internal/ViewAttachmentRenderer.js +459 -0
  55. package/lib/esm/internal/ViewAttachmentRenderer.js.map +1 -0
  56. package/lib/esm/internal/render/webgl/SceneCompositor.js +1 -1
  57. package/lib/esm/internal/render/webgl/SceneCompositor.js.map +1 -1
  58. package/lib/esm/internal/render/webgl/ShaderBuilder.d.ts.map +1 -1
  59. package/lib/esm/internal/render/webgl/ShaderBuilder.js +8 -1
  60. package/lib/esm/internal/render/webgl/ShaderBuilder.js.map +1 -1
  61. package/lib/esm/properties/AngleDescription.js +4 -4
  62. package/lib/esm/properties/AngleDescription.js.map +1 -1
  63. package/lib/esm/properties/LengthDescription.js +9 -9
  64. package/lib/esm/properties/LengthDescription.js.map +1 -1
  65. package/lib/esm/quantity-formatting/QuantityFormatter.d.ts.map +1 -1
  66. package/lib/esm/quantity-formatting/QuantityFormatter.js +9 -8
  67. package/lib/esm/quantity-formatting/QuantityFormatter.js.map +1 -1
  68. package/lib/esm/tools/EventController.js +1 -1
  69. package/lib/esm/tools/EventController.js.map +1 -1
  70. package/lib/esm/tools/MeasureTool.js +21 -21
  71. package/lib/esm/tools/MeasureTool.js.map +1 -1
  72. package/lib/public/scripts/parse-imdl-worker.js +1 -1
  73. package/lib/workers/webpack/parse-imdl-worker.js +1 -1
  74. package/package.json +21 -21
@@ -13,18 +13,10 @@ const core_geometry_1 = require("@itwin/core-geometry");
13
13
  const core_common_1 = require("@itwin/core-common");
14
14
  const CategorySelectorState_1 = require("./CategorySelectorState");
15
15
  const DisplayStyleState_1 = require("./DisplayStyleState");
16
- const GraphicBranch_1 = require("./render/GraphicBranch");
17
16
  const Frustum2d_1 = require("./Frustum2d");
18
- const MockRender_1 = require("./internal/render/MockRender");
19
- const FeatureSymbology_1 = require("./render/FeatureSymbology");
20
- const IModelApp_1 = require("./IModelApp");
21
- const CoordSystem_1 = require("./CoordSystem");
22
- const Viewport_1 = require("./Viewport");
23
17
  const ViewState_1 = require("./ViewState");
24
- const internal_1 = require("./tile/internal");
25
- const ImageUtil_1 = require("./common/ImageUtil");
26
- const ViewRect_1 = require("./common/ViewRect");
27
18
  const GraphicType_1 = require("./common/render/GraphicType");
19
+ const SheetViewAttachments_1 = require("./internal/SheetViewAttachments");
28
20
  // cSpell:ignore ovrs
29
21
  /** Describes the geometry and styling of a sheet border decoration.
30
22
  * The sheet border decoration mimics a sheet of paper with a drop shadow.
@@ -98,189 +90,6 @@ class SheetBorder {
98
90
  builder.addLineString2d(this._rect, 0);
99
91
  }
100
92
  }
101
- /** The information required to instantiate an ViewAttachments object to draw ViewAttachments into a sheet. The list of view attachment Ids is
102
- * supplied to SheetViewState via the constructor. The corresponding ViewAttachmentProps for each attachment are obtained asynchronously in
103
- * SheetViewState.load(). The Attachments object is created in SheetViewState.attachToViewport and disposed of in SheetViewState.detachFromViewport.
104
- */
105
- class ViewAttachmentsInfo {
106
- _attachments;
107
- get attachments() { return this._attachments; }
108
- constructor(attachments) {
109
- this._attachments = attachments;
110
- }
111
- get isLoaded() {
112
- return 0 === this._attachments.length || "string" !== typeof this._attachments[0];
113
- }
114
- get viewAttachmentProps() {
115
- return this.isLoaded ? this._props : [];
116
- }
117
- get _props() {
118
- (0, core_bentley_1.assert)(this.isLoaded);
119
- return this._attachments;
120
- }
121
- get _ids() {
122
- (0, core_bentley_1.assert)(!this.isLoaded);
123
- return this._attachments;
124
- }
125
- static fromJSON(ids = []) {
126
- return new ViewAttachmentsInfo(ids);
127
- }
128
- toJSON() {
129
- return this.isLoaded ? this._props.map((x) => (0, core_bentley_1.expectDefined)(x.id)) : [...this._ids];
130
- }
131
- clone(iModel) {
132
- let attachments = this._attachments;
133
- if (this.isLoaded) {
134
- // Need to clone the attached ViewStates.
135
- attachments = attachments.map((attachment) => {
136
- (0, core_bentley_1.assert)(typeof attachment !== "string");
137
- return {
138
- ...attachment,
139
- attachedView: attachment.attachedView.clone(iModel),
140
- };
141
- });
142
- }
143
- return new ViewAttachmentsInfo(attachments);
144
- }
145
- preload(options) {
146
- if (this.isLoaded)
147
- return;
148
- options.sheetViewAttachmentIds = core_bentley_1.CompressedId64Set.sortAndCompress(this._ids);
149
- options.viewStateLoadProps = {
150
- displayStyle: {
151
- omitScheduleScriptElementIds: !IModelApp_1.IModelApp.tileAdmin.enableFrontendScheduleScripts,
152
- compressExcludedElementIds: true,
153
- },
154
- };
155
- }
156
- async postload(options, iModel) {
157
- if (options.sheetViewViews === undefined)
158
- return;
159
- if (options.sheetViewAttachmentProps === undefined)
160
- return;
161
- const viewStateProps = options.sheetViewViews; // This is viewstateProps, need to turn this into ViewState
162
- const promises = [];
163
- for (const viewProps of viewStateProps) {
164
- const loadView = async () => {
165
- try {
166
- if (viewProps === undefined)
167
- return undefined;
168
- const view = await iModel.views.convertViewStatePropsToViewState(viewProps);
169
- return view;
170
- }
171
- catch {
172
- return undefined;
173
- }
174
- };
175
- promises.push(loadView());
176
- }
177
- const views = await Promise.all(promises);
178
- const attachmentProps = options.sheetViewAttachmentProps;
179
- (0, core_bentley_1.assert)(views.length === attachmentProps.length);
180
- const attachments = [];
181
- for (let i = 0; i < views.length; i++) {
182
- const view = views[i];
183
- if (view && !(view instanceof SheetViewState)) {
184
- const props = attachmentProps[i];
185
- props.attachedView = view;
186
- attachments.push(props);
187
- }
188
- }
189
- this._attachments = attachments;
190
- }
191
- async load(iModel) {
192
- if (this.isLoaded)
193
- return;
194
- const attachmentProps = await iModel.elements.getProps(this._ids);
195
- const promises = [];
196
- for (const attachment of attachmentProps) {
197
- const loadView = async () => {
198
- try {
199
- const view = await iModel.views.load(attachment.view.id);
200
- return view;
201
- }
202
- catch {
203
- return undefined;
204
- }
205
- };
206
- promises.push(loadView());
207
- }
208
- const views = await Promise.all(promises);
209
- (0, core_bentley_1.assert)(views.length === attachmentProps.length);
210
- const attachments = [];
211
- for (let i = 0; i < views.length; i++) {
212
- const view = views[i];
213
- if (view && !(view instanceof SheetViewState)) {
214
- const props = attachmentProps[i];
215
- props.attachedView = view;
216
- attachments.push(props);
217
- }
218
- }
219
- this._attachments = attachments;
220
- }
221
- createAttachments(sheetView) {
222
- return this.isLoaded ? new ViewAttachments(this._props, sheetView) : undefined;
223
- }
224
- }
225
- /** The set of view attachments to be displayed in a Viewport via a SheetViewState. Allocated when the view becomes attached to a Viewport;
226
- * disposed of when it becomes detached from the viewport.
227
- */
228
- class ViewAttachments {
229
- _attachments = [];
230
- maxDepth = Frustum2d_1.Frustum2d.minimumZDistance;
231
- constructor(infos, sheetView) {
232
- for (const info of infos) {
233
- const drawAsRaster = info.jsonProperties?.displayOptions?.drawAsRaster || (info.attachedView.is3d() && info.attachedView.isCameraOn);
234
- const ctor = drawAsRaster ? RasterAttachment : OrthographicAttachment;
235
- const attachment = new ctor(info.attachedView, info, sheetView);
236
- this._attachments.push(attachment);
237
- this.maxDepth = Math.max(this.maxDepth, attachment.zDepth);
238
- }
239
- }
240
- [Symbol.dispose]() {
241
- for (const attachment of this._attachments)
242
- attachment[Symbol.dispose]();
243
- this._attachments.length = 0;
244
- }
245
- [Symbol.iterator]() {
246
- return this._attachments[Symbol.iterator]();
247
- }
248
- /** For tests. */
249
- get attachments() {
250
- return this._attachments;
251
- }
252
- get isEmpty() {
253
- return 0 === this._attachments.length;
254
- }
255
- areAllTileTreesLoaded(displayedExtents) {
256
- return this._attachments.every((x) => {
257
- const placement = core_common_1.Placement2d.fromJSON(x.viewAttachmentProps.placement);
258
- const attachmentRange = placement.calculateRange();
259
- if (!attachmentRange.intersectsRangeXY(displayedExtents))
260
- return true;
261
- return x.areAllTileTreesLoaded;
262
- });
263
- }
264
- /** Strictly for testing purposes */
265
- areAllAttachmentsLoaded() {
266
- return this._attachments.every((attachment) => attachment.areAllTileTreesLoaded);
267
- }
268
- discloseTileTrees(trees) {
269
- for (const attachment of this._attachments)
270
- trees.disclose(attachment);
271
- }
272
- collectStatistics(stats) {
273
- for (const attachment of this._attachments)
274
- attachment.collectStatistics(stats);
275
- }
276
- addToScene(context) {
277
- for (const attachment of this._attachments)
278
- attachment.addToScene(context);
279
- }
280
- findById(attachmentId) {
281
- return this._attachments.find((attachment) => attachment.viewAttachmentProps.id === attachmentId);
282
- }
283
- }
284
93
  /** A view of a [SheetModel]($backend).
285
94
  * @public
286
95
  * @extensions
@@ -288,11 +97,13 @@ class ViewAttachments {
288
97
  class SheetViewState extends ViewState_1.ViewState2d {
289
98
  /** The width and height of the sheet in world coordinates. */
290
99
  sheetSize;
291
- _attachmentsInfo;
292
- _attachments;
100
+ _viewAttachments;
293
101
  _viewedExtents;
102
+ _onViewAttachmentsReloaded = () => undefined;
103
+ /** Strictly for tests. */
104
+ onViewAttachmentsReloaded = new core_bentley_1.BeEvent();
294
105
  get attachmentIds() {
295
- return this._attachmentsInfo.toJSON();
106
+ return this._viewAttachments.attachmentIds;
296
107
  }
297
108
  static get className() { return "SheetViewDefinition"; }
298
109
  static createFromProps(viewStateData, iModel) {
@@ -303,7 +114,7 @@ class SheetViewState extends ViewState_1.ViewState2d {
303
114
  }
304
115
  toProps() {
305
116
  const props = super.toProps();
306
- props.sheetAttachments = this._attachmentsInfo.toJSON();
117
+ props.sheetAttachments = [...this.attachmentIds];
307
118
  // For sheetProps all that is actually used is the size, so just null out everything else.
308
119
  const codeProps = { spec: "", scope: "", value: "" };
309
120
  props.sheetProps = {
@@ -318,20 +129,15 @@ class SheetViewState extends ViewState_1.ViewState2d {
318
129
  }
319
130
  /** Strictly for testing. @internal */
320
131
  get viewAttachmentProps() {
321
- return this._attachmentsInfo.viewAttachmentProps.map((x) => {
322
- return {
323
- ...x,
324
- attachedView: undefined,
325
- };
326
- });
132
+ return this._viewAttachments.attachmentProps;
327
133
  }
328
134
  /** Strictly for testing. @internal */
329
135
  get viewAttachmentInfos() {
330
- return this._attachmentsInfo.attachments;
136
+ return this._viewAttachments.attachmentInfos;
331
137
  }
332
138
  /** Strictly for testing. @internal */
333
139
  get attachments() {
334
- return this._attachments?.attachments;
140
+ return this._viewAttachments.attachments;
335
141
  }
336
142
  isDrawingView() { return false; }
337
143
  isSheetView() { return true; }
@@ -340,41 +146,53 @@ class SheetViewState extends ViewState_1.ViewState2d {
340
146
  if (categories instanceof SheetViewState) {
341
147
  // we are coming from clone...
342
148
  this.sheetSize = categories.sheetSize.clone();
343
- this._attachmentsInfo = categories._attachmentsInfo.clone(iModel);
149
+ this._viewAttachments = categories._viewAttachments.clone(iModel);
344
150
  this._viewedExtents = categories._viewedExtents.clone();
345
151
  }
346
152
  else {
347
153
  this.sheetSize = core_geometry_1.Point2d.create(sheetProps.width, sheetProps.height);
348
- this._attachmentsInfo = ViewAttachmentsInfo.fromJSON(attachments);
154
+ this._viewAttachments = SheetViewAttachments_1.SheetViewAttachments.create(attachments);
349
155
  const extents = new core_geometry_1.Range3d(0, 0, 0, this.sheetSize.x, this.sheetSize.y, 0);
350
156
  const margin = 1.1;
351
157
  extents.scaleAboutCenterInPlace(margin);
352
158
  this._viewedExtents = extents;
353
159
  }
160
+ if (iModel.isBriefcaseConnection()) {
161
+ iModel.txns.onElementsChanged.addListener(async (changes) => {
162
+ let reload = false;
163
+ for (const change of changes.filter({ includeMetadata: (meta) => meta.is("BisCore:ViewAttachment") })) {
164
+ if (change.type === "inserted" || this._viewAttachments.attachmentIds.includes(change.id)) {
165
+ reload = true;
166
+ break;
167
+ }
168
+ }
169
+ if (reload) {
170
+ await this._viewAttachments.reload(this.baseModelId, iModel);
171
+ this._onViewAttachmentsReloaded();
172
+ this.onViewAttachmentsReloaded.raiseEvent();
173
+ }
174
+ });
175
+ }
354
176
  }
355
177
  getOrigin() {
356
178
  const origin = super.getOrigin();
357
- if (this._attachments)
358
- origin.z = -this._attachments.maxDepth;
179
+ origin.z = -this._viewAttachments.maxDepth;
359
180
  return origin;
360
181
  }
361
182
  getExtents() {
362
183
  const extents = super.getExtents();
363
- if (this._attachments)
364
- extents.z = this._attachments.maxDepth + Frustum2d_1.Frustum2d.minimumZDistance;
184
+ extents.z = this._viewAttachments.maxDepth + Frustum2d_1.Frustum2d.minimumZDistance;
365
185
  return extents;
366
186
  }
367
187
  /** Overrides [[ViewState.discloseTileTrees]] to include tile trees associated with [ViewAttachment]($backend)s displayed on this sheet. */
368
188
  discloseTileTrees(trees) {
369
189
  super.discloseTileTrees(trees);
370
- if (this._attachments)
371
- trees.disclose(this._attachments);
190
+ trees.disclose(this._viewAttachments);
372
191
  }
373
192
  /** @internal */
374
193
  collectNonTileTreeStatistics(stats) {
375
194
  super.collectNonTileTreeStatistics(stats);
376
- if (this._attachments)
377
- this._attachments.collectStatistics(stats);
195
+ this._viewAttachments.collectStatistics(stats);
378
196
  }
379
197
  get defaultExtentLimits() {
380
198
  return { min: core_geometry_1.Constant.oneMillimeter, max: this.sheetSize.magnitude() * 10 };
@@ -385,36 +203,23 @@ class SheetViewState extends ViewState_1.ViewState2d {
385
203
  /** @internal */
386
204
  preload(hydrateRequest) {
387
205
  super.preload(hydrateRequest);
388
- this._attachmentsInfo.preload(hydrateRequest);
206
+ this._viewAttachments.preload(hydrateRequest);
389
207
  }
390
208
  /** @internal */
391
209
  async postload(hydrateResponse) {
392
210
  const promises = [];
393
211
  promises.push(super.postload(hydrateResponse));
394
- promises.push(this._attachmentsInfo.postload(hydrateResponse, this.iModel));
212
+ promises.push(this._viewAttachments.postload(hydrateResponse, this.iModel));
395
213
  await Promise.all(promises);
396
214
  }
397
215
  /** @internal */
398
216
  createScene(context) {
399
217
  super.createScene(context);
400
- if (this._attachments)
401
- this._attachments.addToScene(context);
218
+ this._viewAttachments.addToScene(context);
402
219
  }
403
220
  /** @internal */
404
221
  get secondaryViewports() {
405
- if (this._attachments === undefined)
406
- return super.secondaryViewports;
407
- const attachments = this._attachments;
408
- function* iterator() {
409
- for (const attachment of attachments) {
410
- const vp = attachment.viewport;
411
- if (vp)
412
- yield vp;
413
- }
414
- }
415
- return {
416
- [Symbol.iterator]: () => iterator(),
417
- };
222
+ return this._viewAttachments.getSecondaryViewports();
418
223
  }
419
224
  /** @internal */
420
225
  async queryAttachmentIds() {
@@ -427,34 +232,38 @@ class SheetViewState extends ViewState_1.ViewState2d {
427
232
  async changeViewedModel(modelId) {
428
233
  await super.changeViewedModel(modelId);
429
234
  const attachmentIds = await this.queryAttachmentIds();
430
- this._attachmentsInfo = ViewAttachmentsInfo.fromJSON(attachmentIds);
431
- (0, core_bentley_1.assert)(undefined === this._attachments);
235
+ (0, core_bentley_1.dispose)(this._viewAttachments);
236
+ this._viewAttachments = SheetViewAttachments_1.SheetViewAttachments.create(attachmentIds);
432
237
  }
433
238
  /** See [[ViewState.attachToViewport]]. */
434
239
  attachToViewport(args) {
435
240
  super.attachToViewport(args);
436
- (0, core_bentley_1.assert)(undefined === this._attachments);
437
- this._attachments = this._attachmentsInfo.createAttachments(this);
241
+ this._viewAttachments.attachToViewport({
242
+ backgroundColor: this.displayStyle.backgroundColor,
243
+ sheetModelId: this.baseModelId,
244
+ });
245
+ this._onViewAttachmentsReloaded = () => args.invalidateController();
438
246
  }
439
247
  /** See [[ViewState.detachFromViewport]]. */
440
248
  detachFromViewport() {
441
249
  super.detachFromViewport();
442
- this._attachments = (0, core_bentley_1.dispose)(this._attachments);
250
+ this._viewAttachments.detachFromViewport();
251
+ this._onViewAttachmentsReloaded = () => undefined;
443
252
  }
444
253
  get areAllTileTreesLoaded() {
254
+ if (!super.areAllTileTreesLoaded) {
255
+ return false;
256
+ }
445
257
  let displayedExtents = this._viewedExtents;
446
258
  const frustum = this.calculateFrustum();
447
259
  if (frustum) {
448
260
  displayedExtents = frustum.toRange();
449
261
  }
450
- return super.areAllTileTreesLoaded && (!this._attachments || this._attachments.areAllTileTreesLoaded(displayedExtents));
262
+ return this._viewAttachments.areAllTileTreesLoaded(displayedExtents);
451
263
  }
452
264
  /** @internal Strictly for testing */
453
265
  areAllAttachmentsLoaded() {
454
- if (this._attachments) {
455
- return this._attachments.areAllAttachmentsLoaded();
456
- }
457
- return true;
266
+ return this._viewAttachments.areAllAttachmentsLoaded();
458
267
  }
459
268
  /** Create a sheet border decoration graphic. */
460
269
  createBorder(width, height, context) {
@@ -479,454 +288,14 @@ class SheetViewState extends ViewState_1.ViewState2d {
479
288
  }
480
289
  /** @internal */
481
290
  getAttachmentViewport(args) {
482
- const attachment = args.viewAttachmentId ? this._attachments?.findById(args.viewAttachmentId) : undefined;
483
- if (!attachment) {
484
- return undefined;
485
- }
486
- return args.inSectionDrawingAttachment ? attachment.viewport?.view.getAttachmentViewport({ inSectionDrawingAttachment: true }) : attachment.viewport;
291
+ return this._viewAttachments.getAttachmentViewport(args);
487
292
  }
488
293
  /** @beta */
489
294
  computeDisplayTransform(args) {
490
295
  // ###TODO we're currently ignoring model and element Id in args, assuming irrelevant for sheets.
491
296
  // Should probably call super or have super call us.
492
- const attachment = undefined !== args.viewAttachmentId ? this._attachments?.findById(args.viewAttachmentId) : undefined;
493
- if (!attachment || !(attachment instanceof OrthographicAttachment)) {
494
- return undefined;
495
- }
496
- const sheetTransform = attachment.toSheet;
497
- const sectionTransform = args.inSectionDrawingAttachment ? attachment.view.computeDisplayTransform(args) : undefined;
498
- if (!sectionTransform) {
499
- return sheetTransform.clone(args.output);
500
- }
501
- return sheetTransform.multiplyTransformTransform(sectionTransform, args.output);
297
+ return this._viewAttachments.computeDisplayTransform(args);
502
298
  }
503
299
  }
504
300
  exports.SheetViewState = SheetViewState;
505
- /** A mostly no-op RenderTarget for an Attachment.
506
- * its Scene and symbology overrides.
507
- */
508
- class AttachmentTarget extends MockRender_1.MockRender.OffScreenTarget {
509
- _attachment;
510
- constructor(attachment) {
511
- // The dimensions don't matter - we're not drawing anything.
512
- const rect = new ViewRect_1.ViewRect(1, 1);
513
- super(IModelApp_1.IModelApp.renderSystem, rect);
514
- this._attachment = attachment;
515
- }
516
- changeScene(scene) {
517
- this._attachment.scene = scene;
518
- }
519
- overrideFeatureSymbology(ovrs) {
520
- this._attachment.symbologyOverrides = ovrs;
521
- }
522
- }
523
- /** Draws the contents a 2d or orthographic 3d view directly into a sheet view.
524
- * We select tiles for the view in the context of a light-weight offscreen viewport with a no-op RenderTarget, then
525
- * collect the resultant graphics and add them to the sheet view's scene.
526
- */
527
- class OrthographicAttachment {
528
- _viewport;
529
- _props;
530
- _sheetModelId;
531
- _viewFlagOverrides;
532
- _toSheet;
533
- _fromSheet;
534
- _sizeInMeters;
535
- _range;
536
- _viewRect = new ViewRect_1.ViewRect(0, 0, 1, 1);
537
- _originalFrustum = new core_common_1.Frustum();
538
- _clipVolume;
539
- _hiddenLineSettings;
540
- _scale;
541
- _debugFeatureTable;
542
- scene;
543
- symbologyOverrides;
544
- zDepth;
545
- get view() {
546
- return this._viewport.view;
547
- }
548
- get viewAttachmentProps() {
549
- return this._props;
550
- }
551
- get viewport() {
552
- return this._viewport;
553
- }
554
- constructor(view, props, sheetView) {
555
- this.symbologyOverrides = new FeatureSymbology_1.FeatureSymbology.Overrides(view);
556
- const target = new AttachmentTarget(this);
557
- this._viewport = Viewport_1.OffScreenViewport.createViewport(view, target, true);
558
- this._props = props;
559
- this._sheetModelId = sheetView.baseModelId;
560
- const applyClip = true; // set to false for debugging
561
- this._viewFlagOverrides = {
562
- ...view.viewFlags,
563
- clipVolume: applyClip,
564
- lighting: false,
565
- shadows: false,
566
- };
567
- const placement = core_common_1.Placement2d.fromJSON(props.placement);
568
- const range = placement.calculateRange();
569
- this._range = range;
570
- this._sizeInMeters = new core_geometry_1.Point2d(range.xLength(), range.yLength());
571
- // Compute transform from attached view's world coordinates to sheet's world coordinates.
572
- // NB: We obtain the extents and origin from the *viewport* not the *view* - they may have been adjusted by the viewport.
573
- const applySkew = true; // set to false for debugging
574
- const skew = applySkew ? view.getAspectRatioSkew() : 1;
575
- const extents = this._viewport.viewingSpace.viewDelta.clone();
576
- const zDepth = Math.abs(extents.z);
577
- const scaleX = this._sizeInMeters.x / Math.abs(extents.x);
578
- const scaleY = skew * this._sizeInMeters.y / Math.abs(extents.y);
579
- this._scale = { x: 1 / scaleX, y: 1 / scaleY };
580
- const zBias = Frustum2d_1.Frustum2d.depthFromDisplayPriority(props.jsonProperties?.displayPriority ?? 0);
581
- this.zDepth = 1.01 * (zDepth - zBias); // give a little padding so that geometry right up against far plane doesn't get clipped.
582
- // View origin is at the *back* of the view. Align *front* of view based on display priority.
583
- const viewRot = view.getRotation();
584
- const viewOrg = viewRot.multiplyVector(this._viewport.viewingSpace.viewOrigin);
585
- viewOrg.z += zDepth;
586
- viewRot.multiplyTransposeVectorInPlace(viewOrg);
587
- const matrix = core_geometry_1.Matrix3d.createScale(scaleX, scaleY, 1);
588
- matrix.multiplyMatrixMatrix(viewRot, matrix);
589
- const origin = core_geometry_1.Matrix3d.xyzMinusMatrixTimesXYZ(viewOrg, matrix, viewOrg);
590
- const attachmentOrigin = core_geometry_1.Point3d.createFrom(placement.origin);
591
- attachmentOrigin.z = zBias;
592
- const viewOrgToAttachment = attachmentOrigin.minus(viewOrg);
593
- origin.addInPlace(viewOrgToAttachment);
594
- this._toSheet = core_geometry_1.Transform.createRefs(origin, matrix);
595
- this._fromSheet = (0, core_bentley_1.expectDefined)(this._toSheet.inverse());
596
- // If the attached view is a section drawing, it may itself have an attached spatial view with a clip.
597
- // The clip needs to be transformed into sheet space.
598
- if (view.isDrawingView())
599
- this._viewport.drawingToSheetTransform = this._toSheet;
600
- // ###TODO? If we also apply the attachment's clip to the attached view, we may get additional culling during tile selection.
601
- // However the attached view's frustum is already clipped by intersection with sheet view's frustum, and additional clipping planes
602
- // introduce additional computation, so possibly not worth it.
603
- // Transform the view's clip (if any) to sheet space
604
- let viewClip = view.viewFlags.clipVolume ? view.getViewClip()?.clone() : undefined;
605
- if (viewClip)
606
- viewClip.transformInPlace(this._toSheet);
607
- else
608
- viewClip = core_geometry_1.ClipVector.createEmpty();
609
- let sheetClip;
610
- if (undefined !== props.jsonProperties?.clip)
611
- sheetClip = core_geometry_1.ClipVector.fromJSON(props.jsonProperties?.clip);
612
- if (sheetClip && sheetClip.isValid) {
613
- // Clip to view attachment's clip. NB: clip is in sheet coordinate space.
614
- for (const clip of sheetClip.clips)
615
- viewClip.clips.push(clip);
616
- }
617
- else {
618
- // Clip to view attachment's bounding box
619
- viewClip.appendShape([
620
- core_geometry_1.Point3d.create(this._range.low.x, this._range.low.y),
621
- core_geometry_1.Point3d.create(this._range.high.x, this._range.low.y),
622
- core_geometry_1.Point3d.create(this._range.high.x, this._range.high.y),
623
- core_geometry_1.Point3d.create(this._range.low.x, this._range.high.y),
624
- ]);
625
- }
626
- this._clipVolume = IModelApp_1.IModelApp.renderSystem.createClipVolume(viewClip);
627
- // Save off the original frustum (potentially adjusted by viewport).
628
- this._viewport.setupFromView();
629
- this._viewport.viewingSpace.getFrustum(CoordSystem_1.CoordSystem.World, true, this._originalFrustum);
630
- const applyHiddenLineSettings = true; // for debugging edge display, set to false...
631
- const style = view.displayStyle;
632
- if (style.is3d() && applyHiddenLineSettings)
633
- this._hiddenLineSettings = style.settings.hiddenLineSettings;
634
- }
635
- [Symbol.dispose]() {
636
- this._viewport[Symbol.dispose]();
637
- }
638
- discloseTileTrees(trees) {
639
- trees.disclose(this._viewport);
640
- }
641
- addToScene(context) {
642
- if (context.viewport.freezeScene)
643
- return;
644
- if (!context.viewport.view.viewsCategory(this._props.category))
645
- return;
646
- const wantBounds = context.viewport.wantViewAttachmentBoundaries;
647
- const wantClipShapes = context.viewport.wantViewAttachmentClipShapes;
648
- if (wantBounds || wantClipShapes) {
649
- const builder = context.createSceneGraphicBuilder();
650
- if (wantBounds) {
651
- builder.setSymbology(core_common_1.ColorDef.red, core_common_1.ColorDef.red, 2);
652
- builder.addRangeBox(this._range);
653
- }
654
- if (wantClipShapes && this._clipVolume) {
655
- builder.setSymbology(core_common_1.ColorDef.blue, core_common_1.ColorDef.blue, 2);
656
- for (const prim of this._clipVolume.clipVector.clips) {
657
- if (!(prim instanceof core_geometry_1.ClipShape))
658
- continue; // ###TODO handle non-shape primitives, if any such ever encountered
659
- const pts = [];
660
- const tf = prim.transformFromClip;
661
- for (const pt of prim.polygon) {
662
- const tfPt = tf ? tf.multiplyPoint3d(pt) : pt;
663
- pts.push(new core_geometry_1.Point2d(tfPt.x, tfPt.y));
664
- }
665
- builder.addLineString2d(pts, 0);
666
- }
667
- }
668
- // Put into a Batch so that we can see tooltip with attachment Id on mouseover.
669
- const batch = context.target.renderSystem.createBatch(builder.finish(), this.getDebugFeatureTable(), this._range);
670
- context.outputGraphic(batch);
671
- }
672
- if (!context.viewport.wantViewAttachments)
673
- return;
674
- // Pixel size used to compute size of ViewRect so that tiles of appropriate LOD are selected.
675
- const pixelSize = context.viewport.getPixelSizeAtPoint();
676
- if (0 === pixelSize)
677
- return;
678
- // Adjust attached view frustum based on intersection with sheet view frustum.
679
- const attachFrustum = this._originalFrustum.transformBy(this._toSheet);
680
- const attachFrustumRange = attachFrustum.toRange();
681
- const sheetFrustum = context.viewport.getWorldFrustum();
682
- const sheetFrustumRange = sheetFrustum.toRange();
683
- const intersect = attachFrustumRange.intersect(sheetFrustumRange);
684
- if (intersect.isNull)
685
- return;
686
- attachFrustum.initFromRange(intersect);
687
- attachFrustum.transformBy(this._fromSheet, attachFrustum);
688
- this._viewport.setupViewFromFrustum(attachFrustum);
689
- // Adjust view rect based on size of attachment on screen so that tiles of appropriate LOD are selected.
690
- const width = this._sizeInMeters.x * intersect.xLength() / attachFrustumRange.xLength();
691
- const height = this._sizeInMeters.y * intersect.yLength() / attachFrustumRange.yLength();
692
- this._viewRect.width = Math.max(1, Math.round(width / pixelSize));
693
- this._viewRect.height = Math.max(1, Math.round(height / pixelSize));
694
- this._viewport.setRect(this._viewRect);
695
- // Propagate settings from on-screen viewport.
696
- this._viewport.debugBoundingBoxes = context.viewport.debugBoundingBoxes;
697
- this._viewport.setTileSizeModifier(context.viewport.tileSizeModifier);
698
- // Create the scene.
699
- this._viewport.renderFrame();
700
- const scene = this.scene;
701
- if (!scene)
702
- return;
703
- // Extract scene graphics and insert into on-screen scene context.
704
- const options = {
705
- viewAttachmentId: this._props.id,
706
- clipVolume: this._clipVolume,
707
- hline: this._hiddenLineSettings,
708
- frustum: {
709
- is3d: this.view.is3d(),
710
- scale: this._scale,
711
- },
712
- };
713
- const outputGraphics = (source) => {
714
- if (0 === source.length)
715
- return;
716
- const graphics = new GraphicBranch_1.GraphicBranch();
717
- graphics.setViewFlagOverrides(this._viewFlagOverrides);
718
- graphics.symbologyOverrides = this.symbologyOverrides;
719
- for (const graphic of source)
720
- graphics.entries.push(graphic);
721
- const branch = context.createGraphicBranch(graphics, this._toSheet, options);
722
- context.outputGraphic(branch);
723
- };
724
- outputGraphics(scene.foreground);
725
- context.withGraphicType(internal_1.TileGraphicType.BackgroundMap, () => outputGraphics(scene.background));
726
- context.withGraphicType(internal_1.TileGraphicType.Overlay, () => outputGraphics(scene.overlay));
727
- // Report tile statistics to sheet view's viewport.
728
- const tileAdmin = IModelApp_1.IModelApp.tileAdmin;
729
- const selectedAndReady = tileAdmin.getTilesForUser(this._viewport);
730
- const requested = tileAdmin.getRequestsForUser(this._viewport);
731
- tileAdmin.addExternalTilesForUser(context.viewport, {
732
- requested: requested?.size ?? 0,
733
- selected: selectedAndReady?.selected.size ?? 0,
734
- ready: selectedAndReady?.ready.size ?? 0,
735
- });
736
- }
737
- getDebugFeatureTable() {
738
- if (this._debugFeatureTable)
739
- return this._debugFeatureTable;
740
- const featureTable = new core_common_1.FeatureTable(1, this._sheetModelId);
741
- featureTable.insert(new core_common_1.Feature(this._props.id));
742
- this._debugFeatureTable = core_common_1.PackedFeatureTable.pack(featureTable);
743
- return this._debugFeatureTable;
744
- }
745
- get areAllTileTreesLoaded() {
746
- return this.view.areAllTileTreesLoaded;
747
- }
748
- collectStatistics(_stats) {
749
- // Handled by discloseTileTrees()
750
- }
751
- get toSheet() {
752
- return this._toSheet;
753
- }
754
- }
755
- function createRasterAttachmentViewport(_view, _rect, _attachment) {
756
- class RasterAttachmentViewport extends Viewport_1.OffScreenViewport {
757
- _sceneContext;
758
- _isSceneReady = false;
759
- _attachment;
760
- constructor(view, rect, attachment) {
761
- super(IModelApp_1.IModelApp.renderSystem.createOffscreenTarget(rect));
762
- this._attachment = attachment;
763
- this._isAspectRatioLocked = true;
764
- this.changeView(view);
765
- }
766
- createSceneContext() {
767
- (0, core_bentley_1.assert)(!this._isSceneReady);
768
- this._sceneContext = super.createSceneContext();
769
- return this._sceneContext;
770
- }
771
- renderFrame() {
772
- (0, core_bentley_1.assert)(!this._isSceneReady);
773
- this.clearSceneContext();
774
- super.renderFrame();
775
- if (undefined !== this._sceneContext) {
776
- this._isSceneReady = !this._sceneContext.hasMissingTiles && this.view.areAllTileTreesLoaded;
777
- if (this._isSceneReady)
778
- this._attachment.produceGraphics(this._sceneContext);
779
- this._sceneContext = undefined;
780
- }
781
- }
782
- clearSceneContext() {
783
- this._sceneContext = undefined;
784
- }
785
- addDecorations(_decorations) {
786
- // ###TODO: skybox, ground plane, possibly grid. DecorateContext requires a ScreenViewport...
787
- }
788
- }
789
- return new RasterAttachmentViewport(_view, _rect, _attachment);
790
- }
791
- /** Draws a 3d view with camera enabled into a sheet view by producing an image of the view's contents offscreen. */
792
- class RasterAttachment {
793
- _props;
794
- _placement;
795
- _transform;
796
- zDepth;
797
- _viewport;
798
- _graphics;
799
- constructor(view, props, sheetView) {
800
- // Render to a 2048x2048 view rect. Scale in Y to preserve aspect ratio.
801
- const maxSize = 2048;
802
- const rect = new ViewRect_1.ViewRect(0, 0, maxSize, maxSize);
803
- const height = maxSize * view.getAspectRatio() * view.getAspectRatioSkew();
804
- const skew = maxSize / height;
805
- view.setAspectRatioSkew(skew);
806
- if (true !== props.jsonProperties?.displayOptions?.preserveBackground) {
807
- // Make background color 100% transparent so that Viewport.readImageBuffer() will discard transparent pixels.
808
- const bgColor = sheetView.displayStyle.backgroundColor.withAlpha(0);
809
- view.displayStyle.backgroundColor = bgColor;
810
- }
811
- this._viewport = createRasterAttachmentViewport(view, rect, this);
812
- this._props = props;
813
- this._placement = core_common_1.Placement2d.fromJSON(props.placement);
814
- this._transform = this._placement.transform;
815
- this.zDepth = Frustum2d_1.Frustum2d.depthFromDisplayPriority(props.jsonProperties?.displayPriority ?? 0);
816
- }
817
- [Symbol.dispose]() {
818
- this._viewport?.[Symbol.dispose]();
819
- }
820
- get viewAttachmentProps() {
821
- return this._props;
822
- }
823
- get viewport() {
824
- return this._viewport;
825
- }
826
- get areAllTileTreesLoaded() {
827
- return this._viewport?.areAllTileTreesLoaded ?? true;
828
- }
829
- addToScene(context) {
830
- // ###TODO: check viewport.wantViewAttachmentClipShapes
831
- if (!context.viewport.view.viewsCategory(this._props.category))
832
- return;
833
- if (context.viewport.wantViewAttachmentBoundaries) {
834
- const builder = context.createSceneGraphicBuilder(this._transform);
835
- builder.setSymbology(core_common_1.ColorDef.red, core_common_1.ColorDef.red, 2);
836
- builder.addRangeBox(core_geometry_1.Range3d.createRange2d(this._placement.bbox));
837
- context.outputGraphic(builder.finish());
838
- }
839
- if (!context.viewport.wantViewAttachments)
840
- return;
841
- if (this._graphics) {
842
- context.outputGraphic(this._graphics);
843
- return;
844
- }
845
- if (undefined === this._viewport)
846
- return;
847
- this._viewport.debugBoundingBoxes = context.viewport.debugBoundingBoxes;
848
- this._viewport.setTileSizeModifier(context.viewport.tileSizeModifier);
849
- this._viewport.renderFrame();
850
- if (this._graphics)
851
- context.outputGraphic(this._graphics);
852
- }
853
- discloseTileTrees(trees) {
854
- if (this._viewport)
855
- trees.disclose(this._viewport);
856
- }
857
- produceGraphics(context) {
858
- (0, core_bentley_1.assert)(context.viewport === this._viewport);
859
- this._graphics = this.createGraphics(this._viewport);
860
- this._viewport = (0, core_bentley_1.dispose)(this._viewport);
861
- if (undefined !== this._graphics)
862
- context.outputGraphic(this._graphics);
863
- }
864
- createGraphics(vp) {
865
- // Create a texture from the contents of the view.
866
- const image = vp.readImageBuffer({ upsideDown: true });
867
- if (undefined === image)
868
- return undefined;
869
- const debugImage = false; // set to true to open a window displaying the captured image.
870
- if (debugImage) {
871
- const url = (0, ImageUtil_1.imageBufferToPngDataUrl)(image, false);
872
- if (url)
873
- (0, ImageUtil_1.openImageDataUrlInNewWindow)(url, "Attachment");
874
- }
875
- const texture = IModelApp_1.IModelApp.renderSystem.createTexture({
876
- image: { source: image, transparency: core_common_1.TextureTransparency.Opaque },
877
- });
878
- if (!texture)
879
- return undefined;
880
- // Create a material for the texture
881
- const graphicParams = new core_common_1.GraphicParams();
882
- graphicParams.material = IModelApp_1.IModelApp.renderSystem.createRenderMaterial({ textureMapping: { texture } });
883
- // Apply the texture to a rectangular polyface.
884
- const depth = this.zDepth;
885
- const east = this._placement.bbox.low.x;
886
- const west = this._placement.bbox.high.x;
887
- const north = this._placement.bbox.low.y;
888
- const south = this._placement.bbox.high.y;
889
- const corners = [
890
- core_geometry_1.Point3d.create(east, north, depth),
891
- core_geometry_1.Point3d.create(west, north, depth),
892
- core_geometry_1.Point3d.create(west, south, depth),
893
- core_geometry_1.Point3d.create(east, south, depth),
894
- ];
895
- const params = [
896
- core_geometry_1.Point2d.create(0, 0),
897
- core_geometry_1.Point2d.create(1, 0),
898
- core_geometry_1.Point2d.create(1, 1),
899
- core_geometry_1.Point2d.create(0, 1),
900
- ];
901
- const strokeOptions = new core_geometry_1.StrokeOptions();
902
- strokeOptions.needParams = strokeOptions.shouldTriangulate = true;
903
- const polyfaceBuilder = core_geometry_1.PolyfaceBuilder.create(strokeOptions);
904
- polyfaceBuilder.addQuadFacet(corners, params);
905
- const polyface = polyfaceBuilder.claimPolyface();
906
- const graphicBuilder = IModelApp_1.IModelApp.renderSystem.createGraphicBuilder(core_geometry_1.Transform.createIdentity(), GraphicType_1.GraphicType.Scene, vp, this._props.id);
907
- graphicBuilder.activateGraphicParams(graphicParams);
908
- graphicBuilder.addPolyface(polyface, false);
909
- const graphic = graphicBuilder.finish();
910
- // Wrap the polyface in a GraphicBranch.
911
- const branch = new GraphicBranch_1.GraphicBranch(true);
912
- const vfOvrs = (0, internal_1.createDefaultViewFlagOverrides)({ clipVolume: true, shadows: false, lighting: false, thematic: false });
913
- // Disable transparency - background pixels are 100% transparent so they will be discarded anyway. Other pixels are 100% opaque.
914
- vfOvrs.transparency = false;
915
- branch.setViewFlagOverrides(vfOvrs);
916
- branch.symbologyOverrides = new FeatureSymbology_1.FeatureSymbology.Overrides();
917
- branch.entries.push(graphic);
918
- // Apply the attachment's clip, if any.
919
- let clipVolume;
920
- if (this._props.jsonProperties?.clip) {
921
- const clipVector = core_geometry_1.ClipVector.fromJSON(this._props.jsonProperties?.clip);
922
- if (clipVector.isValid)
923
- clipVolume = IModelApp_1.IModelApp.renderSystem.createClipVolume(clipVector);
924
- }
925
- return IModelApp_1.IModelApp.renderSystem.createGraphicBranch(branch, this._transform, { clipVolume });
926
- }
927
- collectStatistics(stats) {
928
- if (this._graphics)
929
- this._graphics.collectStatistics(stats);
930
- }
931
- }
932
301
  //# sourceMappingURL=SheetViewState.js.map