10 changed files with 298 additions and 27 deletions
@ -0,0 +1,5 @@ |
|||
import BaseEntity from '@/core/base/BaseItemEntity.ts' |
|||
|
|||
export default class GstoreEntity extends BaseEntity { |
|||
|
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
import BaseInteraction from '@/core/base/BaseInteraction.ts' |
|||
import * as THREE from 'three' |
|||
|
|||
export default class GstoreInteraction extends BaseInteraction { |
|||
|
|||
get isSinglePointMode(): boolean { |
|||
return true |
|||
} |
|||
|
|||
constructor(itemTypeName: string) { |
|||
super(itemTypeName) |
|||
} |
|||
|
|||
createPointOfItem(item: ItemJson, point: THREE.Vector3): ItemJson { |
|||
item = super.createPointOfItem(item, point) |
|||
|
|||
// 创建一个地堆货架
|
|||
item.dt.rackWidth = 1.2 // 宽度
|
|||
item.dt.rackDepth = 1.2 // 深度
|
|||
return item |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
import type { IMeta } from '@/core/base/IMeta.ts' |
|||
|
|||
export default [ |
|||
{ field: 'uuid', editor: 'UUID', label: 'uuid', readonly: true, category: 'basic' }, |
|||
{ field: 'name', editor: 'TextInput', label: '名称', category: 'basic' }, |
|||
{ field: 'dt.label', editor: 'TextInput', label: '标签', category: 'basic' }, |
|||
{ editor: 'TransformEditor', category: 'basic' }, |
|||
{ field: 'dt.color', editor: 'Color', label: '颜色', category: 'basic' }, |
|||
{ editor: '-', category: 'basic' }, |
|||
{ field: 'tf', editor: 'InOutCenterEditor', category: 'basic' }, |
|||
{ field: 'dt.selectable', editor: 'Switch', label: '可选中', category: 'basic' }, |
|||
{ field: 'dt.protected', editor: 'Switch', label: '受保护', category: 'basic' }, |
|||
{ field: 'visible', editor: 'Switch', label: '可见', category: 'basic' } |
|||
] as IMeta |
|||
@ -0,0 +1,167 @@ |
|||
import * as THREE from 'three' |
|||
import BaseRenderer from '@/core/base/BaseRenderer.ts' |
|||
import { Text } from 'troika-three-text' |
|||
import MoveLinePointPng from '@/assets/images/moveline_point.png' |
|||
import SimSunTTF from '@/assets/fonts/simsunb.ttf' |
|||
import { getLineId } from '@/core/ModelUtils.ts' |
|||
|
|||
/** |
|||
* 辅助测量工具渲染器 |
|||
*/ |
|||
export default class GstoreRenderer extends BaseRenderer { |
|||
static LABEL_NAME = 'way_label' |
|||
static POINT_NAME = 'way_point' |
|||
|
|||
pointMaterial: THREE.Material |
|||
lineMaterial = new THREE.MeshBasicMaterial({ |
|||
color: 0xa0cfff, |
|||
transparent: true, |
|||
opacity: 0.2, |
|||
side: THREE.DoubleSide |
|||
}) |
|||
|
|||
/** |
|||
* 默认点的高度, 防止和地面重合 |
|||
*/ |
|||
readonly defulePositionY: number = 0.5 // 默认点的高度, 0.01, 防止和地面重合
|
|||
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(1.5, 1.2, 0.1) |
|||
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0) |
|||
|
|||
constructor(itemTypeName: string) { |
|||
super(itemTypeName) |
|||
} |
|||
|
|||
async init() { |
|||
return Promise.all([ |
|||
super.init(), |
|||
this.loadFont() |
|||
]) |
|||
} |
|||
|
|||
async loadFont() { |
|||
return new Promise<void>((resolve, reject) => { |
|||
new THREE.TextureLoader().load( |
|||
MoveLinePointPng, |
|||
(texture) => { |
|||
this.pointMaterial = new THREE.SpriteMaterial({ |
|||
map: texture, |
|||
transparent: true, |
|||
side: THREE.DoubleSide |
|||
}) |
|||
resolve() |
|||
}, |
|||
undefined, |
|||
function(err) { |
|||
reject(err) |
|||
} |
|||
) |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 所有的点,必须使用同一个尺寸, 改属性也无效 |
|||
*/ |
|||
override afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, objects: THREE.Object3D[]) { |
|||
super.afterCreateOrUpdatePoint(item, option, objects) |
|||
|
|||
const point = objects[0] |
|||
point.position.y = this.defulePositionY |
|||
point.scale.set(this.defaultScale.x, this.defaultScale.y, this.defaultScale.z) |
|||
point.rotation.set( |
|||
THREE.MathUtils.degToRad(this.defaultRotation.x), |
|||
THREE.MathUtils.degToRad(this.defaultRotation.y), |
|||
THREE.MathUtils.degToRad(this.defaultRotation.z) |
|||
) |
|||
} |
|||
|
|||
|
|||
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D[] { |
|||
const group = new THREE.Group() |
|||
const startPosition = new THREE.Vector3(start.tf[0][0], 0.01, start.tf[0][2]) |
|||
const endPosition = new THREE.Vector3(end.tf[0][0], 0.01, end.tf[0][2]) |
|||
const width = 1 |
|||
|
|||
const curve = new THREE.LineCurve3(startPosition, endPosition) |
|||
const tubeGeometry = new THREE.TubeGeometry(curve, 1, width / 2, 8, false) |
|||
const lineMesh = new THREE.Mesh(tubeGeometry, this.lineMaterial) |
|||
group.add(lineMesh) |
|||
|
|||
|
|||
const midPoint = new THREE.Vector3() |
|||
.addVectors(startPosition, endPosition) |
|||
.multiplyScalar(0.5) |
|||
|
|||
const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) |
|||
|
|||
const label = new Text() |
|||
label.text = distance |
|||
label.font = SimSunTTF |
|||
label.fontSize = 0.2 |
|||
label.color = '#5f5f5f' |
|||
label.opacity = 0.8 |
|||
label.anchorX = 'center' |
|||
label.anchorY = 'middle' |
|||
label.depthOffset = 1 |
|||
label.material.depthTest = false |
|||
label.name = GstoreRenderer.LABEL_NAME |
|||
label.quaternion.copy(this.tempViewport.camera.quaternion) |
|||
label.sync() |
|||
label.position.set(midPoint.x, midPoint.y, midPoint.z) |
|||
|
|||
group.add(label) |
|||
|
|||
return [group] |
|||
} |
|||
|
|||
updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { |
|||
super.updateLine(start, end, type, option) |
|||
|
|||
const startPosition = new THREE.Vector3(start.tf[0][0], 0.01, start.tf[0][2]) |
|||
const endPosition = new THREE.Vector3(end.tf[0][0], 0.01, end.tf[0][2]) |
|||
const width = 1 |
|||
|
|||
const lineId = getLineId(start.id, end.id, type) |
|||
const lines = this.tempViewport.entityManager.findLineObjectsById(lineId) |
|||
const group: THREE.Group = lines[0] as THREE.Group |
|||
|
|||
// 清空group里的元素
|
|||
const label: Text = group.children[1] |
|||
group.clear() |
|||
|
|||
const curve = new THREE.LineCurve3(startPosition, endPosition) |
|||
const tubeGeometry = new THREE.TubeGeometry(curve, 1, width / 2, 8, false) |
|||
const lineMesh = new THREE.Mesh(tubeGeometry, this.lineMaterial) |
|||
group.add(lineMesh) |
|||
|
|||
const midPoint = new THREE.Vector3() |
|||
.addVectors(startPosition, endPosition) |
|||
.multiplyScalar(0.5) |
|||
|
|||
const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) |
|||
label.text = distance |
|||
label.quaternion.copy(this.tempViewport.camera.quaternion) |
|||
label.sync() |
|||
label.position.set(midPoint.x, midPoint.y, midPoint.z) |
|||
group.add(label) |
|||
} |
|||
|
|||
createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D[] { |
|||
const obj = new THREE.Sprite(this.pointMaterial as THREE.SpriteMaterial) |
|||
obj.name = GstoreRenderer.POINT_NAME |
|||
return [obj] |
|||
} |
|||
|
|||
appendToScene(...objects: THREE.Object3D[]) { |
|||
const dragObjects = objects.filter(obj => !!obj.userData.draggable) |
|||
this.tempViewport.dragControl.setDragObjects(dragObjects, 'push') |
|||
// this.tempViewport.dragControl.setDragObjects(objects, 'remove')
|
|||
|
|||
this.tempViewport?.scene.add(...objects) |
|||
} |
|||
|
|||
dispose() { |
|||
super.dispose() |
|||
this.pointMaterial.dispose() |
|||
this.lineMaterial.dispose() |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import GstoreRenderer from './GstoreRenderer.ts' |
|||
import GstoreEntity from './GstoreEntity.ts' |
|||
import GstoreMeta from './GstoreMeta.ts' |
|||
import GstoreInteraction from './GstoreInteraction.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'gstore' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
renderer: new GstoreRenderer(ITEM_TYPE_NAME), |
|||
interaction: new GstoreInteraction(ITEM_TYPE_NAME), |
|||
meta: GstoreMeta, |
|||
entity: GstoreEntity |
|||
}) |
|||
Loading…
Reference in new issue