Worldshaper/src/mapEditorPopup/pixiHeightOverlayHelpers.ts
2026-06-26 18:18:14 -04:00

168 lines
6.5 KiB
TypeScript

/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck
import { BlurFilter, Sprite, Texture } from "pixi.js";
import { getWorldBorderThickness, parseHexColor } from "./pixiSurfaceHelpers";
function createBorderSprite(x, y, width, height, tint, alpha) {
const border = new Sprite(Texture.WHITE);
border.x = x;
border.y = y;
border.width = width;
border.height = height;
border.tint = tint;
border.alpha = alpha;
return border;
}
export function rebuildHeightOverlay(state, scope, helpers) {
if (!helpers.isReady() || !state.heightOverlayRoot) {
return;
}
const overlayMode = scope.isEditingHeightLayer && scope.isEditingHeightLayer() ? "height" : "";
const activeEntry = scope.getActiveHeightLayer ? scope.getActiveHeightLayer() : null;
const activeId = String(activeEntry?.id || "").trim();
if (
!state.dirty
&& state.lastHeightLayersRef === scope.heightLayers
&& state.lastHeightOverlayMode === overlayMode
&& state.lastHeightActiveId === activeId
&& state.lastHeightTileSize === scope.tileSize
) {
return;
}
state.heightPatchEntries.forEach((entry) => {
helpers.destroyHeightPatchEntry(entry);
});
state.heightPatchEntries.clear();
state.heightOverlayRoot.removeChildren();
state.lastHeightLayersRef = scope.heightLayers;
state.lastHeightOverlayMode = overlayMode;
state.lastHeightActiveId = activeId;
state.lastHeightTileSize = scope.tileSize;
if (overlayMode !== "height" || !activeEntry) {
state.heightOverlayRoot.visible = false;
return;
}
state.heightOverlayRoot.visible = true;
const activeZ = Math.max(1, Number(activeEntry.z) || 1);
const visibleEntries = (Array.isArray(scope.heightLayers) ? scope.heightLayers : [])
.filter((entry) => Math.max(1, Number(entry?.z) || 1) === activeZ);
const borderThickness = getWorldBorderThickness(scope.tileSize);
visibleEntries.forEach((entry) => {
const entryId = String(entry?.id || "").trim();
if (!entryId) {
return;
}
const isActive = entryId === activeId;
const patchContainer = new helpers.Container();
patchContainer.label = `height_${entryId}`;
patchContainer.x = Math.max(0, Number(entry?.x) || 0);
patchContainer.y = Math.max(0, Number(entry?.y) || 0);
patchContainer.alpha = isActive ? 0.92 : 0.56;
patchContainer.roundPixels = true;
state.heightOverlayRoot.addChild(patchContainer);
const rows = Array.isArray(entry?.rows) ? entry.rows : [];
let patchWidth = 0;
rows.forEach((rawRow, localY) => {
const row = String(rawRow || "");
patchWidth = Math.max(patchWidth, row.length);
for (let localX = 0; localX < row.length; localX += 1) {
const symbol = String(row.charAt(localX) || " ").charAt(0) || " ";
if (symbol === " " || symbol === ".") {
continue;
}
const sprite = new Sprite(helpers.getTileTexture(symbol));
sprite.x = localX;
sprite.y = localY;
sprite.width = 1;
sprite.height = 1;
sprite.roundPixels = true;
patchContainer.addChild(sprite);
if (isActive) {
const shade = new Sprite(Texture.WHITE);
shade.x = localX;
shade.y = localY;
shade.width = 1;
shade.height = 1;
shade.tint = parseHexColor("#9198A8", 0x9198A8);
shade.alpha = 0.28;
shade.roundPixels = true;
patchContainer.addChild(shade);
}
}
});
if (patchWidth > 0 && rows.length > 0) {
const drawW = patchWidth;
const drawH = rows.length;
const tint = isActive ? parseHexColor("#FFEB8C", 0xFFEB8C) : parseHexColor("#6EA0EB", 0x6EA0EB);
const alpha = isActive ? 0.92 : 0.55;
patchContainer.addChild(createBorderSprite(0, 0, drawW, borderThickness, tint, alpha));
patchContainer.addChild(createBorderSprite(0, drawH - borderThickness, drawW, borderThickness, tint, alpha));
patchContainer.addChild(createBorderSprite(0, 0, borderThickness, drawH, tint, alpha));
patchContainer.addChild(createBorderSprite(drawW - borderThickness, 0, borderThickness, drawH, tint, alpha));
}
state.heightPatchEntries.set(entryId, {
id: entryId,
container: patchContainer,
});
});
}
export function resetSceneRoots(state, scope) {
if (!state.backgroundSprite || !state.baseWorldRoot) {
state.backgroundSprite = new Sprite(Texture.WHITE);
state.backgroundSprite.zIndex = -1;
state.backgroundSprite.roundPixels = true;
}
state.backgroundSprite.tint = parseHexColor(scope.normalizeMapBackgroundColor(scope.backgroundColor));
state.backgroundSprite.width = Math.max(1, Number(scope.width) || 1);
state.backgroundSprite.height = Math.max(1, Number(scope.height) || 1);
if (state.backgroundSprite.parent !== state.baseWorldRoot) {
state.baseWorldRoot.addChildAt(state.backgroundSprite, 0);
}
if (state.heightOverlayRoot?.parent !== state.worldContainer) {
state.worldContainer.addChild(state.heightOverlayRoot);
}
}
export function syncHeightFocusEffect(state, scope) {
if (!state.baseWorldRoot) {
return;
}
const activeHeightLayer = scope.getActiveHeightLayer ? scope.getActiveHeightLayer() : null;
const activeHeightZ = Math.max(0, Number(activeHeightLayer?.z) || 0);
const isHeightModeActive = !!(scope.isEditingHeightLayer && scope.isEditingHeightLayer()) && activeHeightZ > 0;
const blurStep = Math.max(
0,
Math.min(
1,
Number(scope.getEffectiveHeightBlurStep?.() ?? scope.heightBlurStep ?? scope.heightDetailStep) || 0.1,
),
);
const tileReferenceSize = Math.max(8, Number(scope.baseTileSize) || Number(scope.tileSize) || 32);
const nextBlurStrength = isHeightModeActive
? Math.min(8, activeHeightZ * blurStep * (tileReferenceSize / 4))
: 0;
if (!state.heightFocusBlurFilter) {
state.heightFocusBlurFilter = new BlurFilter({ strength: 0, quality: 2, kernelSize: 5 });
state.heightFocusBlurFilter.repeatEdgePixels = true;
}
if (isHeightModeActive) {
if (!state.heightFocusCacheEnabled || Math.abs(nextBlurStrength - state.heightFocusBlurStrength) > 0.001) {
state.heightFocusBlurFilter.strength = nextBlurStrength;
state.baseWorldRoot.filters = [state.heightFocusBlurFilter];
state.heightFocusCacheEnabled = true;
state.heightFocusBlurStrength = nextBlurStrength;
}
} else if (state.heightFocusCacheEnabled) {
state.baseWorldRoot.filters = [];
state.heightFocusCacheEnabled = false;
state.heightFocusBlurStrength = 0;
}
state.baseWorldRoot.alpha = isHeightModeActive
? Math.max(0.92, 1 - (activeHeightZ * 0.015))
: 1;
}