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