web-map/src/services/editor/point-manager.service.ts

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 };
}
}