1
This commit is contained in:
257
src/babylonjs/AppModelDrag.ts
Normal file
257
src/babylonjs/AppModelDrag.ts
Normal file
@ -0,0 +1,257 @@
|
||||
import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh';
|
||||
import { PointerDragBehavior } from '@babylonjs/core/Behaviors/Meshes/pointerDragBehavior';
|
||||
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
|
||||
import { Scene } from '@babylonjs/core/scene';
|
||||
import { Monobehiver } from '../base/Monobehiver';
|
||||
|
||||
/**
|
||||
* 拖拽配置接口
|
||||
*/
|
||||
export interface DragConfig {
|
||||
enable: boolean;
|
||||
axis?: 'x' | 'y' | 'z' | 'xy' | 'xz' | 'yz' | 'xyz';
|
||||
step?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型拖拽信息
|
||||
*/
|
||||
interface ModelDragInfo {
|
||||
config: DragConfig;
|
||||
behavior: PointerDragBehavior | null;
|
||||
currentAxis: 'x' | 'y' | 'z' | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型拖拽管理器 - 负责处理模型的拖拽交互
|
||||
*/
|
||||
export class AppModelDrag extends Monobehiver {
|
||||
private modelDragMap: Map<string, ModelDragInfo>;
|
||||
private scene: Scene | null;
|
||||
|
||||
constructor(mainApp: any) {
|
||||
super(mainApp);
|
||||
this.modelDragMap = new Map();
|
||||
this.scene = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化拖拽管理器
|
||||
*/
|
||||
Awake(): void {
|
||||
this.scene = this.mainApp.appScene.object;
|
||||
if (!this.scene) {
|
||||
console.warn('Scene not initialized');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为模型配置拖拽
|
||||
* @param modelId 模型ID
|
||||
* @param config 拖拽配置
|
||||
*/
|
||||
configureDrag(modelId: string, config: DragConfig): void {
|
||||
// 获取模型的根网格
|
||||
const meshes = this.mainApp.appModel?.modelDic?.Get(modelId);
|
||||
if (!meshes || !meshes.length) {
|
||||
console.warn(`Model not found: ${modelId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const rootMesh = meshes[0]; // 第一个是根节点
|
||||
|
||||
// 如果已存在,先移除旧的行为
|
||||
const existingInfo = this.modelDragMap.get(modelId);
|
||||
if (existingInfo?.behavior) {
|
||||
rootMesh.removeBehavior(existingInfo.behavior);
|
||||
}
|
||||
|
||||
// 创建拖拽信息
|
||||
const dragInfo: ModelDragInfo = {
|
||||
config: { ...config },
|
||||
behavior: null,
|
||||
currentAxis: this.getFirstAvailableAxis(config.axis || 'xyz')
|
||||
};
|
||||
|
||||
if (config.enable) {
|
||||
// 创建并配置拖拽行为
|
||||
dragInfo.behavior = this.createDragBehavior(modelId, dragInfo);
|
||||
rootMesh.addBehavior(dragInfo.behavior);
|
||||
}
|
||||
|
||||
this.modelDragMap.set(modelId, dragInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建拖拽行为
|
||||
*/
|
||||
private createDragBehavior(modelId: string, dragInfo: ModelDragInfo): PointerDragBehavior {
|
||||
const axis = dragInfo.currentAxis;
|
||||
let dragAxis: Vector3;
|
||||
|
||||
// 根据当前激活的轴创建拖拽向量
|
||||
switch (axis) {
|
||||
case 'x':
|
||||
dragAxis = new Vector3(1, 0, 0);
|
||||
break;
|
||||
case 'y':
|
||||
dragAxis = new Vector3(0, 1, 0);
|
||||
break;
|
||||
case 'z':
|
||||
dragAxis = new Vector3(0, 0, 1);
|
||||
break;
|
||||
default:
|
||||
dragAxis = new Vector3(1, 0, 0);
|
||||
}
|
||||
|
||||
// 创建拖拽行为
|
||||
const pointerDragBehavior = new PointerDragBehavior({ dragAxis: dragAxis });
|
||||
|
||||
// 使用世界坐标系而不是物体本地坐标系
|
||||
pointerDragBehavior.useObjectOrientationForDragging = false;
|
||||
|
||||
// 监听拖拽开始事件
|
||||
pointerDragBehavior.onDragStartObservable.add(() => {
|
||||
// 禁用相机控制
|
||||
this.disableCameraControl();
|
||||
});
|
||||
|
||||
// 监听拖拽结束事件
|
||||
pointerDragBehavior.onDragEndObservable.add(() => {
|
||||
// 恢复相机控制
|
||||
this.enableCameraControl();
|
||||
});
|
||||
|
||||
return pointerDragBehavior;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型的拖拽配置
|
||||
* @param modelId 模型ID
|
||||
*/
|
||||
getDragConfig(modelId: string): DragConfig | undefined {
|
||||
return this.modelDragMap.get(modelId)?.config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用/禁用模型拖拽
|
||||
* @param modelId 模型ID
|
||||
* @param enable 是否启用
|
||||
*/
|
||||
setDragEnabled(modelId: string, enable: boolean): void {
|
||||
const dragInfo = this.modelDragMap.get(modelId);
|
||||
if (!dragInfo) return;
|
||||
|
||||
dragInfo.config.enable = enable;
|
||||
|
||||
const meshes = this.mainApp.appModel?.modelDic?.Get(modelId);
|
||||
if (!meshes || !meshes.length) return;
|
||||
|
||||
const rootMesh = meshes[0];
|
||||
|
||||
if (enable) {
|
||||
// 启用:创建并添加行为
|
||||
if (!dragInfo.behavior) {
|
||||
dragInfo.behavior = this.createDragBehavior(modelId, dragInfo);
|
||||
rootMesh.addBehavior(dragInfo.behavior);
|
||||
}
|
||||
} else {
|
||||
// 禁用:移除行为
|
||||
if (dragInfo.behavior) {
|
||||
rootMesh.removeBehavior(dragInfo.behavior);
|
||||
dragInfo.behavior = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换激活的轴向
|
||||
* @param modelId 模型ID
|
||||
* @param axis 要激活的轴向
|
||||
*/
|
||||
switchAxis(modelId: string, axis: 'x' | 'y' | 'z'): void {
|
||||
const dragInfo = this.modelDragMap.get(modelId);
|
||||
if (!dragInfo) return;
|
||||
|
||||
// 检查该轴是否在允许的轴向中
|
||||
if (!this.isAxisAllowed(axis, dragInfo.config.axis || 'xyz')) {
|
||||
console.warn(`Axis ${axis} is not allowed for model ${modelId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新当前轴
|
||||
dragInfo.currentAxis = axis;
|
||||
|
||||
// 重新创建拖拽行为
|
||||
const meshes = this.mainApp.appModel?.modelDic?.Get(modelId);
|
||||
if (!meshes || !meshes.length) return;
|
||||
|
||||
const rootMesh = meshes[0];
|
||||
|
||||
// 移除旧行为
|
||||
if (dragInfo.behavior) {
|
||||
rootMesh.removeBehavior(dragInfo.behavior);
|
||||
}
|
||||
|
||||
// 创建新行为
|
||||
if (dragInfo.config.enable) {
|
||||
dragInfo.behavior = this.createDragBehavior(modelId, dragInfo);
|
||||
rootMesh.addBehavior(dragInfo.behavior);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置中的第一个可用轴
|
||||
*/
|
||||
private getFirstAvailableAxis(axisConfig: string): 'x' | 'y' | 'z' | null {
|
||||
if (axisConfig.includes('x')) return 'x';
|
||||
if (axisConfig.includes('y')) return 'y';
|
||||
if (axisConfig.includes('z')) return 'z';
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查轴是否在允许的配置中
|
||||
*/
|
||||
private isAxisAllowed(axis: 'x' | 'y' | 'z', axisConfig: string): boolean {
|
||||
return axisConfig.includes(axis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用相机控制
|
||||
*/
|
||||
private disableCameraControl(): void {
|
||||
const camera = this.mainApp.appCamera?.object;
|
||||
if (camera) {
|
||||
camera.detachControl();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用相机控制
|
||||
*/
|
||||
private enableCameraControl(): void {
|
||||
const camera = this.mainApp.appCamera?.object;
|
||||
const canvas = this.mainApp.appEngin?.object?.getRenderingCanvas();
|
||||
if (camera && canvas) {
|
||||
camera.attachControl(canvas, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理资源
|
||||
*/
|
||||
dispose(): void {
|
||||
// 移除所有拖拽行为
|
||||
this.modelDragMap.forEach((dragInfo, modelId) => {
|
||||
if (dragInfo.behavior) {
|
||||
const meshes = this.mainApp.appModel?.modelDic?.Get(modelId);
|
||||
if (meshes && meshes.length) {
|
||||
meshes[0].removeBehavior(dragInfo.behavior);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.modelDragMap.clear();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user