118 lines
3.8 KiB
TypeScript
118 lines
3.8 KiB
TypeScript
import { type MapPen, type MapPointInfo, MapPointType, type Point, type Rect } from '@api/map';
|
|
import { CanvasLayer, LockState, s8 } from '@meta2d/core';
|
|
import { isNil } from 'lodash-es';
|
|
|
|
import type { EditorService } from '../editor.service';
|
|
import type { LayerManagerService } from '../layer-manager.service';
|
|
|
|
export class PointManager {
|
|
constructor(
|
|
private readonly editor: EditorService,
|
|
private readonly layerManager: LayerManagerService,
|
|
) {}
|
|
|
|
public getPointRect(pen?: MapPen): Rect | null {
|
|
if (isNil(pen)) return null;
|
|
const { x, y, width, height } = this.editor.getPenRect(pen);
|
|
return { x: x + width / 2, y: y + height / 2, width, height };
|
|
}
|
|
|
|
public async addPoint(p: Point, type = MapPointType.普通点, id?: string): Promise<void> {
|
|
id ||= s8();
|
|
const pointInfo: MapPointInfo = { type };
|
|
|
|
if ([MapPointType.充电点, MapPointType.停靠点].includes(type)) {
|
|
pointInfo.enabled = 1;
|
|
}
|
|
|
|
const pen: MapPen = {
|
|
...p,
|
|
...this.mapPoint(type),
|
|
...this.mapPointImage(type),
|
|
id,
|
|
name: 'point',
|
|
tags: ['point'],
|
|
label: `P${id}`,
|
|
point: pointInfo,
|
|
locked: LockState.DisableEdit,
|
|
};
|
|
pen.x! -= pen.width! / 2;
|
|
pen.y! -= pen.height! / 2;
|
|
const addedPen = await this.editor.addPen(pen, false, true, true);
|
|
|
|
this.layerManager.adjustElementLayer(addedPen);
|
|
|
|
if (type === MapPointType.动作点 && pointInfo.associatedStorageLocations?.length) {
|
|
this.editor.createStorageLocationPens(addedPen.id!, pointInfo.associatedStorageLocations);
|
|
}
|
|
}
|
|
|
|
public updatePoint(id: string, info: Partial<MapPointInfo>, autoCreateStorage = true): void {
|
|
const { point } = this.editor.getPenById(id) ?? {};
|
|
if (!point?.type) return;
|
|
const mergedPoint = { ...point, ...info };
|
|
this.editor.setValue({ id, point: mergedPoint }, { render: true, history: true, doEvent: true });
|
|
|
|
if (point.type === MapPointType.动作点 && info.associatedStorageLocations && autoCreateStorage) {
|
|
this.editor.createStorageLocationPens(id, info.associatedStorageLocations);
|
|
}
|
|
}
|
|
|
|
public changePointType(id: string, type: MapPointType): void {
|
|
const pen = this.editor.getPenById(id);
|
|
const rect = this.getPointRect(pen);
|
|
if (isNil(rect)) return;
|
|
|
|
if (pen?.point?.type === MapPointType.动作点) {
|
|
this.editor.removeStorageLocationPens(id);
|
|
}
|
|
|
|
const point = this.mapPoint(type);
|
|
const pointInfo: MapPointInfo = { type };
|
|
|
|
if ([MapPointType.充电点, MapPointType.停靠点].includes(type)) {
|
|
pointInfo.enabled = 1;
|
|
}
|
|
|
|
this.editor.setValue(
|
|
{
|
|
id,
|
|
x: rect.x - point.width / 2,
|
|
y: rect.y - point.height / 2,
|
|
...point,
|
|
...this.mapPointImage(type),
|
|
point: pointInfo,
|
|
},
|
|
{ render: true, history: true, doEvent: true },
|
|
);
|
|
|
|
if (type >= 10) {
|
|
requestAnimationFrame(() => {
|
|
this.editor.reloadTheme();
|
|
});
|
|
}
|
|
}
|
|
|
|
public refreshPointImages(): void {
|
|
this.editor.find('point').forEach((pen) => {
|
|
const type = pen.point?.type;
|
|
if (!type || type < 10) return;
|
|
this.editor.canvas.updateValue(pen, this.mapPointImage(type));
|
|
});
|
|
}
|
|
|
|
private mapPoint(type: MapPointType): Required<Pick<MapPen, 'width' | 'height' | 'lineWidth' | 'iconSize'>> {
|
|
const width = type < 10 ? 24 : 48;
|
|
const height = type < 10 ? 24 : 60;
|
|
const lineWidth = type < 10 ? 2 : 3;
|
|
const iconSize = type < 10 ? 4 : 10;
|
|
return { width, height, lineWidth, iconSize };
|
|
}
|
|
|
|
private mapPointImage(type: MapPointType): Required<Pick<MapPen, 'image' | 'canvasLayer'>> {
|
|
const theme = this.editor.data().theme;
|
|
const image = type < 10 ? '' : `${import.meta.env.BASE_URL}/point/${type}-${theme}.png`;
|
|
return { image, canvasLayer: CanvasLayer.CanvasMain };
|
|
}
|
|
}
|