Merge branch 'main' of github.com:specklesystems/speckle-server into alessandro/web-1172-change-the-users-repository-to-abstract-the-email-field-in
This commit is contained in:
@@ -105,7 +105,7 @@ const getStream = () => {
|
||||
// prettier-ignore
|
||||
// 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8?c=%5B-7.66134,10.82932,6.41935,-0.07739,-13.88552,1.8697,0,1%5D'
|
||||
// Revit sample house (good for bim-like stuff with many display meshes)
|
||||
'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8'
|
||||
// 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8'
|
||||
// 'https://latest.speckle.dev/streams/c1faab5c62/commits/ab1a1ab2b6'
|
||||
// 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8'
|
||||
// 'https://latest.speckle.dev/streams/58b5648c4d/commits/60371ecb2d'
|
||||
@@ -393,6 +393,10 @@ const getStream = () => {
|
||||
// 'https://app.speckle.systems/projects/47bbaf594f/models/de52414725f8937b1f0e2f550ef9ca52'
|
||||
// qGIS sRGB vertex colors
|
||||
// 'https://latest.speckle.systems/projects/5a6609a4b9/models/10f4931e8c'
|
||||
// DUI3 blocks
|
||||
// 'https://latest.speckle.systems/projects/126cd4b7bb/models/c6f3f309a2'
|
||||
'https://latest.speckle.systems/projects/126cd4b7bb/models/6b62c61a22'
|
||||
// 'https://latest.speckle.systems/projects/126cd4b7bb/models/4dc5265453'
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ export type SpeckleObject = {
|
||||
name?: string
|
||||
referencedId?: string
|
||||
units?: string
|
||||
applicationId?: string
|
||||
}
|
||||
|
||||
export interface ViewerParams {
|
||||
|
||||
@@ -19,6 +19,7 @@ export enum SpeckleType {
|
||||
RevitInstance = 'RevitInstance',
|
||||
Text = 'Text',
|
||||
Transform = 'Transform',
|
||||
InstanceProxy = 'InstanceProxy',
|
||||
Unknown = 'Unknown'
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { MathUtils } from 'three'
|
||||
import { MathUtils, Matrix4 } from 'three'
|
||||
import { type TreeNode, WorldTree } from '../../tree/WorldTree.js'
|
||||
import { NodeMap } from '../../tree/NodeMap.js'
|
||||
import type { SpeckleObject } from '../../../index.js'
|
||||
import { type SpeckleObject } from '../../../index.js'
|
||||
import type ObjectLoader from '@speckle/objectloader'
|
||||
import Logger from '../../utils/Logger.js'
|
||||
|
||||
@@ -22,6 +22,9 @@ export default class SpeckleConverter {
|
||||
private spoofIDs = false
|
||||
private tree: WorldTree
|
||||
private typeLookupTable: { [type: string]: string } = {}
|
||||
private instanceDefinitionLookupTable: { [id: string]: TreeNode } = {}
|
||||
private instancedObjectsLookupTable: { [id: string]: SpeckleObject } = {}
|
||||
private instanceProxies: { [id: string]: TreeNode } = {}
|
||||
private instanceCounter = 0
|
||||
|
||||
private readonly NodeConverterMapping: {
|
||||
@@ -44,6 +47,8 @@ export default class SpeckleConverter {
|
||||
RevitInstance: this.RevitInstanceToNode.bind(this),
|
||||
Text: this.TextToNode.bind(this),
|
||||
Dimension: this.DimensionToNode.bind(this),
|
||||
InstanceDefinitionProxy: this.InstanceDefinitionProxyToNode.bind(this),
|
||||
InstanceProxy: this.InstanceProxyToNode.bind(this),
|
||||
Parameter: null
|
||||
}
|
||||
|
||||
@@ -521,6 +526,130 @@ export default class SpeckleConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private async InstanceDefinitionProxyToNode(obj: SpeckleObject, node: TreeNode) {
|
||||
if (!obj.applicationId) {
|
||||
Logger.warn(`Instance Definition Proxy ${obj.id} has no applicationId`)
|
||||
return
|
||||
}
|
||||
this.instanceDefinitionLookupTable[obj.applicationId] = node
|
||||
}
|
||||
|
||||
private async InstanceProxyToNode(obj: SpeckleObject, node: TreeNode) {
|
||||
if (!obj.applicationId) {
|
||||
Logger.warn(`Instance proxy ${obj.id} has no application id`)
|
||||
return
|
||||
}
|
||||
this.instanceProxies[obj.applicationId] = node
|
||||
return
|
||||
}
|
||||
|
||||
private getInstanceProxyDefinitionId(obj: SpeckleObject): string {
|
||||
return (obj.DefinitionId || obj.definitionId) as string
|
||||
}
|
||||
|
||||
private getInstanceProxyTransform(obj: SpeckleObject): Array<number> {
|
||||
if (!(obj.transform || obj.Transform)) {
|
||||
return new Matrix4().toArray()
|
||||
}
|
||||
return (obj.transform || obj.Transform) as Array<number>
|
||||
}
|
||||
|
||||
private getInstanceProxyDefinitionObjects(obj: SpeckleObject): Array<string> {
|
||||
return (obj.Objects || obj.objects) as Array<string>
|
||||
}
|
||||
|
||||
private createTransformNode(obj: SpeckleObject) {
|
||||
const transformNodeId = MathUtils.generateUUID()
|
||||
const transformData = this.getEmptyTransformData(transformNodeId)
|
||||
transformData.units = obj.units as string
|
||||
transformData.matrix = this.getInstanceProxyTransform(obj)
|
||||
return this.tree.parse({
|
||||
id: transformNodeId,
|
||||
raw: transformData,
|
||||
atomic: false,
|
||||
children: []
|
||||
})
|
||||
}
|
||||
|
||||
private async ConvertInstanceProxyToNode(obj: SpeckleObject, node: TreeNode) {
|
||||
const definitionId = this.getInstanceProxyDefinitionId(obj)
|
||||
if (!definitionId) {
|
||||
Logger.warn(`Instance Proxy ${obj.id} has no definitionId`)
|
||||
return
|
||||
}
|
||||
const definition = this.instanceDefinitionLookupTable[definitionId]
|
||||
const transformNode = this.createTransformNode(obj)
|
||||
|
||||
this.tree.addNode(transformNode, node)
|
||||
const objectApplicationIds = this.getInstanceProxyDefinitionObjects(
|
||||
definition.model.raw
|
||||
)
|
||||
for (const objectApplicationId of objectApplicationIds) {
|
||||
const speckleData = this.instancedObjectsLookupTable[objectApplicationId]
|
||||
const instancedNode = this.tree.parse({
|
||||
id: this.getCompoundId(speckleData.id, this.instanceCounter++),
|
||||
raw: speckleData,
|
||||
atomic: false,
|
||||
children: [],
|
||||
instanced: true
|
||||
})
|
||||
this.tree.addNode(instancedNode, transformNode)
|
||||
await this.convertToNode(speckleData, instancedNode)
|
||||
}
|
||||
}
|
||||
|
||||
public async convertInstances() {
|
||||
/** uh, oh */
|
||||
this.NodeConverterMapping.InstanceProxy = this.ConvertInstanceProxyToNode.bind(this)
|
||||
|
||||
/** Find the nodes that need to be 'consumed' */
|
||||
const consumeApplicationIds: { [id: string]: TreeNode | null } = {}
|
||||
let consumeApplicationIdsCount = 0
|
||||
for (const k in this.instanceDefinitionLookupTable) {
|
||||
const definition = this.instanceDefinitionLookupTable[k]
|
||||
const objects = this.getInstanceProxyDefinitionObjects(definition.model.raw)
|
||||
for (let i = 0; i < objects.length; i++) {
|
||||
consumeApplicationIds[objects[i].toString()] = null
|
||||
consumeApplicationIdsCount++
|
||||
}
|
||||
}
|
||||
/** Do a short async walk */
|
||||
await this.tree.walkAsync((node: TreeNode) => {
|
||||
if (!node.model.raw.applicationId) return true
|
||||
const applicationId = node.model.raw.applicationId.toString()
|
||||
if (consumeApplicationIds[applicationId] !== undefined) {
|
||||
consumeApplicationIds[applicationId] = node
|
||||
consumeApplicationIdsCount--
|
||||
}
|
||||
/** Break out when all applicationIds are accounted for*/
|
||||
if (consumeApplicationIdsCount === 0) return false
|
||||
return true
|
||||
})
|
||||
|
||||
/** Consume them */
|
||||
for (const k in consumeApplicationIds) {
|
||||
const objectNode = consumeApplicationIds[k]
|
||||
if (!objectNode) {
|
||||
Logger.error(`Consumable applicationId ${k} could not be found`)
|
||||
continue
|
||||
}
|
||||
|
||||
/** Store the speckle object data */
|
||||
this.instancedObjectsLookupTable[k] = objectNode.model.raw
|
||||
/** Remove the instance from the list (if needed) */
|
||||
delete this.instanceProxies[k]
|
||||
/** Remove the node from the world tree */
|
||||
this.tree.removeNode(objectNode, true)
|
||||
}
|
||||
|
||||
/** Remaining instance proxies should all be valid */
|
||||
for (const k in this.instanceProxies) {
|
||||
const node = this.instanceProxies[k]
|
||||
/** Create the final instances */
|
||||
await this.convertToNode(node.model.raw, node)
|
||||
}
|
||||
}
|
||||
|
||||
private async PointcloudToNode(obj: SpeckleObject, node: TreeNode) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
|
||||
@@ -70,6 +70,8 @@ export class SpeckleGeometryConverter extends GeometryConverter {
|
||||
return this.TextToGeometryData(node)
|
||||
case SpeckleType.Transform:
|
||||
return this.TransformToGeometryData(node)
|
||||
case SpeckleType.InstanceProxy:
|
||||
return this.InstanceProxyToGeometyData(node)
|
||||
case SpeckleType.Unknown:
|
||||
// console.warn(`Skipping geometry conversion for ${type}`)
|
||||
return null
|
||||
@@ -176,6 +178,11 @@ export class SpeckleGeometryConverter extends GeometryConverter {
|
||||
return null
|
||||
}
|
||||
|
||||
private InstanceProxyToGeometyData(node: NodeData): GeometryData | null {
|
||||
node
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* POINT CLOUD
|
||||
*/
|
||||
|
||||
@@ -128,6 +128,8 @@ export class SpeckleLoader extends Loader {
|
||||
return Promise.resolve(false)
|
||||
}
|
||||
|
||||
await this.converter.convertInstances()
|
||||
|
||||
const t0 = performance.now()
|
||||
const geometryConverter = new SpeckleGeometryConverter()
|
||||
|
||||
|
||||
@@ -108,8 +108,14 @@ export class WorldTree {
|
||||
if (this.nodeMaps[parent.model.subtreeId]?.addNode(node)) parent.addChild(node)
|
||||
}
|
||||
|
||||
public removeNode(node: TreeNode): void {
|
||||
public removeNode(node: TreeNode, removeChildren: boolean): void {
|
||||
const children = node.children
|
||||
this.nodeMaps[node.model.subtreeId]?.removeNode(node)
|
||||
node.drop()
|
||||
if (!removeChildren || !children) return
|
||||
for (let k = 0; k < children.length; k++) {
|
||||
this.removeNode(children[k], removeChildren)
|
||||
}
|
||||
}
|
||||
|
||||
public findAll(predicate: SearchPredicate, node?: TreeNode): Array<TreeNode> {
|
||||
@@ -197,7 +203,8 @@ export class WorldTree {
|
||||
if (subtreeNode) {
|
||||
this.nodeMaps[subtreeNode[0].model.subtreeId].purge()
|
||||
delete this.nodeMaps[subtreeNode[0].model.subtreeId]
|
||||
this.removeNode(subtreeNode[0])
|
||||
// Potentially true?
|
||||
this.removeNode(subtreeNode[0], false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user