fl-web-component 2.0.8 → 2.0.10
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/README.md +4 -0
- package/dist/fl-web-component.common.2.js +126 -48
- package/dist/fl-web-component.common.2.js.map +1 -1
- package/dist/fl-web-component.common.js +7366 -1277
- package/dist/fl-web-component.common.js.map +1 -1
- package/dist/fl-web-component.css +1 -1
- package/package.json +1 -1
- package/packages/components/com-graphics/component/context.js +123 -0
- package/packages/components/com-graphics/index.vue +1243 -85
- package/packages/utils/StreamLoader.js +73 -16
- package/src/utils/threejs/editor/command.js +36 -0
- package/src/utils/threejs/editor/commands/add-element-command.js +41 -0
- package/src/utils/threejs/editor/commands/add-group-command.js +10 -0
- package/src/utils/threejs/editor/commands/clone-element-command.js +100 -0
- package/src/utils/threejs/editor/commands/move-element-command.js +57 -0
- package/src/utils/threejs/editor/commands/multi-command.js +29 -0
- package/src/utils/threejs/editor/commands/remove-element-command.js +46 -0
- package/src/utils/threejs/editor/commands/reset-original-model-style-command.js +30 -0
- package/src/utils/threejs/editor/commands/set-geometry-params-command.js +41 -0
- package/src/utils/threejs/editor/commands/set-original-model-style-command.js +56 -0
- package/src/utils/threejs/editor/commands/set-position-command.js +54 -0
- package/src/utils/threejs/editor/commands/set-rotation-command.js +53 -0
- package/src/utils/threejs/editor/commands/set-scale-command.js +54 -0
- package/src/utils/threejs/editor/commands/set-value-command.js +107 -0
- package/src/utils/threejs/editor/constants.js +107 -0
- package/src/utils/threejs/editor/element-factory.js +163 -0
- package/src/utils/threejs/editor/event-bus.js +34 -0
- package/src/utils/threejs/editor/history.js +80 -0
- package/src/utils/threejs/editor/scene-command-service.js +1529 -0
- package/src/utils/threejs/editor/scene-event-bridge.js +32 -0
- package/src/utils/threejs/editor/scene-helpers.js +415 -0
- package/src/utils/threejs/measure-angle.js +22 -2
- package/src/utils/threejs/measure-area.js +23 -3
- package/src/utils/threejs/measure-distance.js +20 -1
- package/src/utils/threejs/measure-height.js +17 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export default class SceneEventBridge {
|
|
2
|
+
constructor(options = {}) {
|
|
3
|
+
this.eventBus = options.eventBus;
|
|
4
|
+
this.getTreeSnapshot = options.getTreeSnapshot || (() => null);
|
|
5
|
+
this.getOriginalModelStyleChanges = options.getOriginalModelStyleChanges || (() => []);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
emit(eventName, payload) {
|
|
9
|
+
if (!this.eventBus) return;
|
|
10
|
+
this.eventBus.emit(eventName, payload);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
emitSceneGraphChanged(payload = {}) {
|
|
14
|
+
this.emit('sceneGraphChanged', {
|
|
15
|
+
tree: this.getTreeSnapshot(),
|
|
16
|
+
...payload,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
emitOriginalModelChangeListChanged(payload = {}) {
|
|
21
|
+
this.emit('originalModelChangeListChanged', {
|
|
22
|
+
list: this.getOriginalModelStyleChanges(),
|
|
23
|
+
...payload,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
destroy() {
|
|
28
|
+
if (this.eventBus && this.eventBus.clear) {
|
|
29
|
+
this.eventBus.clear();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CUSTOM_ROOT_DISPLAY_NAME,
|
|
3
|
+
CUSTOM_ROOT_NAME,
|
|
4
|
+
ELEMENT_LABELS,
|
|
5
|
+
SCENE_NODE_TYPE,
|
|
6
|
+
} from './constants';
|
|
7
|
+
|
|
8
|
+
export function degreesToRadians(value) {
|
|
9
|
+
return (Number(value) || 0) * (Math.PI / 180);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function radiansToDegrees(value) {
|
|
13
|
+
return (Number(value) || 0) * (180 / Math.PI);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function degreesArrayToRadians(rotation = []) {
|
|
17
|
+
return [
|
|
18
|
+
degreesToRadians(rotation[0]),
|
|
19
|
+
degreesToRadians(rotation[1]),
|
|
20
|
+
degreesToRadians(rotation[2]),
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function radiansArrayToDegrees(rotation = []) {
|
|
25
|
+
return [
|
|
26
|
+
radiansToDegrees(rotation[0]),
|
|
27
|
+
radiansToDegrees(rotation[1]),
|
|
28
|
+
radiansToDegrees(rotation[2]),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getObjectByUuid(scene, uuid) {
|
|
33
|
+
if (!scene || !uuid) return null;
|
|
34
|
+
return scene.getObjectByProperty('uuid', uuid) || null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function getObjectIndex(object) {
|
|
38
|
+
if (!object || !object.parent) return -1;
|
|
39
|
+
return object.parent.children.indexOf(object);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function clampInsertIndex(parent, index) {
|
|
43
|
+
if (!parent) return 0;
|
|
44
|
+
const length = parent.children.length;
|
|
45
|
+
if (typeof index !== 'number' || Number.isNaN(index)) return length;
|
|
46
|
+
if (index < 0) return 0;
|
|
47
|
+
if (index > length) return length;
|
|
48
|
+
return index;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function insertObjectAt(parent, object, index) {
|
|
52
|
+
if (!parent || !object) return;
|
|
53
|
+
parent.add(object);
|
|
54
|
+
const currentIndex = parent.children.indexOf(object);
|
|
55
|
+
const targetIndex = clampInsertIndex(parent, index);
|
|
56
|
+
if (currentIndex === -1 || currentIndex === targetIndex) return;
|
|
57
|
+
parent.children.splice(currentIndex, 1);
|
|
58
|
+
parent.children.splice(targetIndex, 0, object);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function removeObjectFromParent(object) {
|
|
62
|
+
if (!object || !object.parent) return;
|
|
63
|
+
object.parent.remove(object);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function isAncestor(target, possibleDescendant) {
|
|
67
|
+
let current = possibleDescendant;
|
|
68
|
+
while (current) {
|
|
69
|
+
if (current === target) return true;
|
|
70
|
+
current = current.parent;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function isCustomRoot(object) {
|
|
76
|
+
if (!object || !object.userData) return false;
|
|
77
|
+
if (object.userData.nodeType) {
|
|
78
|
+
return object.userData.nodeType === 'custom-root';
|
|
79
|
+
}
|
|
80
|
+
return object.userData.rootType === 'custom-root';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function isCustomElement(object) {
|
|
84
|
+
return !!(object && object.userData && object.userData.nodeType === 'custom-element');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function isCustomGroup(object) {
|
|
88
|
+
return !!(object && object.userData && object.userData.nodeType === 'custom-group');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function isSelectableObject(object) {
|
|
92
|
+
return isCustomRoot(object) || isCustomElement(object) || isCustomGroup(object);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function isTransformControlHelperObject(object) {
|
|
96
|
+
return !!(object && object.userData && object.userData.transformControlHelper === true);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function isHelperObject(object) {
|
|
100
|
+
if (!object) return false;
|
|
101
|
+
if (isTransformControlHelperObject(object)) return true;
|
|
102
|
+
if (object.type === 'Scene' || object.isCamera || object.isLight) return true;
|
|
103
|
+
if (typeof object.type === 'string' && /Helper$/i.test(object.type)) return true;
|
|
104
|
+
if (
|
|
105
|
+
object.type === 'AxesHelper' ||
|
|
106
|
+
object.type === 'GridHelper' ||
|
|
107
|
+
object.type === 'BoxHelper' ||
|
|
108
|
+
object.type === 'CSS2DObject' ||
|
|
109
|
+
object.type === 'TransformControlsRoot'
|
|
110
|
+
) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function getSceneNodeType(object) {
|
|
117
|
+
if (!object) return SCENE_NODE_TYPE.UNKNOWN;
|
|
118
|
+
if (isCustomElement(object)) return SCENE_NODE_TYPE.CUSTOM_ELEMENT;
|
|
119
|
+
if (isCustomGroup(object)) return SCENE_NODE_TYPE.CUSTOM_GROUP;
|
|
120
|
+
if (isCustomRoot(object)) return SCENE_NODE_TYPE.CUSTOM_ROOT;
|
|
121
|
+
if (isHelperObject(object)) return SCENE_NODE_TYPE.HELPER;
|
|
122
|
+
if (object.parent && !isHelperObject(object)) {
|
|
123
|
+
return SCENE_NODE_TYPE.ORIGINAL_MODEL;
|
|
124
|
+
}
|
|
125
|
+
return SCENE_NODE_TYPE.UNKNOWN;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function isOriginalModelObject(object) {
|
|
129
|
+
return getSceneNodeType(object) === SCENE_NODE_TYPE.ORIGINAL_MODEL;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function isEditableObject(object) {
|
|
133
|
+
return !!(object && object.userData && object.userData.editable === true);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function isDeletableObject(object) {
|
|
137
|
+
return !!(object && object.userData && object.userData.deletable === true);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function isCloneableObject(object) {
|
|
141
|
+
return !!(object && object.userData && object.userData.cloneable === true);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function isObjectVisible(object) {
|
|
145
|
+
let current = object;
|
|
146
|
+
while (current) {
|
|
147
|
+
if (current.visible === false) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
current = current.parent;
|
|
151
|
+
}
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function isTransformAttachableObject(object) {
|
|
156
|
+
return !!(
|
|
157
|
+
object &&
|
|
158
|
+
(isCustomElement(object) || isCustomGroup(object)) &&
|
|
159
|
+
isEditableObject(object) &&
|
|
160
|
+
isObjectVisible(object)
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function findSelectableObject(target) {
|
|
165
|
+
let current = target;
|
|
166
|
+
while (current) {
|
|
167
|
+
if (isSelectableObject(current) && isObjectVisible(current)) {
|
|
168
|
+
return current;
|
|
169
|
+
}
|
|
170
|
+
current = current.parent;
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function findSelectableSceneObject(target) {
|
|
176
|
+
let current = target;
|
|
177
|
+
while (current) {
|
|
178
|
+
if (isSelectableObject(current) && isObjectVisible(current)) {
|
|
179
|
+
return current;
|
|
180
|
+
}
|
|
181
|
+
if (isOriginalModelObject(current) && isObjectVisible(current)) {
|
|
182
|
+
return current;
|
|
183
|
+
}
|
|
184
|
+
current = current.parent;
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function ensureCustomRoot(scene, THREE) {
|
|
190
|
+
if (!scene || !THREE) return null;
|
|
191
|
+
let root = scene.children.find(child => isCustomRoot(child));
|
|
192
|
+
if (root) return root;
|
|
193
|
+
|
|
194
|
+
root = new THREE.Group();
|
|
195
|
+
root.name = CUSTOM_ROOT_NAME;
|
|
196
|
+
root.userData = {
|
|
197
|
+
nodeType: 'custom-root',
|
|
198
|
+
rootType: 'custom-root',
|
|
199
|
+
// displayName: CUSTOM_ROOT_DISPLAY_NAME,
|
|
200
|
+
editable: false,
|
|
201
|
+
deletable: false,
|
|
202
|
+
cloneable: false,
|
|
203
|
+
selectable: true,
|
|
204
|
+
};
|
|
205
|
+
scene.add(root);
|
|
206
|
+
return root;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function getElementBaseLabel(type) {
|
|
210
|
+
return ELEMENT_LABELS[type] || '元素';
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function getSiblingNames(parent, ignoreUuid) {
|
|
214
|
+
if (!parent) return [];
|
|
215
|
+
return parent.children
|
|
216
|
+
.filter(child => child && child.uuid !== ignoreUuid)
|
|
217
|
+
.map(child => child.name)
|
|
218
|
+
.filter(Boolean);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function createUniqueName(parent, baseName, options = {}) {
|
|
222
|
+
const siblingNames = getSiblingNames(parent, options.ignoreUuid);
|
|
223
|
+
if (!options.forceSuffix && !siblingNames.includes(baseName)) {
|
|
224
|
+
return baseName;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let index = typeof options.startIndex === 'number' ? options.startIndex : 1;
|
|
228
|
+
while (index < 100000) {
|
|
229
|
+
const suffix =
|
|
230
|
+
options.padding && options.padding > 1
|
|
231
|
+
? String(index).padStart(options.padding, '0')
|
|
232
|
+
: String(index);
|
|
233
|
+
const nextName = `${baseName}_${suffix}`;
|
|
234
|
+
if (!siblingNames.includes(nextName)) {
|
|
235
|
+
return nextName;
|
|
236
|
+
}
|
|
237
|
+
index += 1;
|
|
238
|
+
}
|
|
239
|
+
return `${baseName}_${Date.now()}`;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function createDefaultElementName(parent, type) {
|
|
243
|
+
return createUniqueName(parent, getElementBaseLabel(type), {
|
|
244
|
+
startIndex: 1,
|
|
245
|
+
forceSuffix: true,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function createDefaultGroupName(parent) {
|
|
250
|
+
return createUniqueName(parent, ELEMENT_LABELS.group, {
|
|
251
|
+
startIndex: 1,
|
|
252
|
+
padding: 3,
|
|
253
|
+
forceSuffix: true,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function applyTransform(object, transform = {}) {
|
|
258
|
+
if (!object || !transform) return;
|
|
259
|
+
const { position, rotation, scale } = transform;
|
|
260
|
+
if (Array.isArray(position) && position.length === 3) {
|
|
261
|
+
object.position.set(
|
|
262
|
+
Number(position[0]) || 0,
|
|
263
|
+
Number(position[1]) || 0,
|
|
264
|
+
Number(position[2]) || 0
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
if (Array.isArray(rotation) && rotation.length === 3) {
|
|
268
|
+
const [x, y, z] = degreesArrayToRadians(rotation);
|
|
269
|
+
object.rotation.set(x, y, z);
|
|
270
|
+
}
|
|
271
|
+
if (Array.isArray(scale) && scale.length === 3) {
|
|
272
|
+
object.scale.set(Number(scale[0]) || 1, Number(scale[1]) || 1, Number(scale[2]) || 1);
|
|
273
|
+
}
|
|
274
|
+
object.updateMatrixWorld(true);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function cloneUserData(userData = {}) {
|
|
278
|
+
return JSON.parse(JSON.stringify(userData));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function updateDisplayName(object) {
|
|
282
|
+
if (!object || !object.userData) return;
|
|
283
|
+
object.userData.displayName = object.name;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export function buildTreeSnapshot(object) {
|
|
287
|
+
if (!object) return null;
|
|
288
|
+
return {
|
|
289
|
+
uuid: object.uuid,
|
|
290
|
+
name: object.name,
|
|
291
|
+
// displayName:
|
|
292
|
+
// object.userData && object.userData.displayName ? object.userData.displayName : object.name,
|
|
293
|
+
nodeType: object.userData && object.userData.nodeType ? object.userData.nodeType : '',
|
|
294
|
+
elementType: object.userData && object.userData.elementType ? object.userData.elementType : '',
|
|
295
|
+
visible: object.visible,
|
|
296
|
+
children: object.children
|
|
297
|
+
.filter(child => isCustomElement(child) || isCustomGroup(child))
|
|
298
|
+
.map(child => buildTreeSnapshot(child)),
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function getMaterialSnapshot(material) {
|
|
303
|
+
if (!material) return null;
|
|
304
|
+
return {
|
|
305
|
+
color: material.color && material.color.isColor ? `#${material.color.getHexString()}` : null,
|
|
306
|
+
opacity: typeof material.opacity === 'number' ? material.opacity : 1,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function flattenCustomSaveNodeMaterial(saveNode = {}) {
|
|
311
|
+
const nextNode = { ...saveNode };
|
|
312
|
+
const material =
|
|
313
|
+
saveNode && saveNode.material && typeof saveNode.material === 'object' ? saveNode.material : null;
|
|
314
|
+
if (material) {
|
|
315
|
+
if (Object.prototype.hasOwnProperty.call(material, 'color')) {
|
|
316
|
+
nextNode.color = material.color;
|
|
317
|
+
}
|
|
318
|
+
if (Object.prototype.hasOwnProperty.call(material, 'opacity')) {
|
|
319
|
+
nextNode.opacity = material.opacity;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (Object.prototype.hasOwnProperty.call(nextNode, 'material')) {
|
|
323
|
+
delete nextNode.material;
|
|
324
|
+
}
|
|
325
|
+
return nextNode;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function buildObjectSnapshot(object) {
|
|
329
|
+
const nodeType = getSceneNodeType(object);
|
|
330
|
+
const primaryMaterial = object
|
|
331
|
+
? Array.isArray(object.material)
|
|
332
|
+
? object.material[0]
|
|
333
|
+
: object.material
|
|
334
|
+
: null;
|
|
335
|
+
if (!object) return null;
|
|
336
|
+
return {
|
|
337
|
+
uuid: object.uuid,
|
|
338
|
+
name: object.name,
|
|
339
|
+
// displayName:
|
|
340
|
+
// object.userData && object.userData.displayName ? object.userData.displayName : object.name,
|
|
341
|
+
nodeType,
|
|
342
|
+
// nodeType: object.userData && object.userData.nodeType ? object.userData.nodeType : '',
|
|
343
|
+
elementType: object.userData && object.userData.elementType ? object.userData.elementType : '',
|
|
344
|
+
visible: object.visible !== false,
|
|
345
|
+
position: [object.position.x, object.position.y, object.position.z],
|
|
346
|
+
rotation: radiansArrayToDegrees([object.rotation.x, object.rotation.y, object.rotation.z]),
|
|
347
|
+
scale: [object.scale.x, object.scale.y, object.scale.z],
|
|
348
|
+
material: getMaterialSnapshot(primaryMaterial),
|
|
349
|
+
geometryParams:
|
|
350
|
+
object.userData && object.userData.geometryParams
|
|
351
|
+
? cloneUserData(object.userData.geometryParams)
|
|
352
|
+
: null,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export function buildCustomTree(root) {
|
|
357
|
+
if (!root) return null;
|
|
358
|
+
return {
|
|
359
|
+
uuid: root.uuid,
|
|
360
|
+
name: root.name,
|
|
361
|
+
// displayName: root.userData && root.userData.displayName ? root.userData.displayName : root.name,
|
|
362
|
+
nodeType: root.userData && root.userData.nodeType ? root.userData.nodeType : 'custom-root',
|
|
363
|
+
children: root.children
|
|
364
|
+
.filter(child => isCustomElement(child) || isCustomGroup(child))
|
|
365
|
+
.map(child => buildTreeSnapshot(child)),
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export function buildCustomSaveTree(root) {
|
|
370
|
+
if (!root) return null;
|
|
371
|
+
const snapshot = buildObjectSnapshot(root);
|
|
372
|
+
const saveNode = {
|
|
373
|
+
...(snapshot || {
|
|
374
|
+
uuid: root.uuid,
|
|
375
|
+
name: root.name,
|
|
376
|
+
displayName:
|
|
377
|
+
root.userData && root.userData.displayName ? root.userData.displayName : root.name,
|
|
378
|
+
nodeType: root.userData && root.userData.nodeType ? root.userData.nodeType : 'custom-root',
|
|
379
|
+
elementType: '',
|
|
380
|
+
visible: root.visible !== false,
|
|
381
|
+
position: [root.position.x, root.position.y, root.position.z],
|
|
382
|
+
rotation: radiansArrayToDegrees([root.rotation.x, root.rotation.y, root.rotation.z]),
|
|
383
|
+
scale: [root.scale.x, root.scale.y, root.scale.z],
|
|
384
|
+
material: null,
|
|
385
|
+
geometryParams: null,
|
|
386
|
+
}),
|
|
387
|
+
children: root.children
|
|
388
|
+
.filter(child => isCustomElement(child) || isCustomGroup(child))
|
|
389
|
+
.map(child => buildCustomSaveTree(child)),
|
|
390
|
+
};
|
|
391
|
+
if (Object.prototype.hasOwnProperty.call(saveNode, 'uuid')) {
|
|
392
|
+
delete saveNode.uuid;
|
|
393
|
+
}
|
|
394
|
+
return flattenCustomSaveNodeMaterial(saveNode);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export function disposeObjectResources(object) {
|
|
398
|
+
if (!object) return;
|
|
399
|
+
object.traverse(child => {
|
|
400
|
+
if (child.isMesh) {
|
|
401
|
+
if (child.geometry && child.geometry.dispose) {
|
|
402
|
+
child.geometry.dispose();
|
|
403
|
+
}
|
|
404
|
+
if (Array.isArray(child.material)) {
|
|
405
|
+
child.material.forEach(material => {
|
|
406
|
+
if (material && material.dispose) {
|
|
407
|
+
material.dispose();
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
} else if (child.material && child.material.dispose) {
|
|
411
|
+
child.material.dispose();
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
}
|
|
@@ -24,7 +24,7 @@ var MeasureAngle = function (renderer, scene, camera, width, height) {
|
|
|
24
24
|
this.firstTime = 0;
|
|
25
25
|
// 创建一个辅助平面来捕获鼠标事件
|
|
26
26
|
this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
|
|
27
|
-
|
|
27
|
+
this.measureName = 'measureObj'
|
|
28
28
|
// this.POINT_MATERIAL = new THREE.PointsMaterial({ color: 0xff5000, size: 1, opacity: 0.6, transparent: true, depthWrite: false, depthTest: false })
|
|
29
29
|
// this.LINE_MATERIAL = new THREE.LineBasicMaterial({ color: 0xff0000, linewidth: 3, opacity: 0.8, transparent: true, side: THREE.DoubleSide, depthWrite: false, depthTest: false })
|
|
30
30
|
};
|
|
@@ -89,6 +89,7 @@ MeasureAngle.prototype = {
|
|
|
89
89
|
const geom = new THREE.SphereGeometry(config.size || 0.3, 28, 28);
|
|
90
90
|
const sphere = new THREE.Mesh(geom, mesh);
|
|
91
91
|
sphere.frustumCulled = false;
|
|
92
|
+
sphere.name = this.measureName
|
|
92
93
|
sphere.position.set(pos.x, pos.y, pos.z);
|
|
93
94
|
return sphere;
|
|
94
95
|
},
|
|
@@ -98,10 +99,11 @@ MeasureAngle.prototype = {
|
|
|
98
99
|
linewidth: 10,
|
|
99
100
|
depthTest: false,
|
|
100
101
|
depthWrite: false,
|
|
101
|
-
transparent: true
|
|
102
|
+
transparent: true
|
|
102
103
|
});
|
|
103
104
|
const lineGeometry = new THREE.BufferGeometry().setFromPoints([p1, p2]);
|
|
104
105
|
const line = new THREE.Line(lineGeometry, lineMaterial);
|
|
106
|
+
line.name = this.measureName;
|
|
105
107
|
line.renderOrder = 999;
|
|
106
108
|
line.frustumCulled = false;
|
|
107
109
|
return line;
|
|
@@ -111,6 +113,7 @@ MeasureAngle.prototype = {
|
|
|
111
113
|
div.className = name;
|
|
112
114
|
div.textContent = text;
|
|
113
115
|
const divLabel = new CSS2DObject(div);
|
|
116
|
+
divLabel.name = this.measureName
|
|
114
117
|
divLabel.position.set(position.x, position.y, position.z);
|
|
115
118
|
return divLabel;
|
|
116
119
|
},
|
|
@@ -171,6 +174,7 @@ MeasureAngle.prototype = {
|
|
|
171
174
|
div.className = 'tips-label';
|
|
172
175
|
div.textContent = label;
|
|
173
176
|
const tipsLabel = new CSS2DObject(div);
|
|
177
|
+
tipsLabel.name = this.measureName
|
|
174
178
|
tipsLabel.position.set(position.x + 0.1, position.y, position.z + 0.05);
|
|
175
179
|
return tipsLabel;
|
|
176
180
|
},
|
|
@@ -254,6 +258,22 @@ MeasureAngle.prototype = {
|
|
|
254
258
|
}
|
|
255
259
|
this.renderer.domElement.style.cursor = 'pointer';
|
|
256
260
|
},
|
|
261
|
+
clear() {
|
|
262
|
+
this.remove(this.points);
|
|
263
|
+
this.remove(this.polyline);
|
|
264
|
+
this.remove(this.labels);
|
|
265
|
+
this.remove(this.curves);
|
|
266
|
+
this.pointArray.splice(0);
|
|
267
|
+
this.points.splice(0);
|
|
268
|
+
this.polyline.splice(0);
|
|
269
|
+
this.labels.splice(0);
|
|
270
|
+
this.curves.splice(0);
|
|
271
|
+
this.tempPoints = undefined;
|
|
272
|
+
this.tempLabel = undefined;
|
|
273
|
+
this.tempLine = undefined;
|
|
274
|
+
this.scene.remove(this.tipsLabel);
|
|
275
|
+
this.tipsLabel = undefined;
|
|
276
|
+
},
|
|
257
277
|
remove(array) {
|
|
258
278
|
for (let index = 0; index < array.length; index++) {
|
|
259
279
|
const element = array[index];
|
|
@@ -22,7 +22,7 @@ var MeasureArea = function (renderer, scene, camera, width, height) {
|
|
|
22
22
|
this.width = width;
|
|
23
23
|
this.height = height;
|
|
24
24
|
this.firstTime = 0;
|
|
25
|
-
|
|
25
|
+
this.measureName = 'measureObj'
|
|
26
26
|
// 创建一个辅助平面来捕获鼠标事件
|
|
27
27
|
this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
|
|
28
28
|
};
|
|
@@ -88,10 +88,11 @@ MeasureArea.prototype = {
|
|
|
88
88
|
linewidth: 20,
|
|
89
89
|
depthTest: false,
|
|
90
90
|
depthWrite: false,
|
|
91
|
-
transparent: true
|
|
91
|
+
transparent: true
|
|
92
92
|
});
|
|
93
93
|
const lineGeometry = new THREE.BufferGeometry().setFromPoints([p1, p2]);
|
|
94
94
|
const line = new THREE.Line(lineGeometry, lineMaterial);
|
|
95
|
+
line.name = this.measureName;
|
|
95
96
|
line.renderOrder = 999;
|
|
96
97
|
line.frustumCulled = false;
|
|
97
98
|
return line;
|
|
@@ -101,6 +102,7 @@ MeasureArea.prototype = {
|
|
|
101
102
|
div.className = name;
|
|
102
103
|
div.textContent = text;
|
|
103
104
|
const divLabel = new CSS2DObject(div);
|
|
105
|
+
divLabel.name = this.measureName
|
|
104
106
|
divLabel.position.set(position.x, position.y, position.z);
|
|
105
107
|
return divLabel;
|
|
106
108
|
},
|
|
@@ -163,6 +165,7 @@ MeasureArea.prototype = {
|
|
|
163
165
|
div.className = 'tips-label';
|
|
164
166
|
div.textContent = label;
|
|
165
167
|
const tipsLabel = new CSS2DObject(div);
|
|
168
|
+
tipsLabel.name = this.measureName
|
|
166
169
|
tipsLabel.position.set(position.x + 0.1, position.y, position.z + 0.05);
|
|
167
170
|
return tipsLabel;
|
|
168
171
|
},
|
|
@@ -250,6 +253,21 @@ MeasureArea.prototype = {
|
|
|
250
253
|
|
|
251
254
|
this.renderer.domElement.style.cursor = 'pointer';
|
|
252
255
|
},
|
|
256
|
+
clear() {
|
|
257
|
+
this.remove(this.points);
|
|
258
|
+
this.remove(this.polyline);
|
|
259
|
+
this.remove(this.labels);
|
|
260
|
+
this.remove(this.polygons);
|
|
261
|
+
this.pointArray.splice(0);
|
|
262
|
+
this.points.splice(0);
|
|
263
|
+
this.polyline.splice(0);
|
|
264
|
+
this.labels.splice(0);
|
|
265
|
+
this.tempPoints = undefined;
|
|
266
|
+
this.tempLabel = undefined;
|
|
267
|
+
this.tempLine = undefined;
|
|
268
|
+
this.scene.remove(this.tipsLabel);
|
|
269
|
+
this.tipsLabel = undefined;
|
|
270
|
+
},
|
|
253
271
|
remove(array) {
|
|
254
272
|
for (let index = 0; index < array.length; index++) {
|
|
255
273
|
const element = array[index];
|
|
@@ -304,10 +322,12 @@ MeasureArea.prototype = {
|
|
|
304
322
|
transparent: true,
|
|
305
323
|
opacity: 0.5,
|
|
306
324
|
side: THREE.DoubleSide,
|
|
325
|
+
name: this.measureName
|
|
307
326
|
});
|
|
308
327
|
const mesh = new THREE.Mesh(geom, material);
|
|
309
328
|
mesh.frustumCulled = false;
|
|
310
|
-
mesh.name = 'polygonMesh';
|
|
329
|
+
// mesh.name = 'polygonMesh';
|
|
330
|
+
mesh.name = _this.measureName;
|
|
311
331
|
_this.polygonMesh = mesh;
|
|
312
332
|
_this.scene.add(mesh);
|
|
313
333
|
_this.polygons.push(mesh);
|
|
@@ -20,7 +20,7 @@ var MeasureDistance = function (renderer, scene, camera, width, height) {
|
|
|
20
20
|
this.width = width;
|
|
21
21
|
this.height = height;
|
|
22
22
|
this.firstTime = 0;
|
|
23
|
-
|
|
23
|
+
this.measureName = 'measureObj'
|
|
24
24
|
// 创建一个辅助平面来捕获鼠标事件
|
|
25
25
|
this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
|
|
26
26
|
};
|
|
@@ -91,6 +91,7 @@ MeasureDistance.prototype = {
|
|
|
91
91
|
});
|
|
92
92
|
const lineGeometry = new THREE.BufferGeometry().setFromPoints([p1, p2]);
|
|
93
93
|
const line = new THREE.Line(lineGeometry, lineMaterial);
|
|
94
|
+
line.name = this.measureName;
|
|
94
95
|
line.renderOrder = 999;
|
|
95
96
|
line.frustumCulled = false;
|
|
96
97
|
return line;
|
|
@@ -100,6 +101,7 @@ MeasureDistance.prototype = {
|
|
|
100
101
|
div.className = name;
|
|
101
102
|
div.textContent = text;
|
|
102
103
|
const divLabel = new CSS2DObject(div);
|
|
104
|
+
divLabel.name = this.measureName
|
|
103
105
|
divLabel.position.set(position.x, position.y, position.z);
|
|
104
106
|
return divLabel;
|
|
105
107
|
},
|
|
@@ -147,6 +149,7 @@ MeasureDistance.prototype = {
|
|
|
147
149
|
div.className = 'tips-label';
|
|
148
150
|
div.textContent = label;
|
|
149
151
|
const tipsLabel = new CSS2DObject(div);
|
|
152
|
+
tipsLabel.name = this.measureName
|
|
150
153
|
tipsLabel.position.set(position.x + 0.1, position.y, position.z + 0.05);
|
|
151
154
|
return tipsLabel;
|
|
152
155
|
},
|
|
@@ -154,6 +157,7 @@ MeasureDistance.prototype = {
|
|
|
154
157
|
this.firstTime = new Date().getTime();
|
|
155
158
|
},
|
|
156
159
|
click(e) {
|
|
160
|
+
console.log(_this.points)
|
|
157
161
|
let lastTime = new Date().getTime();
|
|
158
162
|
if (lastTime - this.firstTime < 300) {
|
|
159
163
|
if (_this.isCompleted) {
|
|
@@ -230,6 +234,21 @@ MeasureDistance.prototype = {
|
|
|
230
234
|
}
|
|
231
235
|
this.renderer.domElement.style.cursor = 'pointer';
|
|
232
236
|
},
|
|
237
|
+
clear() {
|
|
238
|
+
this.remove(this.points);
|
|
239
|
+
this.remove(this.polyline);
|
|
240
|
+
this.remove(this.labels);
|
|
241
|
+
this.pointArray.splice(0);
|
|
242
|
+
this.points.splice(0);
|
|
243
|
+
this.polyline.splice(0);
|
|
244
|
+
this.labels.splice(0);
|
|
245
|
+
this.tempPoints = undefined;
|
|
246
|
+
this.tempLabel = undefined;
|
|
247
|
+
this.tempLine = undefined;
|
|
248
|
+
this.scene.remove(this.tipsLabel);
|
|
249
|
+
this.tipsLabel = undefined;
|
|
250
|
+
this.firstTime = 0;
|
|
251
|
+
},
|
|
233
252
|
remove(array) {
|
|
234
253
|
for (let index = 0; index < array.length; index++) {
|
|
235
254
|
const element = array[index];
|
|
@@ -22,6 +22,7 @@ var MeasureHeight = function (renderer, scene, camera, width, height) {
|
|
|
22
22
|
this.height = height;
|
|
23
23
|
this.firstTime = 0;
|
|
24
24
|
this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
|
|
25
|
+
this.measureName = 'measureObj'
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
MeasureHeight.prototype = {
|
|
@@ -82,10 +83,11 @@ MeasureHeight.prototype = {
|
|
|
82
83
|
linewidth: 15,
|
|
83
84
|
depthTest: false,
|
|
84
85
|
depthWrite: false,
|
|
85
|
-
transparent: true
|
|
86
|
+
transparent: true
|
|
86
87
|
});
|
|
87
88
|
const lineGeometry = new THREE.BufferGeometry().setFromPoints([p1, p2]);
|
|
88
89
|
const line = new THREE.Line(lineGeometry, lineMaterial);
|
|
90
|
+
line.name = this.measureName;
|
|
89
91
|
line.renderOrder = 999;
|
|
90
92
|
line.frustumCulled = false;
|
|
91
93
|
return line;
|
|
@@ -95,6 +97,7 @@ MeasureHeight.prototype = {
|
|
|
95
97
|
div.className = name;
|
|
96
98
|
div.textContent = text;
|
|
97
99
|
const divLabel = new CSS2DObject(div);
|
|
100
|
+
divLabel.name = this.measureName
|
|
98
101
|
divLabel.position.set(position.x, position.y, position.z);
|
|
99
102
|
return divLabel;
|
|
100
103
|
},
|
|
@@ -125,6 +128,7 @@ MeasureHeight.prototype = {
|
|
|
125
128
|
div.className = 'tips-label';
|
|
126
129
|
div.textContent = label;
|
|
127
130
|
const tipsLabel = new CSS2DObject(div);
|
|
131
|
+
tipsLabel.name = this.measureName
|
|
128
132
|
tipsLabel.position.set(position.x + 0.1, position.y, position.z + 0.05);
|
|
129
133
|
return tipsLabel;
|
|
130
134
|
},
|
|
@@ -184,6 +188,18 @@ MeasureHeight.prototype = {
|
|
|
184
188
|
this.renderer.domElement.style.cursor = 'pointer';
|
|
185
189
|
this.firstTime = 0;
|
|
186
190
|
}
|
|
191
|
+
|
|
192
|
+
},
|
|
193
|
+
clear() {
|
|
194
|
+
this.remove(this.points);
|
|
195
|
+
this.remove(this.polyline);
|
|
196
|
+
this.remove(this.labels);
|
|
197
|
+
this.pointArray.splice(0);
|
|
198
|
+
this.points.splice(0);
|
|
199
|
+
this.polyline.splice(0);
|
|
200
|
+
this.labels.splice(0);
|
|
201
|
+
this.scene.remove(this.tipsLabel);
|
|
202
|
+
this.tipsLabel = undefined;
|
|
187
203
|
},
|
|
188
204
|
remove(array) {
|
|
189
205
|
for (let index = 0; index < array.length; index++) {
|