1
This commit is contained in:
@ -25,7 +25,7 @@ export class AppCamera extends Monobehiver {
|
||||
this.object = new ArcRotateCamera('Camera', Tools.ToRadians(70), Tools.ToRadians(85), 5, new Vector3(0, 2, 0), scene);
|
||||
this.object.attachControl(canvas, true);
|
||||
this.object.minZ = 0.01; // 近裁剪面
|
||||
this.object.wheelPrecision =999999; // 滚轮缩放精度
|
||||
// this.object.wheelPrecision =999999; // 滚轮缩放精度
|
||||
this.object.panningSensibility = 0;
|
||||
|
||||
// 限制垂直角范围,实现上帝视角
|
||||
|
||||
173
src/babylonjs/AppHotspot.ts
Normal file
173
src/babylonjs/AppHotspot.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import { Vector3 } from '@babylonjs/core'
|
||||
import { Monobehiver } from '../base/Monobehiver'
|
||||
import { HotSpot, HotspotPrams, Point } from '../hotspot'
|
||||
// import { userSellingPointStore } from '@/stores/zguiy'
|
||||
import type { MainApp } from './MainApp'
|
||||
import { Dictionary } from '../utils/Dictionary'
|
||||
import { EventBridge } from '../event/bridge'
|
||||
|
||||
|
||||
export class AppHotspot extends Monobehiver {
|
||||
hotSpot!: HotSpot
|
||||
sllingPointStore: any
|
||||
//偏移量
|
||||
offset: number = 0.7
|
||||
yundong: boolean = false
|
||||
|
||||
|
||||
hotspotDic: Dictionary<HotSpot> = new Dictionary()
|
||||
|
||||
constructor(mainApp: MainApp) {
|
||||
super(mainApp)
|
||||
// this.sllingPointStore = userSellingPointStore()
|
||||
}
|
||||
|
||||
Awake() {
|
||||
|
||||
|
||||
const hotspot = new HotSpot(this.mainApp)
|
||||
hotspot.Awake()
|
||||
this.hotSpot = hotspot;
|
||||
|
||||
// 注意:需要从外部传入热点列表,或者从配置中读取
|
||||
// this.initHotSpot(hotSpotList)
|
||||
|
||||
|
||||
}
|
||||
|
||||
render(hotSpotList: Array<any>) {
|
||||
// 确保 hotSpot 已初始化
|
||||
if (!this.hotSpot) {
|
||||
this.Awake();
|
||||
}
|
||||
this.initHotSpot(hotSpotList);
|
||||
}
|
||||
|
||||
initHotSpot(hotSpotList: Array<any>) {
|
||||
|
||||
hotSpotList.forEach((hotspot: any) => {
|
||||
|
||||
this.createHotspot(hotspot)
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
createHotspot(hotspot: any) {
|
||||
|
||||
// 检查必要的数据
|
||||
if (!hotspot) {
|
||||
console.warn('热点数据为空');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('热点原始数据:', hotspot);
|
||||
|
||||
let position: Vector3;
|
||||
|
||||
// 使用 offset 作为 position
|
||||
if (hotspot.offset) {
|
||||
if (Array.isArray(hotspot.offset)) {
|
||||
console.log('offset 数组:', hotspot.offset);
|
||||
position = new Vector3(
|
||||
hotspot.offset[0] ?? 0,
|
||||
hotspot.offset[1] ?? 0,
|
||||
hotspot.offset[2] ?? 0
|
||||
);
|
||||
} else {
|
||||
position = new Vector3(
|
||||
hotspot.offset.x ?? 0,
|
||||
hotspot.offset.y ?? 0,
|
||||
hotspot.offset.z ?? 0
|
||||
);
|
||||
}
|
||||
} else if (hotspot.position) {
|
||||
// 兼容 position 字段
|
||||
if (Array.isArray(hotspot.position)) {
|
||||
position = new Vector3(
|
||||
hotspot.position[0] ?? 0,
|
||||
hotspot.position[1] ?? 0,
|
||||
hotspot.position[2] ?? 0
|
||||
);
|
||||
} else {
|
||||
position = new Vector3(
|
||||
hotspot.position.x ?? 0,
|
||||
hotspot.position.y ?? 0,
|
||||
hotspot.position.z ?? 0
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.warn('热点数据缺少 position 或 offset 字段:', hotspot);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('创建热点:', hotspot.name, 'position:', position, 'x:', position.x, 'y:', position.y, 'z:', position.z);
|
||||
|
||||
const disposition = Vector3.Zero();
|
||||
|
||||
this.hotSpot.Point_Event(
|
||||
new HotspotPrams(
|
||||
position,
|
||||
disposition,
|
||||
() => {
|
||||
},
|
||||
async (p: Point) => {
|
||||
console.log('热点被点击:', hotspot.name, hotspot.payload)
|
||||
// 触发热点点击事件
|
||||
EventBridge.hotspotClick({
|
||||
id: hotspot.id,
|
||||
name: hotspot.name,
|
||||
meshName: hotspot.meshName,
|
||||
payload: hotspot.payload
|
||||
})
|
||||
},
|
||||
hotspot.icon,
|
||||
hotspot.radius
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
clean() {
|
||||
// 首先隐藏所有热点
|
||||
this.visible(false);
|
||||
|
||||
// 如果存在热点池
|
||||
if (this.hotSpot && this.hotSpot._point_Pool && this.hotSpot._point_Pool.points) {
|
||||
// 遍历所有热点
|
||||
for (let i = 0; i < this.hotSpot._point_Pool.points.length; i++) {
|
||||
const point = this.hotSpot._point_Pool.points[i];
|
||||
|
||||
// 清除事件监听器
|
||||
if (point.img && point.onCallBack) {
|
||||
point.img.removeEventListener('mousedown', point.onCallBack);
|
||||
}
|
||||
|
||||
// 从DOM中移除注释元素
|
||||
if (point.annotation && point.annotation.parentNode) {
|
||||
point.annotation.parentNode.removeChild(point.annotation);
|
||||
}
|
||||
|
||||
// 释放sprite资源
|
||||
if (point.sprite) {
|
||||
point.sprite.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// 清空热点池
|
||||
this.hotSpot._point_Pool.points = [];
|
||||
|
||||
|
||||
}
|
||||
|
||||
console.log('热点资源已释放');
|
||||
}
|
||||
|
||||
visible(visible: boolean) {
|
||||
console.log(visible);
|
||||
|
||||
if (this.hotSpot) {
|
||||
this.hotSpot.Enable_All(visible)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -71,6 +71,15 @@ class AppRay extends Monobehiver {
|
||||
|
||||
// 处理单击
|
||||
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,
|
||||
@ -125,18 +134,7 @@ class AppRay extends Monobehiver {
|
||||
* @param hotspots 热点数据
|
||||
*/
|
||||
renderHotspots(hotspots: any[]): void {
|
||||
console.log('Rendering hotspots:', hotspots);
|
||||
|
||||
// 这里需要根据实际的热点渲染逻辑实现
|
||||
// 示例实现:
|
||||
// 1. 清除现有的热点
|
||||
// 2. 根据热点数据创建新的热点标记
|
||||
// 3. 为热点添加交互事件
|
||||
|
||||
hotspots.forEach((hotspot, index) => {
|
||||
console.log(`Rendering hotspot ${index}:`, hotspot);
|
||||
// 这里需要根据实际的热点数据结构实现
|
||||
});
|
||||
this.mainApp.appHotspot?.render(hotspots);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Mesh, PBRMaterial, Texture, AbstractMesh, Plane, Vector3, Scene, Color3 } from "@babylonjs/core";
|
||||
import { Mesh, PBRMaterial, Texture, AbstractMesh, Plane, Vector3, Scene, Color3, TransformNode } from "@babylonjs/core";
|
||||
import { Observer } from "@babylonjs/core/Misc/observable";
|
||||
import { Nullable } from "@babylonjs/core/types";
|
||||
import { Monobehiver } from '../base/Monobehiver';
|
||||
@ -441,10 +441,10 @@ export class GameManager extends Monobehiver {
|
||||
this.rollerDoorGroup!.position.y = next;
|
||||
|
||||
// 打印每个卷帘门的当前位置
|
||||
console.log('Roller door positions:');
|
||||
for (const mesh of this.rollerDoorMeshes) {
|
||||
console.log(`${mesh.name}: ${mesh.position.y.toFixed(2)}`);
|
||||
}
|
||||
// console.log('Roller door positions:');
|
||||
// for (const mesh of this.rollerDoorMeshes) {
|
||||
// console.log(`${mesh.name}: ${mesh.position.y.toFixed(2)}`);
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
@ -544,8 +544,8 @@ export class GameManager extends Monobehiver {
|
||||
// 创建或获取 group 作为父级
|
||||
if (!this.rollerDoorGroup) {
|
||||
// 创建一个 AbstractMesh 作为组
|
||||
this.rollerDoorGroup = new AbstractMesh('rollerDoorGroup', scene);
|
||||
// 确保 group 的缩放为 1
|
||||
// 使用 TransformNode 代替 AbstractMesh,因为 AbstractMesh 是抽象类无法实例化
|
||||
this.rollerDoorGroup = new TransformNode('rollerDoorGroup', scene) as any;
|
||||
// 确保 group 的初始位置为 (0, 0, 0)
|
||||
this.rollerDoorGroup.position.set(0, 0, 0);
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import { AppConfig } from './AppConfig';
|
||||
import { AppRay } from './AppRay';
|
||||
import { GameManager } from './GameManager';
|
||||
import { EventBridge } from '../event/bridge';
|
||||
import { AppHotspot } from './AppHotspot';
|
||||
|
||||
/**
|
||||
* 主应用类 - 3D场景的核心控制器
|
||||
@ -26,6 +27,7 @@ export class MainApp {
|
||||
appLight: AppLight;
|
||||
appEnv: AppEnv;
|
||||
appRay: AppRay;
|
||||
appHotspot: AppHotspot;
|
||||
gameManager: GameManager;
|
||||
|
||||
|
||||
@ -37,6 +39,7 @@ export class MainApp {
|
||||
this.appLight = new AppLight(this);
|
||||
this.appEnv = new AppEnv(this);
|
||||
this.appRay = new AppRay(this);
|
||||
this.appHotspot = new AppHotspot(this);
|
||||
this.gameManager = new GameManager(this);
|
||||
|
||||
window.addEventListener("resize", () => this.appEngin.handleResize());
|
||||
@ -84,5 +87,6 @@ export class MainApp {
|
||||
async dispose(): Promise<void> {
|
||||
this.appModel?.clean();
|
||||
this.appEnv?.clean();
|
||||
this.appHotspot?.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user