Browse Source

红选模式

master
修宁 7 months ago
parent
commit
cc24f8451d
  1. 159
      src/core/controls/SelectInspect.ts
  2. 28
      src/core/engine/Viewport.ts
  3. 21
      src/core/manager/EntityManager.ts
  4. 14
      src/editor/widgets/property/PropertyView.vue
  5. 2
      src/modules/way/WayRenderer.ts
  6. 3
      src/runtime/EventBus.ts

159
src/core/controls/SelectInspect.ts

@ -19,7 +19,12 @@ export default class SelectInspect implements IControls {
/**
* 线
*/
material: LineMaterial = new LineMaterial({ color: 0xffff00, linewidth: 2 })
yellowMaterial: LineMaterial = new LineMaterial({ color: 0xffff00, linewidth: 2 })
/**
* 线
*/
redMaterial: LineMaterial = new LineMaterial({ color: 0xff0000, linewidth: 2 })
/**
*
@ -76,6 +81,11 @@ export default class SelectInspect implements IControls {
this.updateSelectionBox(this.viewport.state.selectedObject)
})
EventBus.on('multiSelectedObjectsChanged', (data) => {
// 如果多选对象发生变化,清除当前选中对象的包围盒线框
this.updateMultiSelectionBoxes(data.multiSelectedObjects)
})
EventBus.on('selectedObjectPropertyChanged', (data) => {
this.updateSelectionBox(this.viewport.state.selectedObject)
})
@ -90,6 +100,69 @@ export default class SelectInspect implements IControls {
})
}
redSelectionGroup = new THREE.Group()
private updateMultiSelectionBoxes(multiSelectedObjects: THREE.Object3D[]) {
// 为所有多选对象创建包围盒线框
this.clearRedSelectionBoxes()
if (!multiSelectedObjects || multiSelectedObjects.length === 0) {
return
}
for (const object of multiSelectedObjects) {
if (object.userData.entityId) {
this.createRedSelectionBox(object)
}
}
}
clearRedSelectionBoxes() {
// 清除之前的红色包围盒线框
if (this.redSelectionGroup.children.length > 0) {
for (const child of this.redSelectionGroup.children) {
this.redSelectionGroup.remove(child)
}
}
this.viewport.scene.remove(this.redSelectionGroup)
this.redSelectionGroup = new THREE.Group()
this.viewport.scene.add(this.redSelectionGroup)
}
createRedSelectionBox(object: THREE.Object3D) {
// 如果对象没有 entityId,则不创建包围盒线框
if (!object.userData.entityId) {
return
}
// 如果选中的对象小于 0.5,要扩展包围盒
const RED_EXPAND_AMOUNT = 0.01 // 扩展包围盒的大小
// 避免某些蒙皮网格的帧延迟效应(e.g. Michelle.glb)
object.updateWorldMatrix(false, true)
const box = new THREE.Box3().setFromObject(object)
box.expandByScalar(RED_EXPAND_AMOUNT)
const size = new THREE.Vector3()
box.getSize(size)
const center = new THREE.Vector3()
box.getCenter(center)
// 创建包围盒几何体
const helperGeometry = new THREE.BoxGeometry(size.x, size.y, size.z)
const edgesGeometry = new THREE.EdgesGeometry(helperGeometry)
const lineGeom = new LineGeometry()
// @ts-ignore
lineGeom.setPositions(edgesGeometry.attributes.position.array)
const selectionBox = new Line2(lineGeom, this.redMaterial)
selectionBox.computeLineDistances()
selectionBox.position.copy(center)
this.redSelectionGroup.add(selectionBox)
}
/**
* 线
*/
@ -101,12 +174,13 @@ export default class SelectInspect implements IControls {
}
this.selectionId = selectedObject.userData?.entityId
const expandAmount = 0.2 // 扩展包围盒的大小
// 如果选中的对象小于 0.5,要扩展包围盒
const YELLOW_EXPAND_AMOUNT = 0.03 // 扩展包围盒的大小
// 避免某些蒙皮网格的帧延迟效应(e.g. Michelle.glb)
selectedObject.updateWorldMatrix(false, true)
const box = new THREE.Box3().setFromObject(selectedObject)
box.expandByScalar(expandAmount)
box.expandByScalar(YELLOW_EXPAND_AMOUNT)
const size = new THREE.Vector3()
box.getSize(size)
@ -117,16 +191,13 @@ export default class SelectInspect implements IControls {
// 创建包围盒几何体
const helperGeometry = new THREE.BoxGeometry(size.x, size.y, size.z)
const edgesGeometry = new THREE.EdgesGeometry(helperGeometry)
// 使用 LineGeometry 包装 edgesGeometry
const lineGeom = new LineGeometry()
//@ts-ignore
// @ts-ignore
lineGeom.setPositions(edgesGeometry.attributes.position.array)
const selectionBox = new Line2(lineGeom, this.material)
const selectionBox = new Line2(lineGeom, this.yellowMaterial)
selectionBox.computeLineDistances()
selectionBox.position.copy(center)
selectionBox.name = 'selectionBox'
this.selectionBox = selectionBox
console.log('selectedItem', this.viewport.state.selectedItem)
@ -162,7 +233,7 @@ export default class SelectInspect implements IControls {
if (this.recStartPos) {
// 创建矩形
this.rectangle = new THREE.Mesh(
new THREE.PlaneGeometry(1, 1),
new THREE.PlaneGeometry(0.001, 0.001),
this.rectMaterial
)
this.rectangle.name = 'selectRectangle'
@ -176,6 +247,7 @@ export default class SelectInspect implements IControls {
}
}
updateRectangle(position: THREE.Vector3) {
if (!this.rectangle || !this.recStartPos) return
// console.log('updateRectangle', this.recStartPos, position)
@ -201,6 +273,8 @@ export default class SelectInspect implements IControls {
// 记录鼠标按下位置
this.recStartPos = this.viewport.getClosestIntersection(event)
this.createRectangle()
this.viewport.controls.enabled = false // 禁用控制器
} else {
// 为 click 事件添加处理逻辑
this.clickTime = Date.now()
@ -220,11 +294,14 @@ export default class SelectInspect implements IControls {
disposeRect() {
if (this.rectangle !== null) {
// 查找在这个矩形内的所有有效业务对象,并将他们添加进 viewport.state.multiSelectedObjects
this.multipleSelectedObjects()
this.viewport.scene.remove(this.rectangle)
this.rectangle.geometry.dispose()
this.rectangle = null
}
this.recStartPos = null
this.viewport.controls.enabled = true // 启用控制器
}
onMouseUp(event: MouseEvent) {
@ -253,7 +330,71 @@ export default class SelectInspect implements IControls {
selectedObjectMeta: this.viewport.state.selectedObjectMeta
})
}
} else {
// 如果没有选中任何对象,清除选中状态
this.viewport.state.selectedObject = null
this.viewport.state.selectedItem = null
this.viewport.state.selectedEntityId = null
this.viewport.state.selectedObjectMeta = null
EventBus.dispatch('selectedObjectChanged', {
viewport: markRaw(this.viewport),
selectedObject: null,
selectedItem: null,
selectedEntityId: null,
selectedObjectMeta: null
})
}
}
}
private multipleSelectedObjects() {
if (!this.rectangle || !this.recStartPos) return
// 获取矩形的包围盒
const box = new THREE.Box3().setFromObject(this.rectangle)
// 获取盒子的 startX, startZ, endX, endZ
const startX = box.min.x
const startZ = box.min.z
const endX = box.max.x
const endZ = box.max.z
// 查找所有在矩形内的对象
const objects = this.viewport.entityManager.getObjectsInBox(startX, startZ, endX, endZ)
// 清空之前的多选对象
this.viewport.state.multiSelectedObjects = []
// 遍历找到的对象,添加到多选对象中
const multiSelectedObjects = []
const multiSelectedItems = []
const multiSelectedEntityIds = []
const multiSelectedObjectMetas = []
for (const object of objects) {
if (object.userData.entityId && object.userData.t) {
const item = this.viewport.entityManager.findItemById(object.userData.entityId)
if (item && item.dt.protected !== true) {
multiSelectedObjects.push(object)
multiSelectedItems.push(item)
multiSelectedEntityIds.push(object.userData.entityId)
multiSelectedObjectMetas.push(getMeta(object.userData.t))
}
}
}
// 触发多选对象更新事件
this.viewport.state.multiSelectedObjects = markRaw(objects)
this.viewport.state.multiSelectedItems = markRaw(multiSelectedItems)
this.viewport.state.multiSelectedEntityIds = multiSelectedEntityIds
this.viewport.state.multiSelectedObjectMetas = multiSelectedObjectMetas
EventBus.dispatch('multiSelectedObjectsChanged', {
viewport: markRaw(this.viewport),
multiSelectedObjects: this.viewport.state.multiSelectedObjects,
multiSelectedItems: this.viewport.state.multiSelectedItems,
multiSelectedEntityIds: this.viewport.state.multiSelectedEntityIds,
multiSelectedObjectMetas: this.viewport.state.multiSelectedObjectMetas
})
}
}

28
src/core/engine/Viewport.ts

@ -66,7 +66,17 @@ export default class Viewport {
isReady: false,
isUpdating: false,
cursorMode: 'normal',
selectedObject: null,
selectedObject: undefined,
selectedItem: undefined,
selectedEntityId: undefined,
selectedObjectMeta: undefined,
multiSelectedObjects: [],
multiSelectedItems: [],
multiSelectedEntityIds: [],
multiSelectedObjectMetas: [],
view3DMode: Constract.Mode2D,
camera: {
position: { x: 0, y: 0, z: 0 },
@ -550,20 +560,22 @@ export interface ViewportState {
cursorMode: string // CursorMode,
/**
*
*
*/
selectedObject: THREE.Object3D | undefined
selectedItem: ItemJson | undefined
selectedEntityId: string | undefined
view3DMode: string // Constract.Mode2D | Constract.Mode3D
selectedObjectMeta: IMeta | undefined
/**
*
*
*/
selectedObjectMeta: IMeta | undefined
multiSelectedObjects: THREE.Object3D[]
multiSelectedItems: ItemJson[]
multiSelectedEntityIds: string[]
multiSelectedObjectMetas: IMeta[]
view3DMode: string // Constract.Mode2D | Constract.Mode3D
/**
*

21
src/core/manager/EntityManager.ts

@ -548,6 +548,27 @@ export default class EntityManager {
r => getClosestObject(r.object)
).filter(obj => obj?.userData && obj.userData.selectable !== false)
}
/**
*
*/
getObjectsInBox(startX: number, startZ: number, endX: number, endZ: number) {
const box = new THREE.Box2(
new THREE.Vector2(startX, startZ),
new THREE.Vector2(endX, endZ)
)
const objectsInBox: THREE.Object3D[] = []
for (const [id, objects] of this.objects.entries()) {
for (const obj of objects) {
if (box.containsPoint(new Vector2(obj.position.x, obj.position.z))) {
objectsInBox.push(obj)
}
}
}
return objectsInBox
}
}
interface LineDiffItem {

14
src/editor/widgets/property/PropertyView.vue

@ -93,12 +93,14 @@ export default {
selectedObjectChanged(state) {
const data = state.selectedItem;
console.log("selectedObjectChanged data", data)
this.viewport.stateManager.beginStateUpdate()
const item = _.find(this.viewport.stateManager.vdata.items, item=>item.id === data.id)
// item.tf[0][0] = item.tf[0][0] / 2;
console.log("selectedObjectChanged item", item)
// _.extend(item, data)
this.viewport.stateManager.endStateUpdate()
if(data) {
this.viewport.stateManager.beginStateUpdate()
const item = _.find(this.viewport.stateManager.vdata.items, item => item.id === data.id)
// item.tf[0][0] = item.tf[0][0] / 2;
console.log("selectedObjectChanged item", item)
// _.extend(item, data)
this.viewport.stateManager.endStateUpdate()
}
},
},
mounted() {

2
src/modules/way/WayRenderer.ts

@ -87,7 +87,7 @@ export default class WayRenderer extends BaseRenderer {
const width = 1
const curve = new THREE.LineCurve3(startPosition, endPosition)
const tubeGeometry = new THREE.TubeGeometry(curve, 1, width / 2, 8, false)
const tubeGeometry = new THREE.TubeGeometry(curve, 1, width / 2, 2, false)
const lineMesh = new THREE.Mesh(tubeGeometry, this.lineMaterial)
group.add(lineMesh)

3
src/runtime/EventBus.ts

@ -6,7 +6,8 @@ export type DispatchNames = 'selectedObjectChanged' |
'catalogChanged' |
'dataLoadComplete' |
'entityDeleted' |
'selectedObjectPropertyChanged'
'selectedObjectPropertyChanged' |
'multiSelectedObjectsChanged'
export default {
dispatch(name: DispatchNames, data?: any) {

Loading…
Cancel
Save