2026-03-30 15:56:18 +08:00
|
|
|
import { BaseManager } from '../core/base-manager';
|
|
|
|
|
import { ManagerRegistry } from '../core/manager-registry';
|
|
|
|
|
import { WalkDockPanel } from '../components/walk-dock-panel';
|
|
|
|
|
import { WalkPathDialogManager } from './walk-path-dialog-manager';
|
|
|
|
|
|
|
|
|
|
export class WalkDockManager extends BaseManager {
|
|
|
|
|
private panel: WalkDockPanel | null = null;
|
|
|
|
|
private pathManager: WalkPathDialogManager | null = null;
|
|
|
|
|
private unsubscribeDockState: (() => void) | null = null;
|
|
|
|
|
|
|
|
|
|
constructor(registry: ManagerRegistry) {
|
|
|
|
|
super(registry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public init(): void {
|
|
|
|
|
this.pathManager = new WalkPathDialogManager(this.registry);
|
|
|
|
|
this.pathManager.init();
|
|
|
|
|
|
|
|
|
|
if (!this.unsubscribeDockState) {
|
|
|
|
|
this.unsubscribeDockState = this.registry.bottomDock?.onStateChange((state) => {
|
|
|
|
|
if (state.id !== 'walk') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (state.open) {
|
|
|
|
|
this.onOpen();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.onClose();
|
|
|
|
|
}) ?? null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public destroy(): void {
|
|
|
|
|
if (this.unsubscribeDockState) {
|
|
|
|
|
this.unsubscribeDockState();
|
|
|
|
|
this.unsubscribeDockState = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.onClose();
|
|
|
|
|
this.pathManager?.destroy();
|
|
|
|
|
this.pathManager = null;
|
|
|
|
|
super.destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getPanelElement(): HTMLElement {
|
|
|
|
|
if (!this.panel) {
|
|
|
|
|
this.panel = new WalkDockPanel({
|
|
|
|
|
onPlanViewToggle: (isActive) => {
|
|
|
|
|
this.engineComponent?.toggleMiniMap();
|
|
|
|
|
this.registry.toolbar?.setBtnActive('map', isActive);
|
|
|
|
|
this.emit('walk:plan-view-toggle', { isActive });
|
|
|
|
|
},
|
|
|
|
|
onPathModeToggle: (isActive) => {
|
|
|
|
|
if (isActive) {
|
|
|
|
|
this.pathManager?.show();
|
|
|
|
|
} else {
|
|
|
|
|
this.pathManager?.hide();
|
|
|
|
|
}
|
|
|
|
|
this.emit('walk:path-mode-toggle', { isActive });
|
|
|
|
|
},
|
|
|
|
|
onWalkModeToggle: (isActive) => {
|
|
|
|
|
if (isActive) {
|
|
|
|
|
this.pathManager?.hide();
|
|
|
|
|
}
|
|
|
|
|
this.emit('walk:walk-mode-toggle', { isActive });
|
|
|
|
|
},
|
|
|
|
|
onSpeedChange: (speed) => {
|
|
|
|
|
const engineSpeed = speed * 0.1;
|
|
|
|
|
this.engineComponent?.setWalkSpeed(engineSpeed);
|
|
|
|
|
this.emit('walk:speed-change', { speed });
|
|
|
|
|
},
|
|
|
|
|
onGravityToggle: (enabled) => {
|
|
|
|
|
this.engineComponent?.setWalkGravity(enabled);
|
|
|
|
|
this.emit('walk:gravity-toggle', { enabled });
|
|
|
|
|
},
|
|
|
|
|
onCollisionToggle: (enabled) => {
|
|
|
|
|
this.engineComponent?.setWalkCollision(enabled);
|
|
|
|
|
this.emit('walk:collision-toggle', { enabled });
|
|
|
|
|
},
|
|
|
|
|
onCharacterModelChange: (model) => {
|
|
|
|
|
void model;
|
|
|
|
|
},
|
|
|
|
|
onWalkModeChange: (mode) => {
|
|
|
|
|
void mode;
|
|
|
|
|
},
|
|
|
|
|
onExit: () => {
|
|
|
|
|
this.registry.bottomDock?.close('walk');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.panel.init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.syncMapState();
|
|
|
|
|
return this.panel.element;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private onOpen(): void {
|
|
|
|
|
this.engineComponent?.activateFirstPersonMode();
|
|
|
|
|
this.syncMapState();
|
2026-04-21 15:07:49 +08:00
|
|
|
|
|
|
|
|
const engineSpeed = this.engineComponent?.getWalkSpeed() ?? 1;
|
|
|
|
|
const panelSpeed = Math.round(engineSpeed / 0.1);
|
|
|
|
|
console.log('[WalkDock] 初始速度 - engineSpeed:', engineSpeed, 'panelSpeed:', panelSpeed);
|
|
|
|
|
this.panel?.setSpeed(panelSpeed);
|
2026-03-30 15:56:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private onClose(): void {
|
|
|
|
|
this.pathManager?.hide();
|
|
|
|
|
|
|
|
|
|
if (this.engineComponent?.getMiniMapState()) {
|
|
|
|
|
this.engineComponent.toggleMiniMap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.engineComponent?.deactivateFirstPersonMode();
|
|
|
|
|
|
|
|
|
|
if (this.panel) {
|
|
|
|
|
this.panel.destroy();
|
|
|
|
|
this.panel = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.registry.toolbar?.setBtnActive('map', false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private syncMapState(): void {
|
|
|
|
|
const mapState = this.engineComponent?.getMiniMapState() ?? false;
|
|
|
|
|
this.panel?.setPlanViewActive(mapState);
|
|
|
|
|
}
|
|
|
|
|
}
|