142 lines
3.8 KiB
TypeScript
142 lines
3.8 KiB
TypeScript
import {
|
||
type IPointerEvent,
|
||
PickingInfo,
|
||
PointerEventTypes,
|
||
Vector3,
|
||
AbstractMesh,
|
||
Color3,
|
||
PBRMaterial,
|
||
StandardMaterial,
|
||
HighlightLayer,
|
||
PointerInfo,
|
||
} from '@babylonjs/core'
|
||
import { MainApp } from './MainApp'
|
||
import { Monobehiver } from '../base/Monobehiver';
|
||
import { EventBridge } from '../event/bridge';
|
||
|
||
class AppRay extends Monobehiver {
|
||
oldPoint: Vector3 = Vector3.Zero()
|
||
newPoint: Vector3 = Vector3.Zero()
|
||
private highlightLayer: HighlightLayer | null = null
|
||
private originalMaterial: any = null
|
||
private highlightedMesh: AbstractMesh | null = null
|
||
|
||
constructor(mainApp: MainApp) {
|
||
super(mainApp)
|
||
}
|
||
|
||
Awake() {
|
||
this.setupHighlightLayer()
|
||
this.setupUnifiedEventHandling()
|
||
}
|
||
|
||
// 设置高亮层
|
||
setupHighlightLayer() {
|
||
// 高亮层创建已禁用
|
||
return
|
||
}
|
||
|
||
// 设置统一的事件处理
|
||
setupUnifiedEventHandling() {
|
||
// 使用观察者模式而不是直接覆盖事件处理器
|
||
this.mainApp.appScene.object.onPointerObservable.add((pointerInfo: PointerInfo) => {
|
||
const { type, event, pickInfo } = pointerInfo;
|
||
|
||
// 检查事件类型并转换
|
||
const pointerEvent = event as IPointerEvent;
|
||
|
||
// 只处理鼠标和触摸事件
|
||
if (pointerEvent.pointerType !== "mouse" && pointerEvent.pointerType !== "touch") {
|
||
return;
|
||
}
|
||
|
||
// 处理非主要触摸点
|
||
if (pointerEvent.pointerType === "touch" && (pointerEvent as any).isPrimary === false) {
|
||
return;
|
||
}
|
||
|
||
if (type === PointerEventTypes.POINTERDOWN) {
|
||
this.oldPoint.set(pointerEvent.clientX, 0, pointerEvent.clientY);
|
||
} else if (type === PointerEventTypes.POINTERUP) {
|
||
this.newPoint.set(pointerEvent.clientX, 0, pointerEvent.clientY);
|
||
const distance = Vector3.Distance(this.oldPoint, this.newPoint);
|
||
|
||
// 只有在没有移动的情况下才处理单击
|
||
if (distance < 5) { // 增加一些容差
|
||
this.handleSingleClick(pointerEvent, pickInfo);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 处理单击
|
||
handleSingleClick(evt: IPointerEvent, pickInfo: PickingInfo | null) {
|
||
// 先尝试热点(mesh 热点 / sprite 热点)
|
||
// if (pickInfo && pickInfo.pickedMesh) {
|
||
// const isHotspotClick = this.mainApp.appHotspot?.handlePick(pickInfo.pickedMesh);
|
||
// if (isHotspotClick) return;
|
||
// }
|
||
|
||
// const isSpriteHotspotClick = this.mainApp.appHotspot?.handleSpritePick();
|
||
// if (isSpriteHotspotClick) return;
|
||
|
||
if (pickInfo && pickInfo.pickedMesh) {
|
||
EventBridge.modelClick({
|
||
meshName: pickInfo.pickedMesh.name,
|
||
});
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// 高亮显示网格 - 已禁用
|
||
highlightMesh(mesh: AbstractMesh) {
|
||
// 高亮功能已禁用
|
||
return
|
||
}
|
||
|
||
// 使用材质方式高亮 - 已禁用
|
||
highlightWithMaterial(mesh: AbstractMesh) {
|
||
// 材质高亮功能已禁用
|
||
return
|
||
}
|
||
|
||
// 清除高亮
|
||
clearHighlight() {
|
||
try {
|
||
// 清除高亮层
|
||
if (this.highlightLayer && this.highlightedMesh) {
|
||
try {
|
||
this.highlightLayer.removeMesh(this.highlightedMesh as any)
|
||
} catch (error) {
|
||
console.warn('高亮层移除失败:', error)
|
||
}
|
||
}
|
||
|
||
// 恢复原始材质
|
||
if (this.highlightedMesh && this.originalMaterial) {
|
||
const material = this.highlightedMesh.material as PBRMaterial
|
||
if (material && this.originalMaterial.albedoColor) {
|
||
material.albedoColor = this.originalMaterial.albedoColor
|
||
material.emissiveColor = this.originalMaterial.emissiveColor
|
||
}
|
||
}
|
||
|
||
this.highlightedMesh = null
|
||
this.originalMaterial = null
|
||
} catch (error) {
|
||
console.error('清除高亮失败:', error)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 渲染热点
|
||
* @param hotspots 热点数据
|
||
*/
|
||
renderHotspots(hotspots: any[]): void {
|
||
this.mainApp.appHotspot?.render(hotspots);
|
||
}
|
||
}
|
||
|
||
export { AppRay }
|