feat: add labels module and integrate into PackedGraph

This commit is contained in:
StempunkDev 2026-02-10 22:38:38 +01:00
parent be82ddb0a4
commit 7bf33b6e65
3 changed files with 155 additions and 0 deletions

View file

@ -12,4 +12,5 @@ import "./routes-generator";
import "./states-generator";
import "./zones-generator";
import "./religions-generator";
import "./labels";
import "./provinces-generator";

152
src/modules/labels.ts Normal file
View file

@ -0,0 +1,152 @@
declare global {
var Labels: LabelsModule;
}
// --- Types ---
export interface StateLabelData {
i: number;
type: "state";
stateId: number;
text: string;
pathPoints: [number, number][];
startOffset: number;
fontSize: number;
letterSpacing: number;
transform: string;
}
export interface BurgLabelData {
i: number;
type: "burg";
burgId: number;
group: string;
text: string;
x: number;
y: number;
dx: number;
dy: number;
}
export interface CustomLabelData {
i: number;
type: "custom";
group: string;
text: string;
pathPoints: [number, number][];
startOffset: number;
fontSize: number;
letterSpacing: number;
transform: string;
}
export type LabelData = StateLabelData | BurgLabelData | CustomLabelData;
// --- Implementation ---
class LabelsModule {
private getNextId(): number {
const labels = pack.labels;
if (labels.length === 0) return 0;
const existingIds = labels.map((l) => l.i).sort((a, b) => a - b);
for (let id = 0; id < existingIds[existingIds.length - 1]; id++) {
if (!existingIds.includes(id)) return id;
}
return existingIds[existingIds.length - 1] + 1;
}
getAll(): LabelData[] {
return pack.labels;
}
get(id: number): LabelData | undefined {
return pack.labels.find((l) => l.i === id);
}
getByType(type: LabelData["type"]): LabelData[] {
return pack.labels.filter((l) => l.type === type);
}
getByGroup(group: string): LabelData[] {
return pack.labels.filter(
(l) => (l.type === "burg" || l.type === "custom") && l.group === group,
);
}
getStateLabel(stateId: number): StateLabelData | undefined {
return pack.labels.find(
(l) => l.type === "state" && l.stateId === stateId,
) as StateLabelData | undefined;
}
getBurgLabel(burgId: number): BurgLabelData | undefined {
return pack.labels.find(
(l) => l.type === "burg" && l.burgId === burgId,
) as BurgLabelData | undefined;
}
addStateLabel(
data: Omit<StateLabelData, "i" | "type">,
): StateLabelData {
const label: StateLabelData = { i: this.getNextId(), type: "state", ...data };
pack.labels.push(label);
return label;
}
addBurgLabel(data: Omit<BurgLabelData, "i" | "type">): BurgLabelData {
const label: BurgLabelData = { i: this.getNextId(), type: "burg", ...data };
pack.labels.push(label);
return label;
}
addCustomLabel(
data: Omit<CustomLabelData, "i" | "type">,
): CustomLabelData {
const label: CustomLabelData = { i: this.getNextId(), type: "custom", ...data };
pack.labels.push(label);
return label;
}
updateLabel(id: number, updates: Partial<LabelData>): void {
const label = pack.labels.find((l) => l.i === id);
if (!label) return;
Object.assign(label, updates, { i: label.i, type: label.type });
}
removeLabel(id: number): void {
const index = pack.labels.findIndex((l) => l.i === id);
if (index !== -1) pack.labels.splice(index, 1);
}
removeByType(type: LabelData["type"]): void {
pack.labels = pack.labels.filter((l) => l.type !== type);
}
removeByGroup(group: string): void {
pack.labels = pack.labels.filter(
(l) =>
!((l.type === "burg" || l.type === "custom") && l.group === group),
);
}
removeStateLabel(stateId: number): void {
const index = pack.labels.findIndex(
(l) => l.type === "state" && l.stateId === stateId,
);
if (index !== -1) pack.labels.splice(index, 1);
}
removeBurgLabel(burgId: number): void {
const index = pack.labels.findIndex(
(l) => l.type === "burg" && l.burgId === burgId,
);
if (index !== -1) pack.labels.splice(index, 1);
}
clear(): void {
pack.labels = [];
}
}
window.Labels = new LabelsModule();

View file

@ -5,6 +5,7 @@ import type { Province } from "../modules/provinces-generator";
import type { River } from "../modules/river-generator";
import type { Route } from "../modules/routes-generator";
import type { State } from "../modules/states-generator";
import type { LabelData } from "../modules/labels";
import type { Zone } from "../modules/zones-generator";
type TypedArray =
@ -62,5 +63,6 @@ export interface PackedGraph {
zones: Zone[];
markers: any[];
ice: any[];
labels: LabelData[];
provinces: Province[];
}