bruce-cesium 7.6.0 → 7.6.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/dist/bruce-cesium.es5.js +2057 -348
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +2050 -345
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +2 -1
- package/dist/lib/bruce-cesium.js.map +1 -1
- package/dist/lib/rendering/cesium-animated-property.js +63 -107
- package/dist/lib/rendering/cesium-animated-property.js.map +1 -1
- package/dist/lib/rendering/entity-gatherer.js +11 -3
- package/dist/lib/rendering/entity-gatherer.js.map +1 -1
- package/dist/lib/rendering/menu-item-manager.js +83 -10
- package/dist/lib/rendering/menu-item-manager.js.map +1 -1
- package/dist/lib/rendering/relation-render-engine.js +24 -5
- package/dist/lib/rendering/relation-render-engine.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-label-group.js +13 -9
- package/dist/lib/rendering/render-managers/common/entity-label-group.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-label.js +94 -12
- package/dist/lib/rendering/render-managers/common/entity-label.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-rerender-maintain-state.js +44 -5
- package/dist/lib/rendering/render-managers/common/entity-rerender-maintain-state.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-simulation.js +483 -0
- package/dist/lib/rendering/render-managers/common/entity-simulation.js.map +1 -0
- package/dist/lib/rendering/render-managers/common/historic-trail.js +123 -0
- package/dist/lib/rendering/render-managers/common/historic-trail.js.map +1 -0
- package/dist/lib/rendering/render-managers/common/historic-utils.js +17 -6
- package/dist/lib/rendering/render-managers/common/historic-utils.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-datalab-render-manager.js +3 -2
- package/dist/lib/rendering/render-managers/entities/entities-datalab-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-ids-render-manager.js +10 -2
- package/dist/lib/rendering/render-managers/entities/entities-ids-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-loaded-render-manager.js +3 -2
- package/dist/lib/rendering/render-managers/entities/entities-loaded-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-render-manager.js +18 -5
- package/dist/lib/rendering/render-managers/entities/entities-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entity-render-manager.js +1 -1
- package/dist/lib/rendering/render-managers/entities/entity-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/other/assembly-render-manager.js +745 -106
- package/dist/lib/rendering/render-managers/other/assembly-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/other/legacy-relations-render-manager.js +23 -1
- package/dist/lib/rendering/render-managers/other/legacy-relations-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/other/relations-render-manager.js +23 -1
- package/dist/lib/rendering/render-managers/other/relations-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/tilesets/tileset-arb-render-manager.js +2 -0
- package/dist/lib/rendering/render-managers/tilesets/tileset-arb-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/tilesets/tileset-cad-render-manager.js +130 -40
- package/dist/lib/rendering/render-managers/tilesets/tileset-cad-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/tilesets/tileset-entities-render-manager.js +3 -0
- package/dist/lib/rendering/render-managers/tilesets/tileset-entities-render-manager.js.map +1 -1
- package/dist/lib/rendering/tileset-styler.js +1 -1
- package/dist/lib/rendering/tileset-styler.js.map +1 -1
- package/dist/lib/rendering/visual-register-culler.js +2 -0
- package/dist/lib/rendering/visual-register-culler.js.map +1 -1
- package/dist/lib/rendering/visuals-register.js +89 -20
- package/dist/lib/rendering/visuals-register.js.map +1 -1
- package/dist/lib/utils/entity-utils.js +43 -2
- package/dist/lib/utils/entity-utils.js.map +1 -1
- package/dist/lib/widgets/widget-info-view.js +20 -7
- package/dist/lib/widgets/widget-info-view.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +2 -1
- package/dist/types/rendering/cesium-animated-property.d.ts +8 -6
- package/dist/types/rendering/entity-gatherer.d.ts +6 -1
- package/dist/types/rendering/menu-item-manager.d.ts +33 -1
- package/dist/types/rendering/relation-render-engine.d.ts +10 -0
- package/dist/types/rendering/render-managers/common/entity-label-group.d.ts +3 -2
- package/dist/types/rendering/render-managers/common/entity-label.d.ts +5 -0
- package/dist/types/rendering/render-managers/common/entity-rerender-maintain-state.d.ts +20 -0
- package/dist/types/rendering/render-managers/common/entity-simulation.d.ts +126 -0
- package/dist/types/rendering/render-managers/common/historic-trail.d.ts +30 -0
- package/dist/types/rendering/render-managers/common/historic-utils.d.ts +4 -0
- package/dist/types/rendering/render-managers/entities/entities-datalab-render-manager.d.ts +2 -0
- package/dist/types/rendering/render-managers/entities/entities-ids-render-manager.d.ts +2 -0
- package/dist/types/rendering/render-managers/entities/entities-loaded-render-manager.d.ts +2 -0
- package/dist/types/rendering/render-managers/entities/entities-render-manager.d.ts +2 -0
- package/dist/types/rendering/render-managers/entities/entity-render-manager.d.ts +2 -0
- package/dist/types/rendering/render-managers/other/assembly-render-manager.d.ts +79 -2
- package/dist/types/rendering/render-managers/other/legacy-relations-render-manager.d.ts +5 -0
- package/dist/types/rendering/render-managers/other/relations-render-manager.d.ts +5 -0
- package/dist/types/rendering/render-managers/render-manager.d.ts +4 -0
- package/dist/types/rendering/render-managers/tilesets/tileset-arb-render-manager.d.ts +3 -0
- package/dist/types/rendering/render-managers/tilesets/tileset-cad-render-manager.d.ts +11 -1
- package/dist/types/rendering/render-managers/tilesets/tileset-entities-render-manager.d.ts +3 -0
- package/dist/types/rendering/tileset-styler.d.ts +2 -0
- package/dist/types/rendering/visuals-register.d.ts +13 -0
- package/dist/types/utils/entity-utils.d.ts +6 -0
- package/dist/types/widgets/widget-info-view.d.ts +1 -0
- package/package.json +2 -2
|
@@ -9,7 +9,7 @@ const js_utils_1 = require("../../../internal/js-utils");
|
|
|
9
9
|
const entity_render_engine_1 = require("../../entity-render-engine");
|
|
10
10
|
const cesium_animated_property_1 = require("../../cesium-animated-property");
|
|
11
11
|
const historic_utils_1 = require("../common/historic-utils");
|
|
12
|
-
const
|
|
12
|
+
const historic_trail_1 = require("../common/historic-trail");
|
|
13
13
|
const cesium_utils_1 = require("../../../internal/cesium-utils");
|
|
14
14
|
/**
|
|
15
15
|
* Menu Item that will render an Assembly.
|
|
@@ -32,6 +32,55 @@ var AssemblyRenderManager;
|
|
|
32
32
|
get ModelSpace() {
|
|
33
33
|
return this.modelSpace;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Every node of the Assembly read so far, so a caller can work out motion in the Assembly's own terms.
|
|
37
|
+
* @param timeMs the scene time for each node's current pose. Default: the clock's.
|
|
38
|
+
* @returns per node its pose within its parent from the API (local) and as drawn at the time (current).
|
|
39
|
+
*/
|
|
40
|
+
GetNodes(timeMs) {
|
|
41
|
+
const at = timeMs !== null && timeMs !== void 0 ? timeMs : Cesium.JulianDate.toDate(this.viewer.clock.currentTime).getTime();
|
|
42
|
+
const rowsOf = (m) => m ? [0, 1, 2, 3].map(row => [0, 1, 2, 3].map(column => m[(column * 4) + row])) : null;
|
|
43
|
+
return Object.values(this.hierarchyNodeByEntityId || {}).map(node => {
|
|
44
|
+
var _a, _b, _c;
|
|
45
|
+
const entity = (_a = this.apiEntities.get(node.entityId)) !== null && _a !== void 0 ? _a : null;
|
|
46
|
+
const rows = (_b = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _b === void 0 ? void 0 : _b.AssemblyPosition;
|
|
47
|
+
return {
|
|
48
|
+
entityId: node.entityId,
|
|
49
|
+
name: node.name,
|
|
50
|
+
parentId: (_c = node.parentId) !== null && _c !== void 0 ? _c : null,
|
|
51
|
+
local: Manager.MatrixFromRows(rows) ? rows : null,
|
|
52
|
+
current: rowsOf(this.localAt(node.entityId, at)),
|
|
53
|
+
entity
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The root's world frame at a time, history and simulation included, eg. to follow or frame the Assembly.
|
|
59
|
+
* @param timeMs the scene time. Default: the clock's.
|
|
60
|
+
* @returns null until the root has been read.
|
|
61
|
+
*/
|
|
62
|
+
GetRootFrame(timeMs) {
|
|
63
|
+
const root = this.rootAt(timeMs !== null && timeMs !== void 0 ? timeMs : Cesium.JulianDate.toDate(this.viewer.clock.currentTime).getTime());
|
|
64
|
+
return root ? Manager.rootFrame(root.pos3d, root.heading, root.pitch, root.roll) : null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A part's world frame at a time as its records and its parents place it, size included.
|
|
68
|
+
* @param entityId the part.
|
|
69
|
+
* @param timeMs the scene time. Default: the clock's.
|
|
70
|
+
* @returns null until the root and the part have been read.
|
|
71
|
+
*/
|
|
72
|
+
GetPartFrame(entityId, timeMs) {
|
|
73
|
+
const at = timeMs !== null && timeMs !== void 0 ? timeMs : Cesium.JulianDate.toDate(this.viewer.clock.currentTime).getTime();
|
|
74
|
+
const rootFrame = this.GetRootFrame(at);
|
|
75
|
+
const world = entityId === this.rootId ? Cesium.Matrix4.IDENTITY : this.composeWorld(entityId, at);
|
|
76
|
+
if (!rootFrame || !world) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
// Where the part is drawn, so its own ground offset is part of its frame.
|
|
80
|
+
const ground = this.groundOffsets.get(entityId);
|
|
81
|
+
const placed = ground ? Cesium.Matrix4.multiply(Cesium.Matrix4.fromTranslation(ground), world, new Cesium.Matrix4()) : world;
|
|
82
|
+
return Cesium.Matrix4.multiply(rootFrame, placed, new Cesium.Matrix4());
|
|
83
|
+
}
|
|
35
84
|
constructor(params) {
|
|
36
85
|
this.disposed = false;
|
|
37
86
|
// Cache of the hierarchy so that our scene-tree can reference it.
|
|
@@ -41,19 +90,41 @@ var AssemblyRenderManager;
|
|
|
41
90
|
this.hierarchyNodeByEntityId = null;
|
|
42
91
|
this.modelSpace = false;
|
|
43
92
|
this.rootId = null;
|
|
44
|
-
// Where the root sits
|
|
45
|
-
// Every child is placed through this, so a root move is one value changing rather than a refetch of the whole Assembly.
|
|
93
|
+
// Where the root sits outside its history, and which way it faces in degrees. Children are placed through it.
|
|
46
94
|
this.rootPos3d = null;
|
|
47
95
|
this.rootHeading = 0;
|
|
48
|
-
|
|
96
|
+
this.rootPitch = 0;
|
|
97
|
+
this.rootRoll = 0;
|
|
98
|
+
// The root's recorded positions and attitudes, oldest first, kept apart since a record may name only one.
|
|
99
|
+
this.rootSeries = [];
|
|
100
|
+
this.rootAttitude = [];
|
|
101
|
+
// Every placement worked out for the scene time last asked about, shared by all parts drawn at it.
|
|
102
|
+
this.pose = null;
|
|
103
|
+
// Entity ID -> what was drawn for it.
|
|
49
104
|
this.children = new Map();
|
|
105
|
+
// Entity ID -> its live position within its parent, for every node fetched including undrawn groups.
|
|
106
|
+
this.localPositions = new Map();
|
|
107
|
+
// Entity ID -> how much higher the ground under it is than under the root, along the root's up.
|
|
108
|
+
this.groundOffsets = new Map();
|
|
109
|
+
// Entity ID -> its recorded poses within its parent, oldest first.
|
|
110
|
+
this.jointSeries = new Map();
|
|
111
|
+
// Drawn children that can move with the clock, so a tick places only these and not the whole Assembly.
|
|
112
|
+
this.animatedIds = new Set();
|
|
50
113
|
// The trail through the root's own movement, which describes the whole Assembly.
|
|
51
|
-
this.
|
|
114
|
+
this.trail = null;
|
|
115
|
+
this.simulationRemoval = null;
|
|
116
|
+
this.FollowsSimulation = true;
|
|
117
|
+
// Entity ID -> the record the API gave, so a cleared simulation falls back to it without a refetch.
|
|
118
|
+
this.apiEntities = new Map();
|
|
119
|
+
// Re-reads history and re-applies it, eg. after simulated records change. Set while the clock is followed.
|
|
120
|
+
this.regather = null;
|
|
121
|
+
this.followingClock = false;
|
|
52
122
|
// Callback to dispose the link between scene time and the root's historic position.
|
|
53
123
|
this.viewerDateTimeChangeRemoval = null;
|
|
54
124
|
this.historicGatherer = null;
|
|
55
125
|
this.historicAnimation = null;
|
|
56
126
|
const { viewer, register: visualsManager, getters, item } = params;
|
|
127
|
+
this.simulation = params.simulation;
|
|
57
128
|
this.viewer = viewer;
|
|
58
129
|
this.getters = getters;
|
|
59
130
|
this.item = item;
|
|
@@ -77,10 +148,10 @@ var AssemblyRenderManager;
|
|
|
77
148
|
return entity_render_engine_1.EntityRenderEngine.GetHeightRef((_b = (_a = item === null || item === void 0 ? void 0 : item.Style) === null || _a === void 0 ? void 0 : _a.Settings) === null || _b === void 0 ? void 0 : _b["modelStyle"]);
|
|
78
149
|
}
|
|
79
150
|
/*
|
|
80
|
-
* The root's frame: east-north-up at its position, turned by its heading.
|
|
151
|
+
* The root's frame: east-north-up at its position, turned by its heading, pitch and roll.
|
|
81
152
|
*/
|
|
82
|
-
static rootFrame(rootPos3d, headingDegrees) {
|
|
83
|
-
const hpr = new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(headingDegrees || 0), 0, 0);
|
|
153
|
+
static rootFrame(rootPos3d, headingDegrees, pitchDegrees = 0, rollDegrees = 0) {
|
|
154
|
+
const hpr = new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(headingDegrees || 0), Cesium.Math.toRadians(pitchDegrees || 0), Cesium.Math.toRadians(rollDegrees || 0));
|
|
84
155
|
return Cesium.Transforms.headingPitchRollToFixedFrame(rootPos3d, hpr);
|
|
85
156
|
}
|
|
86
157
|
/**
|
|
@@ -103,28 +174,553 @@ var AssemblyRenderManager;
|
|
|
103
174
|
return Cesium.Matrix4.multiplyByPoint(Manager.rootFrame(rootPos3d, headingDegrees), offset, new Cesium.Cartesian3());
|
|
104
175
|
}
|
|
105
176
|
/**
|
|
106
|
-
* Moves the
|
|
177
|
+
* Moves where the root sits outside its history, without refetching children; recorded poses still win.
|
|
107
178
|
* @param params
|
|
108
179
|
*/
|
|
109
180
|
ApplyRootPosition(params) {
|
|
110
|
-
var _a, _b;
|
|
181
|
+
var _a, _b, _c, _d, _e, _f;
|
|
111
182
|
if (this.disposed || !(params === null || params === void 0 ? void 0 : params.pos3d)) {
|
|
112
183
|
return;
|
|
113
184
|
}
|
|
114
185
|
this.rootPos3d = params.pos3d;
|
|
115
186
|
this.rootHeading = (_b = (_a = params.heading) !== null && _a !== void 0 ? _a : this.rootHeading) !== null && _b !== void 0 ? _b : 0;
|
|
187
|
+
this.rootPitch = (_d = (_c = params.pitch) !== null && _c !== void 0 ? _c : this.rootPitch) !== null && _d !== void 0 ? _d : 0;
|
|
188
|
+
this.rootRoll = (_f = (_e = params.roll) !== null && _e !== void 0 ? _e : this.rootRoll) !== null && _f !== void 0 ? _f : 0;
|
|
189
|
+
this.repose(true);
|
|
190
|
+
}
|
|
191
|
+
/*
|
|
192
|
+
* Drops every placement worked out so far, after the root or a joint's records change.
|
|
193
|
+
* @param everyChild re-place the parts that cannot move as well, because where they rest has changed.
|
|
194
|
+
*/
|
|
195
|
+
repose(everyChild = false) {
|
|
196
|
+
this.pose = null;
|
|
116
197
|
for (const child of this.children.values()) {
|
|
117
|
-
|
|
118
|
-
|
|
198
|
+
if (everyChild || Boolean(child.moving) != this.canMove(child.entityId)) {
|
|
199
|
+
this.bindPlacement(child);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
this.viewer.scene.requestRender();
|
|
203
|
+
}
|
|
204
|
+
/*
|
|
205
|
+
* Takes a node's pose outside its history from its record, and for the root where it stands and faces.
|
|
206
|
+
*/
|
|
207
|
+
absorbNode(entity) {
|
|
208
|
+
var _a, _b, _c, _d, _e;
|
|
209
|
+
const id = (_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.ID;
|
|
210
|
+
const local = Manager.MatrixFromRows((_b = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _b === void 0 ? void 0 : _b.AssemblyPosition);
|
|
211
|
+
if (local) {
|
|
212
|
+
this.localPositions.set(id, local);
|
|
213
|
+
}
|
|
214
|
+
// Anchored on the root, which is usually never drawn; everything under it is placed from the hierarchy.
|
|
215
|
+
if (id === this.rootId || (!this.rootId && !this.rootPos3d)) {
|
|
216
|
+
const rootPos3d = entity_utils_1.EntityUtils.GetPos({
|
|
217
|
+
viewer: this.viewer,
|
|
218
|
+
entity,
|
|
219
|
+
recordHeightRef: Manager.GetRecordHeightRef(this.item),
|
|
220
|
+
returnHeightRef: Cesium.HeightReference.NONE,
|
|
221
|
+
allowRendered: false
|
|
222
|
+
});
|
|
223
|
+
if (rootPos3d) {
|
|
224
|
+
this.rootPos3d = rootPos3d;
|
|
225
|
+
this.rootHeading = (0, js_utils_1.EnsureNumber)((_c = entity.Bruce.Transform) === null || _c === void 0 ? void 0 : _c.heading, 0);
|
|
226
|
+
this.rootPitch = (0, js_utils_1.EnsureNumber)((_d = entity.Bruce.Transform) === null || _d === void 0 ? void 0 : _d.pitch, 0);
|
|
227
|
+
this.rootRoll = (0, js_utils_1.EnsureNumber)((_e = entity.Bruce.Transform) === null || _e === void 0 ? void 0 : _e.roll, 0);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/*
|
|
232
|
+
* A node's record with its simulation laid over it, keeping what a stand-in leaves out, eg. its model.
|
|
233
|
+
*/
|
|
234
|
+
withSimulation(entity) {
|
|
235
|
+
var _a;
|
|
236
|
+
const id = (_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.ID;
|
|
237
|
+
if (!this.simulation || !id) {
|
|
238
|
+
return entity;
|
|
239
|
+
}
|
|
240
|
+
const standIn = this.simulation.GetEntity(id);
|
|
241
|
+
if (!standIn) {
|
|
242
|
+
return this.simulation.Overlay(entity);
|
|
243
|
+
}
|
|
244
|
+
return { ...entity, ...standIn, Bruce: { ...entity.Bruce, ...standIn.Bruce } };
|
|
245
|
+
}
|
|
246
|
+
/*
|
|
247
|
+
* Brings the Assembly in line with a change to what is simulated.
|
|
248
|
+
*/
|
|
249
|
+
onSimulationChanged(change) {
|
|
250
|
+
var _a;
|
|
251
|
+
if (this.disposed || !this.hierarchyNodeByEntityId) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const ids = change.entityIds.filter(id => this.hierarchyNodeByEntityId[id]);
|
|
255
|
+
if (!ids.length) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (change.entities) {
|
|
259
|
+
for (const id of ids) {
|
|
260
|
+
const api = this.apiEntities.get(id);
|
|
261
|
+
if (!api) {
|
|
262
|
+
// Not loaded yet, and it will be drawn from its simulation when it is.
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const entity = this.withSimulation(api);
|
|
266
|
+
// A cleared blob leaves the node's own matrix where the API has none, so it is reset.
|
|
267
|
+
if (!((_a = entity.Bruce) === null || _a === void 0 ? void 0 : _a.AssemblyPosition)) {
|
|
268
|
+
this.localPositions.delete(id);
|
|
269
|
+
}
|
|
270
|
+
this.absorbNode(entity);
|
|
271
|
+
const child = this.children.get(id);
|
|
272
|
+
if (child) {
|
|
273
|
+
child.entity = entity;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
this.repose(true);
|
|
277
|
+
}
|
|
278
|
+
if (change.records) {
|
|
279
|
+
if (this.regather) {
|
|
280
|
+
this.regather(true);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
this.viewerDateTimeSub();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/*
|
|
288
|
+
* Nodes of this Assembly with simulated history.
|
|
289
|
+
*/
|
|
290
|
+
simulatedNodeIds() {
|
|
291
|
+
if (!this.simulation || !this.hierarchyNodeByEntityId) {
|
|
292
|
+
return [];
|
|
293
|
+
}
|
|
294
|
+
return this.simulation.GetRecordEntityIds().filter(id => this.hierarchyNodeByEntityId[id]);
|
|
295
|
+
}
|
|
296
|
+
/*
|
|
297
|
+
* Whether a node can move with time: the root has history, or it or an ancestor does.
|
|
298
|
+
*/
|
|
299
|
+
canMove(entityId) {
|
|
300
|
+
return this.rootSeries.length > 0 || this.rootAttitude.length > 0 || this.animatedIds.has(entityId);
|
|
301
|
+
}
|
|
302
|
+
/*
|
|
303
|
+
* Gives a child its position and orientation, as functions of scene time only when it can move.
|
|
304
|
+
*/
|
|
305
|
+
bindPlacement(child) {
|
|
306
|
+
const id = child.entityId;
|
|
307
|
+
const moving = this.canMove(id);
|
|
308
|
+
if (moving) {
|
|
309
|
+
if (!child.moving) {
|
|
310
|
+
child.cEntity.position = new Cesium.CallbackProperty((time, result) => { var _a; return Manager.cloneOrUndefined((_a = this.placementAt(id, time)) === null || _a === void 0 ? void 0 : _a.pos3d, result); }, false);
|
|
311
|
+
child.cEntity.orientation = new Cesium.CallbackProperty((time, result) => {
|
|
312
|
+
var _a;
|
|
313
|
+
const orient = (_a = this.placementAt(id, time)) === null || _a === void 0 ? void 0 : _a.orient;
|
|
314
|
+
return orient ? Cesium.Quaternion.clone(orient, result) : undefined;
|
|
315
|
+
}, false);
|
|
316
|
+
child.cEntity.model.scale = new Cesium.CallbackProperty((time) => { var _a, _b; return (_b = (_a = this.placementAt(id, time)) === null || _a === void 0 ? void 0 : _a.scale) !== null && _b !== void 0 ? _b : 1; }, false);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
const placed = this.placementAt(id, this.viewer.clock.currentTime);
|
|
321
|
+
if (placed) {
|
|
322
|
+
child.cEntity.position = new Cesium.ConstantPositionProperty(placed.pos3d);
|
|
323
|
+
if (placed.orient) {
|
|
324
|
+
child.cEntity.orientation = new Cesium.ConstantProperty(placed.orient);
|
|
325
|
+
}
|
|
326
|
+
child.cEntity.model.scale = new Cesium.ConstantProperty(placed.scale);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (Boolean(child.moving) != moving) {
|
|
330
|
+
child.moving = moving;
|
|
331
|
+
this.visualsManager.SetMoving({ moving, entityIds: [id], menuItemId: this.item.id });
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/*
|
|
335
|
+
* The one scale a model takes from its part's composed matrix, the largest when they are uneven.
|
|
336
|
+
*/
|
|
337
|
+
static uniformScale(world) {
|
|
338
|
+
return Cesium.Cartesian3.maximumComponent(Cesium.Matrix4.getScale(world, new Cesium.Cartesian3()));
|
|
339
|
+
}
|
|
340
|
+
static cloneOrUndefined(pos3d, result) {
|
|
341
|
+
return pos3d ? Cesium.Cartesian3.clone(pos3d, result) : undefined;
|
|
342
|
+
}
|
|
343
|
+
/*
|
|
344
|
+
* Where a node draws at a scene time, from one composition shared by every part asked about at that time.
|
|
345
|
+
*/
|
|
346
|
+
placementAt(entityId, time) {
|
|
347
|
+
if (this.disposed || !time) {
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
const timeMs = Cesium.JulianDate.toDate(time).getTime();
|
|
351
|
+
if (!this.pose || this.pose.timeMs !== timeMs) {
|
|
352
|
+
const root = this.rootAt(timeMs);
|
|
353
|
+
this.pose = {
|
|
354
|
+
timeMs,
|
|
355
|
+
rootFrame: root ? Manager.rootFrame(root.pos3d, root.heading, root.pitch, root.roll) : null,
|
|
356
|
+
worlds: new Map(),
|
|
357
|
+
placements: new Map()
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const pose = this.pose;
|
|
361
|
+
if (!pose.rootFrame) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
let placed = pose.placements.get(entityId);
|
|
365
|
+
if (!placed) {
|
|
366
|
+
const world = this.composeWorld(entityId, timeMs, pose.worlds);
|
|
367
|
+
const offset = world
|
|
368
|
+
? Cesium.Matrix4.getTranslation(world, new Cesium.Cartesian3())
|
|
369
|
+
: new Cesium.Cartesian3(0, 0, 0);
|
|
370
|
+
const ground = this.groundOffsets.get(entityId);
|
|
371
|
+
if (ground) {
|
|
372
|
+
Cesium.Cartesian3.add(offset, ground, offset);
|
|
373
|
+
}
|
|
374
|
+
placed = {
|
|
375
|
+
pos3d: Cesium.Matrix4.multiplyByPoint(pose.rootFrame, offset, new Cesium.Cartesian3()),
|
|
376
|
+
// Without a matrix, eg. the root itself, there is no orientation of its own to apply.
|
|
377
|
+
orient: world ? entity_utils_1.EntityUtils.GetAssemblyOrientationInFrame(pose.rootFrame, world) : null,
|
|
378
|
+
scale: world ? Manager.uniformScale(world) : 1
|
|
379
|
+
};
|
|
380
|
+
pose.placements.set(entityId, placed);
|
|
381
|
+
}
|
|
382
|
+
return placed;
|
|
383
|
+
}
|
|
384
|
+
/*
|
|
385
|
+
* The root's pose at a time, position and attitude each following their own records as a joint's do.
|
|
386
|
+
*/
|
|
387
|
+
rootAt(timeMs) {
|
|
388
|
+
const pos3d = this.rootPositionAt(timeMs);
|
|
389
|
+
if (!pos3d) {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
const live = { heading: this.rootHeading, pitch: this.rootPitch, roll: this.rootRoll };
|
|
393
|
+
const series = this.rootAttitude;
|
|
394
|
+
if (!series.length || timeMs < series[0].timeMs) {
|
|
395
|
+
return { pos3d, ...live };
|
|
396
|
+
}
|
|
397
|
+
let i = 0;
|
|
398
|
+
while (i < series.length - 1 && series[i + 1].timeMs <= timeMs) {
|
|
399
|
+
i++;
|
|
400
|
+
}
|
|
401
|
+
const a = series[i];
|
|
402
|
+
const b = series[i + 1];
|
|
403
|
+
const t = b ? (timeMs - a.timeMs) / (b.timeMs - a.timeMs) : 0;
|
|
404
|
+
const turn = (from, to, fallback) => {
|
|
405
|
+
var _a, _b, _c;
|
|
406
|
+
const x = (_a = from !== null && from !== void 0 ? from : fallback) !== null && _a !== void 0 ? _a : 0;
|
|
407
|
+
const y = (_c = (_b = (b ? to : from)) !== null && _b !== void 0 ? _b : fallback) !== null && _c !== void 0 ? _c : 0;
|
|
408
|
+
// The short way round, so 350 to 10 degrees turns through north rather than all the way back.
|
|
409
|
+
return x + (Cesium.Math.negativePiToPi(Cesium.Math.toRadians(y - x)) * 180 / Math.PI) * t;
|
|
410
|
+
};
|
|
411
|
+
return {
|
|
412
|
+
pos3d,
|
|
413
|
+
heading: turn(a.heading, b === null || b === void 0 ? void 0 : b.heading, live.heading),
|
|
414
|
+
pitch: turn(a.pitch, b === null || b === void 0 ? void 0 : b.pitch, live.pitch),
|
|
415
|
+
roll: turn(a.roll, b === null || b === void 0 ? void 0 : b.roll, live.roll)
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/*
|
|
419
|
+
* Where the root is at a time, from its recorded positions.
|
|
420
|
+
*/
|
|
421
|
+
rootPositionAt(timeMs) {
|
|
422
|
+
const series = this.rootSeries;
|
|
423
|
+
if (!series.length || timeMs < series[0].timeMs) {
|
|
424
|
+
return this.rootPos3d;
|
|
425
|
+
}
|
|
426
|
+
let i = 0;
|
|
427
|
+
while (i < series.length - 1 && series[i + 1].timeMs <= timeMs) {
|
|
428
|
+
i++;
|
|
429
|
+
}
|
|
430
|
+
const a = series[i];
|
|
431
|
+
const b = series[i + 1];
|
|
432
|
+
if (!b) {
|
|
433
|
+
return a.pos3d;
|
|
434
|
+
}
|
|
435
|
+
const t = (timeMs - a.timeMs) / (b.timeMs - a.timeMs);
|
|
436
|
+
// A straight line between orbit samples cuts up to a kilometre inside the path, so it is lifted back out.
|
|
437
|
+
const chord = Cesium.Cartesian3.lerp(a.pos3d, b.pos3d, t, new Cesium.Cartesian3());
|
|
438
|
+
const carto = Cesium.Cartographic.fromCartesian(chord);
|
|
439
|
+
return carto
|
|
440
|
+
? Cesium.Cartesian3.fromRadians(carto.longitude, carto.latitude, Cesium.Math.lerp(a.height, b.height, t))
|
|
441
|
+
: chord;
|
|
442
|
+
}
|
|
443
|
+
/*
|
|
444
|
+
* Takes the root's records into its series.
|
|
445
|
+
* @param replace the records are everything held for the root, so the series becomes exactly them.
|
|
446
|
+
* @returns whether the series changed.
|
|
447
|
+
*/
|
|
448
|
+
absorbRootRecords(posses, replace) {
|
|
449
|
+
if (!(posses === null || posses === void 0 ? void 0 : posses.length) && !(replace && this.rootSeries.length)) {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
const byTime = new Map(replace ? [] : this.rootSeries.map(k => [k.timeMs, k]));
|
|
453
|
+
for (const pos of posses) {
|
|
454
|
+
const carto = Cesium.Cartographic.fromCartesian(pos.pos3d);
|
|
455
|
+
if (!carto) {
|
|
119
456
|
continue;
|
|
120
457
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
458
|
+
byTime.set(pos.dateTime.getTime(), {
|
|
459
|
+
timeMs: pos.dateTime.getTime(),
|
|
460
|
+
pos3d: pos.pos3d,
|
|
461
|
+
height: carto.height
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
const series = Array.from(byTime.values()).sort((x, y) => x.timeMs - y.timeMs);
|
|
465
|
+
const changed = (series.length !== this.rootSeries.length ||
|
|
466
|
+
series.some((k, i) => !Cesium.Cartesian3.equals(k.pos3d, this.rootSeries[i].pos3d)));
|
|
467
|
+
this.rootSeries = series;
|
|
468
|
+
return changed;
|
|
469
|
+
}
|
|
470
|
+
/*
|
|
471
|
+
* Takes the angles the root's records name into its attitude series, apart from where it is.
|
|
472
|
+
* @param replace the records are everything held for the root, as for absorbRootRecords.
|
|
473
|
+
* @returns whether the series changed.
|
|
474
|
+
*/
|
|
475
|
+
absorbRootAttitude(records, replace) {
|
|
476
|
+
const angle = (transform, key) => {
|
|
477
|
+
var _a;
|
|
478
|
+
const value = (_a = transform === null || transform === void 0 ? void 0 : transform[key]) !== null && _a !== void 0 ? _a : transform === null || transform === void 0 ? void 0 : transform[key[0].toUpperCase() + key.slice(1)];
|
|
479
|
+
return value == null || isNaN(+value) ? null : +value;
|
|
480
|
+
};
|
|
481
|
+
const byTime = new Map(replace ? [] : this.rootAttitude.map(k => [k.timeMs, k]));
|
|
482
|
+
for (const record of records || []) {
|
|
483
|
+
const timeMs = (record === null || record === void 0 ? void 0 : record.dateTime) ? new Date(record.dateTime).getTime() : NaN;
|
|
484
|
+
const key = {
|
|
485
|
+
timeMs,
|
|
486
|
+
heading: angle(record === null || record === void 0 ? void 0 : record.transform, "heading"),
|
|
487
|
+
pitch: angle(record === null || record === void 0 ? void 0 : record.transform, "pitch"),
|
|
488
|
+
roll: angle(record === null || record === void 0 ? void 0 : record.transform, "roll")
|
|
489
|
+
};
|
|
490
|
+
if (isNaN(timeMs) || (key.heading == null && key.pitch == null && key.roll == null)) {
|
|
491
|
+
continue;
|
|
125
492
|
}
|
|
493
|
+
byTime.set(timeMs, key);
|
|
126
494
|
}
|
|
127
|
-
|
|
495
|
+
const series = Array.from(byTime.values()).sort((x, y) => x.timeMs - y.timeMs);
|
|
496
|
+
const held = this.rootAttitude;
|
|
497
|
+
const differs = (k, i) => (k.timeMs !== held[i].timeMs ||
|
|
498
|
+
k.heading !== held[i].heading ||
|
|
499
|
+
k.pitch !== held[i].pitch ||
|
|
500
|
+
k.roll !== held[i].roll);
|
|
501
|
+
const changed = series.length !== held.length || series.some(differs);
|
|
502
|
+
this.rootAttitude = series;
|
|
503
|
+
return changed;
|
|
504
|
+
}
|
|
505
|
+
/*
|
|
506
|
+
* A node's matrix in the root's frame at a time, from each ancestor's pose within its parent.
|
|
507
|
+
*/
|
|
508
|
+
composeWorld(entityId, timeMs, memo, localOf = (id) => this.localAt(id, timeMs)) {
|
|
509
|
+
var _a, _b, _c, _d;
|
|
510
|
+
if (memo === null || memo === void 0 ? void 0 : memo.has(entityId)) {
|
|
511
|
+
return memo.get(entityId);
|
|
512
|
+
}
|
|
513
|
+
let world = null;
|
|
514
|
+
const local = localOf(entityId);
|
|
515
|
+
if (local) {
|
|
516
|
+
const parentId = (_b = (_a = this.hierarchyNodeByEntityId) === null || _a === void 0 ? void 0 : _a[entityId]) === null || _b === void 0 ? void 0 : _b.parentId;
|
|
517
|
+
const parent = parentId ? this.composeWorld(parentId, timeMs, memo, localOf) : null;
|
|
518
|
+
world = parent ? Cesium.Matrix4.multiply(parent, local, new Cesium.Matrix4()) : Cesium.Matrix4.clone(local);
|
|
519
|
+
}
|
|
520
|
+
else if (entityId !== this.rootId) {
|
|
521
|
+
// A node whose own position was not fetched falls back to the API's composed matrix.
|
|
522
|
+
const child = this.children.get(entityId);
|
|
523
|
+
world = Manager.MatrixFromRows((_d = (_c = child === null || child === void 0 ? void 0 : child.entity) === null || _c === void 0 ? void 0 : _c.Bruce) === null || _d === void 0 ? void 0 : _d.AssemblyWorldPosition);
|
|
524
|
+
}
|
|
525
|
+
memo === null || memo === void 0 ? void 0 : memo.set(entityId, world);
|
|
526
|
+
return world;
|
|
527
|
+
}
|
|
528
|
+
/*
|
|
529
|
+
* Under a clamped or relative style, lifts a part by how much higher its ground is than the root's.
|
|
530
|
+
*/
|
|
531
|
+
measureGroundOffset(entity) {
|
|
532
|
+
var _a;
|
|
533
|
+
const entityId = (_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.ID;
|
|
534
|
+
this.groundOffsets.delete(entityId);
|
|
535
|
+
const root = this.apiEntities.get(this.rootId);
|
|
536
|
+
if (!entityId ||
|
|
537
|
+
entityId === this.rootId ||
|
|
538
|
+
!root ||
|
|
539
|
+
!this.rootPos3d ||
|
|
540
|
+
Manager.GetRecordHeightRef(this.item) === Cesium.HeightReference.NONE) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const rootFrame = Manager.rootFrame(this.rootPos3d, this.rootHeading, this.rootPitch, this.rootRoll);
|
|
544
|
+
const toRoot = Cesium.Matrix4.inverse(rootFrame, new Cesium.Matrix4());
|
|
545
|
+
const groundUp = (record) => {
|
|
546
|
+
const pos3d = entity_utils_1.EntityUtils.GetPos({
|
|
547
|
+
viewer: this.viewer,
|
|
548
|
+
entity: record,
|
|
549
|
+
recordHeightRef: Cesium.HeightReference.CLAMP_TO_GROUND,
|
|
550
|
+
returnHeightRef: Cesium.HeightReference.NONE,
|
|
551
|
+
allowRendered: false
|
|
552
|
+
});
|
|
553
|
+
return pos3d ? Cesium.Matrix4.multiplyByPoint(toRoot, pos3d, new Cesium.Cartesian3()).z : null;
|
|
554
|
+
};
|
|
555
|
+
const part = groundUp(entity);
|
|
556
|
+
const under = groundUp(root);
|
|
557
|
+
if (part == null || under == null || Math.abs(part - under) < 1e-6) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
this.groundOffsets.set(entityId, new Cesium.Cartesian3(0, 0, part - under));
|
|
561
|
+
}
|
|
562
|
+
/*
|
|
563
|
+
* The rigid Earth-fixed motion from where a part's record places it to where it is drawn at a time.
|
|
564
|
+
*/
|
|
565
|
+
motionAt(entityId, time) {
|
|
566
|
+
if (this.disposed || !time || !this.rootPos3d) {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
const timeMs = Cesium.JulianDate.toDate(time).getTime();
|
|
570
|
+
const root = this.rootAt(timeMs);
|
|
571
|
+
const drawn = this.composeWorld(entityId, timeMs, new Map());
|
|
572
|
+
const stored = this.composeWorld(entityId, timeMs, new Map(), (id) => {
|
|
573
|
+
var _a, _b, _c, _d;
|
|
574
|
+
return ((_d = (_c = Manager.MatrixFromRows((_b = (_a = this.apiEntities.get(id)) === null || _a === void 0 ? void 0 : _a.Bruce) === null || _b === void 0 ? void 0 : _b.AssemblyPosition)) !== null && _c !== void 0 ? _c : this.localPositions.get(id)) !== null && _d !== void 0 ? _d : null);
|
|
575
|
+
});
|
|
576
|
+
if (!root || !drawn || !stored) {
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
const drawnFixed = Cesium.Matrix4.multiply(Manager.rootFrame(root.pos3d, root.heading, root.pitch, root.roll), drawn, new Cesium.Matrix4());
|
|
580
|
+
const storedFixed = Cesium.Matrix4.multiply(Manager.rootFrame(this.rootPos3d, this.rootHeading, this.rootPitch, this.rootRoll), stored, new Cesium.Matrix4());
|
|
581
|
+
return Cesium.Matrix4.multiply(drawnFixed, Cesium.Matrix4.inverse(storedFixed, new Cesium.Matrix4()), new Cesium.Matrix4());
|
|
582
|
+
}
|
|
583
|
+
/*
|
|
584
|
+
* A node's pose within its parent at a time, interpolated between the records either side.
|
|
585
|
+
*/
|
|
586
|
+
localAt(entityId, timeMs) {
|
|
587
|
+
var _a;
|
|
588
|
+
// The live pose stands before the first record and the last record holds after it, as in an API read.
|
|
589
|
+
const live = (_a = this.localPositions.get(entityId)) !== null && _a !== void 0 ? _a : null;
|
|
590
|
+
const series = this.jointSeries.get(entityId);
|
|
591
|
+
if (!(series === null || series === void 0 ? void 0 : series.length) || timeMs == null || timeMs < series[0].timeMs) {
|
|
592
|
+
return live;
|
|
593
|
+
}
|
|
594
|
+
let i = 0;
|
|
595
|
+
while (i < series.length - 1 && series[i + 1].timeMs <= timeMs) {
|
|
596
|
+
i++;
|
|
597
|
+
}
|
|
598
|
+
const a = series[i];
|
|
599
|
+
const b = series[i + 1];
|
|
600
|
+
if (!b) {
|
|
601
|
+
return Cesium.Matrix4.fromTranslationQuaternionRotationScale(a.translation, a.rotation, a.scale);
|
|
602
|
+
}
|
|
603
|
+
const t = (timeMs - a.timeMs) / (b.timeMs - a.timeMs);
|
|
604
|
+
return Cesium.Matrix4.fromTranslationQuaternionRotationScale(Cesium.Cartesian3.lerp(a.translation, b.translation, t, new Cesium.Cartesian3()), Cesium.Quaternion.slerp(a.rotation, b.rotation, t, new Cesium.Quaternion()), Cesium.Cartesian3.lerp(a.scale, b.scale, t, new Cesium.Cartesian3()));
|
|
605
|
+
}
|
|
606
|
+
/*
|
|
607
|
+
* Rebuilds each node's keyframes from the historic records held so far.
|
|
608
|
+
* @returns whether any node has keyframes.
|
|
609
|
+
*/
|
|
610
|
+
absorbJointRecords(recordsByIds) {
|
|
611
|
+
var _a;
|
|
612
|
+
// Everything held is given, so a node with nothing left, eg. its simulated records cleared, stops moving.
|
|
613
|
+
for (const entityId of Array.from(this.jointSeries.keys())) {
|
|
614
|
+
if (!((_a = recordsByIds === null || recordsByIds === void 0 ? void 0 : recordsByIds[entityId]) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
615
|
+
this.jointSeries.delete(entityId);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
for (const entityId of Object.keys(recordsByIds || {})) {
|
|
619
|
+
const keyframes = [];
|
|
620
|
+
for (const record of recordsByIds[entityId] || []) {
|
|
621
|
+
const matrix = Manager.MatrixFromRows(record.assemblyPosition);
|
|
622
|
+
const timeMs = new Date(record.dateTime).getTime();
|
|
623
|
+
if (!matrix || isNaN(timeMs)) {
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
const scale = Cesium.Matrix4.getScale(matrix, new Cesium.Cartesian3());
|
|
627
|
+
const rotation = Cesium.Matrix4.getRotation(matrix, new Cesium.Matrix3());
|
|
628
|
+
keyframes.push({
|
|
629
|
+
timeMs,
|
|
630
|
+
translation: Cesium.Matrix4.getTranslation(matrix, new Cesium.Cartesian3()),
|
|
631
|
+
rotation: Cesium.Quaternion.fromRotationMatrix(rotation),
|
|
632
|
+
scale
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
if (keyframes.length) {
|
|
636
|
+
keyframes.sort((x, y) => x.timeMs - y.timeMs);
|
|
637
|
+
this.jointSeries.set(entityId, keyframes);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
this.refreshAnimated();
|
|
641
|
+
return this.jointSeries.size > 0;
|
|
642
|
+
}
|
|
643
|
+
/*
|
|
644
|
+
* Rebuilds which drawn children can move with the clock, by walking each one up to the root.
|
|
645
|
+
*/
|
|
646
|
+
refreshAnimated() {
|
|
647
|
+
this.animatedIds.clear();
|
|
648
|
+
if (!this.jointSeries.size) {
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
for (const entityId of this.children.keys()) {
|
|
652
|
+
if (this.hasAnimatedAncestry(entityId)) {
|
|
653
|
+
this.animatedIds.add(entityId);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
/*
|
|
658
|
+
* Whether a node or anything above it has keyframes, so the clock can move it.
|
|
659
|
+
*/
|
|
660
|
+
hasAnimatedAncestry(entityId) {
|
|
661
|
+
var _a, _b;
|
|
662
|
+
let at = entityId;
|
|
663
|
+
while (at && this.jointSeries.size) {
|
|
664
|
+
if (this.jointSeries.has(at)) {
|
|
665
|
+
return true;
|
|
666
|
+
}
|
|
667
|
+
at = (_b = (_a = this.hierarchyNodeByEntityId) === null || _a === void 0 ? void 0 : _a[at]) === null || _b === void 0 ? void 0 : _b.parentId;
|
|
668
|
+
}
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
/*
|
|
672
|
+
* Which nodes to ask history for.
|
|
673
|
+
*/
|
|
674
|
+
async historicEntityIds(api) {
|
|
675
|
+
var _a, _b;
|
|
676
|
+
// Through the Assembly when there is one, so the hierarchy follows the relation type on its record.
|
|
677
|
+
const assemblyId = this.item["Assembly.ID"];
|
|
678
|
+
const root = assemblyId ? { key: "root", AssemblyID: assemblyId } : { key: "root", RootID: this.rootId };
|
|
679
|
+
const historic = {
|
|
680
|
+
key: "historic",
|
|
681
|
+
Historic: { HistoricKey: ((_a = this.item.BruceEntity) === null || _a === void 0 ? void 0 : _a.historicAttrKey) || undefined }
|
|
682
|
+
};
|
|
683
|
+
const query = {
|
|
684
|
+
[bruce_models_1.DataLab.EReqKey.Primary]: { Items: [root, historic], Select: { Type: bruce_models_1.DataLab.ESelectType.Id } }
|
|
685
|
+
};
|
|
686
|
+
const load = 1000;
|
|
687
|
+
try {
|
|
688
|
+
const ids = [];
|
|
689
|
+
for (let skip = 0;; skip += load) {
|
|
690
|
+
const { items } = await bruce_models_1.DataLab.Run({ api, query, skip, load });
|
|
691
|
+
ids.push(...(items !== null && items !== void 0 ? items : []));
|
|
692
|
+
if (!items || items.length < load) {
|
|
693
|
+
return ids;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
catch (e) {
|
|
698
|
+
// An API without the historic criterion gets asked about every node, as before it existed.
|
|
699
|
+
console.warn("AssemblyRenderManager.historicEntityIds()", e);
|
|
700
|
+
}
|
|
701
|
+
return Object.keys((_b = this.hierarchyNodeByEntityId) !== null && _b !== void 0 ? _b : { [this.rootId]: null });
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Builds a matrix from the row-major rows that Bruce/AssemblyPosition and AssemblyWorldPosition use.
|
|
705
|
+
* @param rows
|
|
706
|
+
*/
|
|
707
|
+
static MatrixFromRows(rows) {
|
|
708
|
+
if (!Array.isArray(rows) || rows.length !== 4 || rows.some(r => !Array.isArray(r) || r.length !== 4)) {
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
return new Cesium.Matrix4(+rows[0][0], +rows[0][1], +rows[0][2], +rows[0][3], +rows[1][0], +rows[1][1], +rows[1][2], +rows[1][3], +rows[2][0], +rows[2][1], +rows[2][2], +rows[2][3], +rows[3][0], +rows[3][1], +rows[3][2], +rows[3][3]);
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* The inverse of MatrixFromRows.
|
|
715
|
+
* @param matrix
|
|
716
|
+
*/
|
|
717
|
+
static RowsFromMatrix(matrix) {
|
|
718
|
+
const rows = [];
|
|
719
|
+
for (let r = 0; r < 4; r++) {
|
|
720
|
+
const row = Cesium.Matrix4.getRow(matrix, r, new Cesium.Cartesian4());
|
|
721
|
+
rows.push([row.x, row.y, row.z, row.w]);
|
|
722
|
+
}
|
|
723
|
+
return rows;
|
|
128
724
|
}
|
|
129
725
|
Init() {
|
|
130
726
|
this.renderPriority = this.item.renderPriority;
|
|
@@ -132,6 +728,7 @@ var AssemblyRenderManager;
|
|
|
132
728
|
this.renderPriority = 1;
|
|
133
729
|
}
|
|
134
730
|
(async () => {
|
|
731
|
+
var _a, _b;
|
|
135
732
|
if (this.disposed) {
|
|
136
733
|
return;
|
|
137
734
|
}
|
|
@@ -147,6 +744,8 @@ var AssemblyRenderManager;
|
|
|
147
744
|
this.hierarchyUpdate.Trigger(hierarchy);
|
|
148
745
|
// Build hierarchy node cache for quick lookups
|
|
149
746
|
this.buildHierarchyNodes(hierarchy);
|
|
747
|
+
// A set for membership, since searching the list took minutes at 200k nodes.
|
|
748
|
+
const seenIds = new Set();
|
|
150
749
|
const traverseHierarchy = (node, leavesOnly) => {
|
|
151
750
|
var _a;
|
|
152
751
|
if (node.Children) {
|
|
@@ -155,7 +754,8 @@ var AssemblyRenderManager;
|
|
|
155
754
|
}
|
|
156
755
|
}
|
|
157
756
|
const addNode = !leavesOnly || !((_a = node.Children) === null || _a === void 0 ? void 0 : _a.length);
|
|
158
|
-
if (addNode && node.ID && !
|
|
757
|
+
if (addNode && node.ID && !seenIds.has(node.ID)) {
|
|
758
|
+
seenIds.add(node.ID);
|
|
159
759
|
flatEntityIds.push(node.ID);
|
|
160
760
|
}
|
|
161
761
|
};
|
|
@@ -174,17 +774,17 @@ var AssemblyRenderManager;
|
|
|
174
774
|
}
|
|
175
775
|
}
|
|
176
776
|
this.rootId = rootId;
|
|
777
|
+
this.simulationRemoval = (_b = (_a = this.simulation) === null || _a === void 0 ? void 0 : _a.OnChanged.Subscribe((change) => this.onSimulationChanged(change))) !== null && _b !== void 0 ? _b : null;
|
|
177
778
|
if (this.disposed) {
|
|
178
779
|
return;
|
|
179
780
|
}
|
|
180
781
|
else if (flatEntityIds.length === 0) {
|
|
181
782
|
return;
|
|
182
783
|
}
|
|
784
|
+
// Followed while the parts load: in a large Assembly loading takes far longer than anyone waits.
|
|
785
|
+
const following = this.viewerDateTimeSub();
|
|
183
786
|
await this.processEntityIds(flatEntityIds);
|
|
184
|
-
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
this.viewerDateTimeSub();
|
|
787
|
+
await following;
|
|
188
788
|
}
|
|
189
789
|
catch (e) {
|
|
190
790
|
console.error("AssemblyRenderManager.Manager.Init()", e);
|
|
@@ -216,7 +816,7 @@ var AssemblyRenderManager;
|
|
|
216
816
|
if (!batch.length) {
|
|
217
817
|
continue;
|
|
218
818
|
}
|
|
219
|
-
const { entities:
|
|
819
|
+
const { entities: apiEntities } = await bruce_models_1.Entity.GetListByIds({
|
|
220
820
|
entityIds: batch,
|
|
221
821
|
api: this.getters.GetBruceApi(),
|
|
222
822
|
expandLODs: true,
|
|
@@ -228,6 +828,16 @@ var AssemblyRenderManager;
|
|
|
228
828
|
if (this.disposed) {
|
|
229
829
|
return;
|
|
230
830
|
}
|
|
831
|
+
const fetched = apiEntities.map((entity) => {
|
|
832
|
+
var _a;
|
|
833
|
+
this.apiEntities.set((_a = entity.Bruce) === null || _a === void 0 ? void 0 : _a.ID, entity);
|
|
834
|
+
return this.withSimulation(entity);
|
|
835
|
+
});
|
|
836
|
+
for (const entity of fetched) {
|
|
837
|
+
this.absorbNode(entity);
|
|
838
|
+
}
|
|
839
|
+
// Placements already worked out did not know about this batch's positions.
|
|
840
|
+
this.pose = null;
|
|
231
841
|
for (const entity of fetched) {
|
|
232
842
|
// Filter for valid LODs then take the highest quality one (lowest level).
|
|
233
843
|
let lods = entity.Bruce.LOD || [];
|
|
@@ -250,57 +860,46 @@ var AssemblyRenderManager;
|
|
|
250
860
|
// Won't bother with vector data for this experiment.
|
|
251
861
|
continue;
|
|
252
862
|
}
|
|
253
|
-
const recordHeightRef = Manager.GetRecordHeightRef(this.item);
|
|
254
|
-
const recordPos3d = entity_utils_1.EntityUtils.GetPos({
|
|
255
|
-
viewer: this.viewer,
|
|
256
|
-
entity,
|
|
257
|
-
recordHeightRef: recordHeightRef,
|
|
258
|
-
returnHeightRef: Cesium.HeightReference.NONE,
|
|
259
|
-
allowRendered: false
|
|
260
|
-
});
|
|
261
|
-
if (!recordPos3d) {
|
|
262
|
-
continue;
|
|
263
|
-
}
|
|
264
863
|
const entityId = entity.Bruce.ID;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
864
|
+
this.measureGroundOffset(entity);
|
|
865
|
+
// A placement cached before the offset was known would leave the part off its ground.
|
|
866
|
+
(_a = this.pose) === null || _a === void 0 ? void 0 : _a.placements.delete(entityId);
|
|
867
|
+
if (!this.canMove(entityId) && !this.placementAt(entityId, this.viewer.clock.currentTime)) {
|
|
868
|
+
continue;
|
|
269
869
|
}
|
|
270
|
-
// Held as an offset in the root's frame, so a root move places it again without
|
|
271
|
-
// anything being fetched. Where the root already moved, that is where it goes.
|
|
272
|
-
const offset = Manager.ChildOffsetIn(this.rootPos3d, this.rootHeading, recordPos3d);
|
|
273
|
-
const pos3d = Manager.ChildPositionFrom(this.rootPos3d, this.rootHeading, offset);
|
|
274
|
-
// Optional: a child with no world matrix is still worth drawing, it just has no
|
|
275
|
-
// orientation of its own to apply.
|
|
276
|
-
const orient = entity_utils_1.EntityUtils.GetAssemblyOrientation(entity, pos3d);
|
|
277
870
|
const cEntity = this.viewer.entities.add({
|
|
278
871
|
model: {
|
|
279
872
|
uri: lod["ClientFile"].URL,
|
|
280
873
|
...view_utils_1.ViewUtils.DefaultLightingProps(),
|
|
281
874
|
heightReference: Cesium.HeightReference.NONE
|
|
282
|
-
}
|
|
283
|
-
position: pos3d,
|
|
284
|
-
orientation: orient ? new Cesium.ConstantProperty(orient) : undefined
|
|
875
|
+
}
|
|
285
876
|
});
|
|
286
877
|
const prior = this.children.get(entityId);
|
|
287
878
|
if (prior && prior.cEntity !== cEntity) {
|
|
288
879
|
(0, cesium_utils_1.RemoveCEntityFromScene)(this.viewer, prior.cEntity);
|
|
289
880
|
}
|
|
290
|
-
|
|
881
|
+
const child = {
|
|
291
882
|
entityId: entityId,
|
|
292
883
|
entity: entity,
|
|
293
|
-
cEntity: cEntity
|
|
294
|
-
|
|
295
|
-
|
|
884
|
+
cEntity: cEntity
|
|
885
|
+
};
|
|
886
|
+
this.children.set(entityId, child);
|
|
887
|
+
// Joins the animated set by its own ancestry, so a late part never re-walks the rest.
|
|
888
|
+
if (this.hasAnimatedAncestry(entityId)) {
|
|
889
|
+
this.animatedIds.add(entityId);
|
|
890
|
+
}
|
|
296
891
|
const geometryRadius = bruce_models_1.Entity.GetValue({
|
|
297
892
|
entity: entity,
|
|
298
893
|
path: ["Bruce", "GeometryRadius"]
|
|
299
894
|
});
|
|
300
895
|
cEntity.model["_radius"] = geometryRadius;
|
|
301
896
|
cEntity.model["_radiusLoaded"] = true;
|
|
897
|
+
// Placed before it is registered, so the register never measures a visual with no position.
|
|
898
|
+
this.bindPlacement(child);
|
|
302
899
|
this.visualsManager.AddRego({
|
|
303
900
|
rego: {
|
|
901
|
+
moving: child.moving ? true : null,
|
|
902
|
+
motion: (time) => this.motionAt(entity.Bruce.ID, time),
|
|
304
903
|
canEdit: true,
|
|
305
904
|
entityId: entity.Bruce.ID,
|
|
306
905
|
menuItemId: this.item.id,
|
|
@@ -320,47 +919,89 @@ var AssemblyRenderManager;
|
|
|
320
919
|
}
|
|
321
920
|
}
|
|
322
921
|
/*
|
|
323
|
-
* Follows the scene clock
|
|
324
|
-
* Only the root is fetched: everything under it is placed through ApplyRootPosition.
|
|
922
|
+
* Follows the scene clock, moving the Assembly along the root's history and each joint along its own.
|
|
325
923
|
*/
|
|
326
|
-
viewerDateTimeSub() {
|
|
327
|
-
|
|
924
|
+
async viewerDateTimeSub() {
|
|
925
|
+
var _a;
|
|
926
|
+
const historic = Manager.IsHistoric(this.item);
|
|
927
|
+
if (this.followingClock || !this.rootId || (!historic && !this.simulatedNodeIds().length)) {
|
|
328
928
|
return;
|
|
329
929
|
}
|
|
930
|
+
this.followingClock = true;
|
|
330
931
|
const api = this.getters.GetBruceApi();
|
|
331
|
-
const
|
|
932
|
+
const historicIds = historic ? await this.historicEntityIds(api) : [];
|
|
933
|
+
if (this.disposed) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
const attrKey = (_a = this.item.BruceEntity) === null || _a === void 0 ? void 0 : _a.historicAttrKey;
|
|
332
937
|
const recordHeightRef = Manager.GetRecordHeightRef(this.item);
|
|
333
938
|
const toPosses = (records) => {
|
|
334
939
|
return cesium_animated_property_1.CesiumAnimatedProperty.GetSeriesPossesForHistoricEntity(this.viewer, recordHeightRef, Cesium.HeightReference.NONE, records);
|
|
335
940
|
};
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
941
|
+
if (historicIds.length) {
|
|
942
|
+
this.historicGatherer = new historic_utils_1.HistoricGatherer({
|
|
943
|
+
viewer: this.viewer,
|
|
944
|
+
getApi: () => api,
|
|
945
|
+
getAttrKey: () => attrKey,
|
|
946
|
+
// For clock desync between whatever wrote the record and this client.
|
|
947
|
+
paddingMs: 15000,
|
|
948
|
+
simulation: this.simulation,
|
|
949
|
+
onRecords: (recordsByIds) => {
|
|
950
|
+
var _a;
|
|
951
|
+
const records = recordsByIds[this.rootId];
|
|
952
|
+
if (records === null || records === void 0 ? void 0 : records.length) {
|
|
953
|
+
const posses = toPosses(records);
|
|
954
|
+
(_a = this.historicAnimation) === null || _a === void 0 ? void 0 : _a.SupplementSeries(posses);
|
|
955
|
+
const moved = this.absorbRootRecords(posses, false);
|
|
956
|
+
if (this.absorbRootAttitude(records, false) || moved) {
|
|
957
|
+
this.repose();
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
// Joint records go in together once the gather lands, so parents never draw apart from children.
|
|
346
961
|
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
// The nodes with history: what the API has records for, and whatever has been simulated since.
|
|
965
|
+
const nodes = () => Array.from(new Set([...historicIds, ...this.simulatedNodeIds()]));
|
|
349
966
|
let gathering = false;
|
|
350
|
-
|
|
967
|
+
// Set when what is held changed without a fetch, eg. a simulated record arriving.
|
|
968
|
+
let stale = true;
|
|
969
|
+
const gather = async (force) => {
|
|
970
|
+
var _a, _b;
|
|
971
|
+
stale = stale || Boolean(force);
|
|
351
972
|
if (this.disposed || gathering) {
|
|
352
973
|
return;
|
|
353
974
|
}
|
|
354
975
|
gathering = true;
|
|
355
976
|
try {
|
|
356
|
-
const
|
|
977
|
+
const ids = nodes();
|
|
978
|
+
let fetched = false;
|
|
979
|
+
let recordsByIds;
|
|
980
|
+
if (this.historicGatherer) {
|
|
981
|
+
({ fetched, recordsByIds } = await this.historicGatherer.Gather(ids.map(id => ({ Bruce: { ID: id } }))));
|
|
982
|
+
}
|
|
983
|
+
else {
|
|
984
|
+
recordsByIds = (_b = (_a = this.simulation) === null || _a === void 0 ? void 0 : _a.MergeRecords({}, attrKey, ids)) !== null && _b !== void 0 ? _b : {};
|
|
985
|
+
}
|
|
357
986
|
if (this.disposed) {
|
|
358
987
|
return;
|
|
359
988
|
}
|
|
989
|
+
// A gather served from what is held changes nothing and runs every tick, so it stops here.
|
|
990
|
+
if (!fetched && !stale && this.jointSeries.size) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
stale = false;
|
|
994
|
+
let changed = this.absorbJointRecords(recordsByIds);
|
|
360
995
|
const posses = toPosses(recordsByIds[this.rootId] || []);
|
|
996
|
+
changed = this.absorbRootRecords(posses, true) || changed;
|
|
997
|
+
changed = this.absorbRootAttitude(recordsByIds[this.rootId] || [], true) || changed;
|
|
998
|
+
if (changed) {
|
|
999
|
+
this.repose();
|
|
1000
|
+
}
|
|
361
1001
|
if (!posses.length) {
|
|
362
1002
|
return;
|
|
363
1003
|
}
|
|
1004
|
+
// Held for the trail alone; where the root is drawn comes from rootAt(), never from its smoothing.
|
|
364
1005
|
if (!this.historicAnimation) {
|
|
365
1006
|
this.historicAnimation = new cesium_animated_property_1.CesiumAnimatedProperty.AnimatePositionSeries({
|
|
366
1007
|
posses: posses,
|
|
@@ -374,15 +1015,21 @@ var AssemblyRenderManager;
|
|
|
374
1015
|
}
|
|
375
1016
|
catch (e) {
|
|
376
1017
|
console.error("AssemblyRenderManager.viewerDateTimeSub()", e);
|
|
1018
|
+
// A gather that throws would throw again straight away, so the retry waits for the next tick.
|
|
1019
|
+
stale = false;
|
|
377
1020
|
}
|
|
378
1021
|
finally {
|
|
379
1022
|
gathering = false;
|
|
1023
|
+
// A change that landed mid-gather is not left for a tick that may never come on a paused clock.
|
|
1024
|
+
if (stale && !this.disposed) {
|
|
1025
|
+
gather();
|
|
1026
|
+
}
|
|
380
1027
|
}
|
|
381
1028
|
};
|
|
1029
|
+
this.regather = gather;
|
|
382
1030
|
gather();
|
|
383
1031
|
let lastTime = null;
|
|
384
1032
|
const tickRemoval = this.viewer.clock.onTick.addEventListener(() => {
|
|
385
|
-
var _a;
|
|
386
1033
|
if (this.disposed) {
|
|
387
1034
|
return;
|
|
388
1035
|
}
|
|
@@ -392,15 +1039,9 @@ var AssemblyRenderManager;
|
|
|
392
1039
|
}
|
|
393
1040
|
lastTime = now;
|
|
394
1041
|
gather();
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const pos3d = this.historicAnimation.GetValue();
|
|
399
|
-
if (pos3d) {
|
|
400
|
-
this.ApplyRootPosition({
|
|
401
|
-
pos3d: pos3d,
|
|
402
|
-
heading: (_a = this.historicAnimation.GetHeadingDegrees()) !== null && _a !== void 0 ? _a : this.rootHeading
|
|
403
|
-
});
|
|
1042
|
+
// Moving parts read the clock themselves when drawn, so the scene only needs a new frame.
|
|
1043
|
+
if (this.rootSeries.length || this.rootAttitude.length || this.animatedIds.size) {
|
|
1044
|
+
this.viewer.scene.requestRender();
|
|
404
1045
|
}
|
|
405
1046
|
});
|
|
406
1047
|
this.viewerDateTimeChangeRemoval = () => {
|
|
@@ -409,6 +1050,10 @@ var AssemblyRenderManager;
|
|
|
409
1050
|
(_a = this.historicGatherer) === null || _a === void 0 ? void 0 : _a.Dispose();
|
|
410
1051
|
this.historicGatherer = null;
|
|
411
1052
|
this.historicAnimation = null;
|
|
1053
|
+
this.regather = null;
|
|
1054
|
+
this.rootSeries = [];
|
|
1055
|
+
this.rootAttitude = [];
|
|
1056
|
+
this.pose = null;
|
|
412
1057
|
};
|
|
413
1058
|
}
|
|
414
1059
|
/*
|
|
@@ -416,7 +1061,7 @@ var AssemblyRenderManager;
|
|
|
416
1061
|
*/
|
|
417
1062
|
applyRootTrack() {
|
|
418
1063
|
var _a;
|
|
419
|
-
if (!this.item.historicDrawTrack || !this.historicAnimation || this.
|
|
1064
|
+
if (!this.item.historicDrawTrack || !this.historicAnimation || this.trail) {
|
|
420
1065
|
return;
|
|
421
1066
|
}
|
|
422
1067
|
const trackStyle = entity_render_engine_1.EntityRenderEngine.GetTrackStyle({
|
|
@@ -426,41 +1071,35 @@ var AssemblyRenderManager;
|
|
|
426
1071
|
if (!trackStyle) {
|
|
427
1072
|
return;
|
|
428
1073
|
}
|
|
429
|
-
this.
|
|
430
|
-
id: bruce_models_1.ObjectUtils.UId(15),
|
|
431
|
-
polyline: {
|
|
432
|
-
positions: new Cesium.CallbackProperty(() => { var _a, _b; return (_b = (_a = this.historicAnimation) === null || _a === void 0 ? void 0 : _a.GetSeries()) !== null && _b !== void 0 ? _b : []; }, false),
|
|
433
|
-
width: trackStyle.width,
|
|
434
|
-
material: trackStyle.color,
|
|
435
|
-
clampToGround: entity_render_engine_1.EntityRenderEngine.GetHeightRefPolyline(Manager.GetRecordHeightRef(this.item))
|
|
436
|
-
== Cesium.HeightReference.CLAMP_TO_GROUND,
|
|
437
|
-
zIndex: 0,
|
|
438
|
-
classificationType: Cesium.ClassificationType.BOTH
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
|
-
this.trackEntity._noEdit = true;
|
|
442
|
-
this.trackEntity._noSelect = true;
|
|
443
|
-
cesium_entity_styler_1.CesiumEntityStyler.SetDefaultColor({
|
|
444
|
-
color: trackStyle.color,
|
|
445
|
-
entity: this.trackEntity,
|
|
1074
|
+
this.trail = new historic_trail_1.HistoricTrail.Trail({
|
|
446
1075
|
viewer: this.viewer,
|
|
447
|
-
|
|
448
|
-
|
|
1076
|
+
color: trackStyle.color,
|
|
1077
|
+
width: trackStyle.width,
|
|
1078
|
+
clampToGround: entity_render_engine_1.EntityRenderEngine.GetHeightRefPolyline(Manager.GetRecordHeightRef(this.item))
|
|
1079
|
+
== Cesium.HeightReference.CLAMP_TO_GROUND,
|
|
1080
|
+
getSeries: () => { var _a, _b; return (_b = (_a = this.historicAnimation) === null || _a === void 0 ? void 0 : _a.GetSeries()) !== null && _b !== void 0 ? _b : []; },
|
|
1081
|
+
trailSeconds: historic_trail_1.HistoricTrail.GetTrailSeconds(this.item),
|
|
1082
|
+
// Where the root is drawn, so the trail ends on the model; nothing before the first record held.
|
|
1083
|
+
positionAt: (timeMs) => (this.rootSeries.length && timeMs >= this.rootSeries[0].timeMs ? this.rootPositionAt(timeMs) : null)
|
|
449
1084
|
});
|
|
450
1085
|
}
|
|
451
1086
|
Dispose() {
|
|
452
|
-
var _a;
|
|
1087
|
+
var _a, _b, _c;
|
|
453
1088
|
if (this.disposed) {
|
|
454
1089
|
return;
|
|
455
1090
|
}
|
|
456
1091
|
this.disposed = true;
|
|
457
1092
|
(_a = this.viewerDateTimeChangeRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
458
1093
|
this.viewerDateTimeChangeRemoval = null;
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
1094
|
+
(_b = this.simulationRemoval) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
1095
|
+
this.simulationRemoval = null;
|
|
1096
|
+
this.apiEntities.clear();
|
|
1097
|
+
(_c = this.trail) === null || _c === void 0 ? void 0 : _c.Dispose();
|
|
1098
|
+
this.trail = null;
|
|
463
1099
|
this.children.clear();
|
|
1100
|
+
this.localPositions.clear();
|
|
1101
|
+
this.jointSeries.clear();
|
|
1102
|
+
this.animatedIds.clear();
|
|
464
1103
|
this.visualsManager.RemoveRegos({
|
|
465
1104
|
menuItemId: this.item.id
|
|
466
1105
|
});
|