From 74defa0a5347a802de9ce40c21245093724c58f2 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 10:58:20 +0000
Subject: [PATCH 1/7] Initial plan
From d29458bc217d6eed32f2adf7a8ddc9d2aedd5471 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 11:18:27 +0000
Subject: [PATCH 2/7] Add lakes as movable, toggleable layer in map layers
panel
Agent-Logs-Url: https://github.com/Azgaar/Fantasy-Map-Generator/sessions/ee056fa6-a52a-4abf-98d8-ff91ec027763
Co-authored-by: Azgaar <26469650+Azgaar@users.noreply.github.com>
---
public/modules/io/load.js | 1 +
public/modules/ui/hotkeys.js | 1 +
public/modules/ui/layers.js | 28 ++++++++++++++++++++++++----
src/index.html | 8 ++++++++
4 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/public/modules/io/load.js b/public/modules/io/load.js
index f1ee17e4c..3d41752f3 100644
--- a/public/modules/io/load.js
+++ b/public/modules/io/load.js
@@ -434,6 +434,7 @@ async function parseLoadedData(data, mapVersion) {
// turn on active layers
if (hasChild(texture, "image")) turnOn("toggleTexture");
if (hasChildren(terrs.select("#landHeights"))) turnOn("toggleHeight");
+ if (isVisible(lakes)) turnOn("toggleLakes");
if (hasChildren(biomes)) turnOn("toggleBiomes");
if (hasChildren(cells)) turnOn("toggleCells");
if (hasChildren(gridOverlay)) turnOn("toggleGrid");
diff --git a/public/modules/ui/hotkeys.js b/public/modules/ui/hotkeys.js
index 4b1e626d5..8dd54f022 100644
--- a/public/modules/ui/hotkeys.js
+++ b/public/modules/ui/hotkeys.js
@@ -61,6 +61,7 @@ function handleKeyup(event) {
else if (key === "%") toggleAddMarker();
else if (code === "KeyX") toggleTexture();
else if (code === "KeyH") toggleHeight();
+ else if (code === "KeyQ") toggleLakes();
else if (code === "KeyB") toggleBiomes();
else if (code === "KeyE") toggleCells();
else if (code === "KeyG") toggleGrid();
diff --git a/public/modules/ui/layers.js b/public/modules/ui/layers.js
index f2f04a4be..96877e9c4 100644
--- a/public/modules/ui/layers.js
+++ b/public/modules/ui/layers.js
@@ -11,6 +11,7 @@ function getDefaultPresets() {
"toggleBurgIcons",
"toggleIce",
"toggleLabels",
+ "toggleLakes",
"toggleRivers",
"toggleRoutes",
"toggleScaleBar",
@@ -22,6 +23,7 @@ function getDefaultPresets() {
"toggleBurgIcons",
"toggleCultures",
"toggleLabels",
+ "toggleLakes",
"toggleRivers",
"toggleRoutes",
"toggleScaleBar",
@@ -31,6 +33,7 @@ function getDefaultPresets() {
"toggleBorders",
"toggleBurgIcons",
"toggleLabels",
+ "toggleLakes",
"toggleReligions",
"toggleRivers",
"toggleRoutes",
@@ -40,19 +43,21 @@ function getDefaultPresets() {
provinces: [
"toggleBorders",
"toggleBurgIcons",
+ "toggleLakes",
"toggleProvinces",
"toggleRivers",
"toggleScaleBar",
"toggleVignette"
],
- biomes: ["toggleBiomes", "toggleIce", "toggleRivers", "toggleScaleBar", "toggleVignette"],
- heightmap: ["toggleHeight", "toggleRivers", "toggleVignette"],
- physical: ["toggleCoordinates", "toggleHeight", "toggleIce", "toggleRivers", "toggleScaleBar", "toggleVignette"],
+ biomes: ["toggleBiomes", "toggleIce", "toggleLakes", "toggleRivers", "toggleScaleBar", "toggleVignette"],
+ heightmap: ["toggleHeight", "toggleLakes", "toggleRivers", "toggleVignette"],
+ physical: ["toggleCoordinates", "toggleHeight", "toggleIce", "toggleLakes", "toggleRivers", "toggleScaleBar", "toggleVignette"],
poi: [
"toggleBorders",
"toggleBurgIcons",
"toggleHeight",
"toggleIce",
+ "toggleLakes",
"toggleMarkers",
"toggleRivers",
"toggleRoutes",
@@ -63,6 +68,7 @@ function getDefaultPresets() {
"toggleBorders",
"toggleBurgIcons",
"toggleLabels",
+ "toggleLakes",
"toggleMilitary",
"toggleRivers",
"toggleRoutes",
@@ -75,13 +81,14 @@ function getDefaultPresets() {
"toggleBurgIcons",
"toggleIce",
"toggleEmblems",
+ "toggleLakes",
"toggleRivers",
"toggleRoutes",
"toggleScaleBar",
"toggleStates",
"toggleVignette"
],
- landmass: ["toggleScaleBar"]
+ landmass: ["toggleLakes", "toggleScaleBar"]
};
}
@@ -709,6 +716,18 @@ function toggleRelief(event) {
}
}
+function toggleLakes(event) {
+ if (!layerIsOn("toggleLakes")) {
+ turnButtonOn("toggleLakes");
+ $("#lakes").fadeIn();
+ if (event && isCtrlClick(event)) editStyle("lakes");
+ } else {
+ if (event && isCtrlClick(event)) return editStyle("lakes");
+ $("#lakes").fadeOut();
+ turnButtonOff("toggleLakes");
+ }
+}
+
function toggleTexture(event) {
if (!layerIsOn("toggleTexture")) {
turnButtonOn("toggleTexture");
@@ -979,6 +998,7 @@ function moveLayer(event, ui) {
// define connection between option layer buttons and actual svg groups to move the element
function getLayer(id) {
+ if (id === "toggleLakes") return $("#lakes");
if (id === "toggleHeight") return $("#terrs");
if (id === "toggleBiomes") return $("#biomes");
if (id === "toggleCells") return $("#cells");
diff --git a/src/index.html b/src/index.html
index e4958414e..30408f7c8 100644
--- a/src/index.html
+++ b/src/index.html
@@ -497,6 +497,14 @@
data-tip="Click to toggle a layer, drag to raise or lower a layer. Ctrl + click to edit layer style"
id="mapLayers"
>
+
+ Lakes
+
Date: Wed, 22 Apr 2026 12:08:59 +0000
Subject: [PATCH 3/7] Reposition Lakes after Heightmap in panel and add e2e
tests
Agent-Logs-Url: https://github.com/Azgaar/Fantasy-Map-Generator/sessions/000c5f7d-f7b5-44cd-9924-84f1a8877e63
Co-authored-by: Azgaar <26469650+Azgaar@users.noreply.github.com>
---
src/index.html | 16 +++---
tests/e2e/lakes-layer.spec.ts | 103 ++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+), 8 deletions(-)
create mode 100644 tests/e2e/lakes-layer.spec.ts
diff --git a/src/index.html b/src/index.html
index 30408f7c8..f32c80ed0 100644
--- a/src/index.html
+++ b/src/index.html
@@ -497,14 +497,6 @@
data-tip="Click to toggle a layer, drag to raise or lower a layer. Ctrl + click to edit layer style"
id="mapLayers"
>
-
- Lakes
-
Heightmap
+
+ Lakes
+
{
+ test.beforeEach(async ({ context, page }) => {
+ await context.clearCookies();
+
+ await page.goto("/");
+ await page.evaluate(() => {
+ localStorage.clear();
+ sessionStorage.clear();
+ });
+
+ await page.goto("/?seed=test-seed&width=1280&height=720");
+
+ // Wait for map generation to complete
+ await page.waitForFunction(() => (window as any).mapId !== undefined, {
+ timeout: 60000,
+ });
+
+ // Wait for any post-generation rendering to settle
+ await page.waitForTimeout(500);
+ });
+
+ test("lakes toggle button hides and shows the #lakes SVG group", async ({
+ page,
+ }) => {
+ const lakes = page.locator("#lakes");
+
+ // Open the options panel (layers tab) so the toggle button is reachable
+ await page.evaluate(() => (window as any).showOptions());
+
+ // Lakes should be visible by default
+ await expect(lakes).toBeVisible();
+
+ // Click the toggle button to hide; wait for jQuery fadeOut to complete
+ await page.locator("#toggleLakes").click();
+ await expect(lakes).toBeHidden();
+
+ // Click again to show; wait for jQuery fadeIn to complete
+ await page.locator("#toggleLakes").click();
+ await expect(lakes).toBeVisible();
+ });
+
+ test("KeyQ toggles the lakes layer", async ({ page }) => {
+ const lakes = page.locator("#lakes");
+
+ // Lakes should be visible by default
+ await expect(lakes).toBeVisible();
+
+ // Press Q to hide lakes; wait for jQuery fadeOut to complete
+ await page.keyboard.press("q");
+ await expect(lakes).toBeHidden();
+
+ // Press Q again to show lakes; wait for jQuery fadeIn to complete
+ await page.keyboard.press("q");
+ await expect(lakes).toBeVisible();
+ });
+
+ test("Lakes panel entry is positioned just after Heightmap", async ({
+ page,
+ }) => {
+ const [lakesIndex, heightmapIndex] = await page.evaluate(() => {
+ const items = Array.from(
+ document.querySelectorAll("#mapLayers > li")
+ ) as HTMLElement[];
+ return [
+ items.findIndex((li) => li.id === "toggleLakes"),
+ items.findIndex((li) => li.id === "toggleHeight"),
+ ];
+ });
+
+ expect(lakesIndex).toBe(heightmapIndex + 1);
+ });
+
+ test("dragging Lakes below Heightmap in panel moves #lakes after #terrs in SVG", async ({
+ page,
+ }) => {
+ // Confirm initial SVG order: #lakes is before #terrs (rendered behind heightmap by default)
+ const initialOrder = await page.evaluate(() => {
+ const viewbox = document.getElementById("viewbox")!;
+ const ids = Array.from(viewbox.children).map((el) => el.id);
+ return { lakes: ids.indexOf("lakes"), terrs: ids.indexOf("terrs") };
+ });
+ expect(initialOrder.lakes).toBeGreaterThanOrEqual(0);
+ expect(initialOrder.terrs).toBeGreaterThanOrEqual(0);
+ expect(initialOrder.lakes).toBeLessThan(initialOrder.terrs);
+
+ // Simulate what moveLayer does when the user drags Lakes below Heightmap:
+ // panel item "toggleLakes" is now after "toggleHeight" → el.insertAfter(#terrs)
+ await page.evaluate(() => {
+ const $ = (window as any).$;
+ $("#lakes").insertAfter($("#terrs"));
+ });
+
+ // After move: #lakes should be after #terrs in SVG → renders on top of heightmap
+ const newOrder = await page.evaluate(() => {
+ const viewbox = document.getElementById("viewbox")!;
+ const ids = Array.from(viewbox.children).map((el) => el.id);
+ return { lakes: ids.indexOf("lakes"), terrs: ids.indexOf("terrs") };
+ });
+ expect(newOrder.lakes).toBeGreaterThan(newOrder.terrs);
+ });
+});
From c8ff7ba558675447f72cdfe7d35d3c145a01aa12 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 12:40:38 +0000
Subject: [PATCH 4/7] Remove toggleLakes from the landmass preset
Agent-Logs-Url: https://github.com/Azgaar/Fantasy-Map-Generator/sessions/d15d8549-f004-4431-9be6-a5a9069e7fac
Co-authored-by: Azgaar <26469650+Azgaar@users.noreply.github.com>
---
public/modules/ui/layers.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/public/modules/ui/layers.js b/public/modules/ui/layers.js
index 96877e9c4..10123b386 100644
--- a/public/modules/ui/layers.js
+++ b/public/modules/ui/layers.js
@@ -88,7 +88,7 @@ function getDefaultPresets() {
"toggleStates",
"toggleVignette"
],
- landmass: ["toggleLakes", "toggleScaleBar"]
+ landmass: ["toggleScaleBar"]
};
}
From ca62139f387699c7fab1a77193761407ee22c0cd Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 12:44:23 +0000
Subject: [PATCH 5/7] Move #lakes SVG group after #terrs so lakes render above
heightmap by default
Agent-Logs-Url: https://github.com/Azgaar/Fantasy-Map-Generator/sessions/cd73e8fd-9235-4ea0-b026-0490582c209f
Co-authored-by: Azgaar <26469650+Azgaar@users.noreply.github.com>
---
public/main.js | 2 +-
tests/e2e/lakes-layer.spec.ts | 16 ++++++++--------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/public/main.js b/public/main.js
index 033181cbf..6786852a6 100644
--- a/public/main.js
+++ b/public/main.js
@@ -40,10 +40,10 @@ let legend = svg.append("g").attr("id", "legend");
let ocean = viewbox.append("g").attr("id", "ocean");
let oceanLayers = ocean.append("g").attr("id", "oceanLayers");
let oceanPattern = ocean.append("g").attr("id", "oceanPattern");
-let lakes = viewbox.append("g").attr("id", "lakes");
let landmass = viewbox.append("g").attr("id", "landmass");
let texture = viewbox.append("g").attr("id", "texture");
let terrs = viewbox.append("g").attr("id", "terrs");
+let lakes = viewbox.append("g").attr("id", "lakes");
let biomes = viewbox.append("g").attr("id", "biomes");
let cells = viewbox.append("g").attr("id", "cells");
let gridOverlay = viewbox.append("g").attr("id", "gridOverlay");
diff --git a/tests/e2e/lakes-layer.spec.ts b/tests/e2e/lakes-layer.spec.ts
index b2555c25f..0d9a19102 100644
--- a/tests/e2e/lakes-layer.spec.ts
+++ b/tests/e2e/lakes-layer.spec.ts
@@ -72,10 +72,10 @@ test.describe("Lakes layer", () => {
expect(lakesIndex).toBe(heightmapIndex + 1);
});
- test("dragging Lakes below Heightmap in panel moves #lakes after #terrs in SVG", async ({
+ test("dragging Lakes above Heightmap in panel moves #lakes before #terrs in SVG", async ({
page,
}) => {
- // Confirm initial SVG order: #lakes is before #terrs (rendered behind heightmap by default)
+ // Confirm initial SVG order: #lakes is after #terrs (rendered above heightmap by default)
const initialOrder = await page.evaluate(() => {
const viewbox = document.getElementById("viewbox")!;
const ids = Array.from(viewbox.children).map((el) => el.id);
@@ -83,21 +83,21 @@ test.describe("Lakes layer", () => {
});
expect(initialOrder.lakes).toBeGreaterThanOrEqual(0);
expect(initialOrder.terrs).toBeGreaterThanOrEqual(0);
- expect(initialOrder.lakes).toBeLessThan(initialOrder.terrs);
+ expect(initialOrder.lakes).toBeGreaterThan(initialOrder.terrs);
- // Simulate what moveLayer does when the user drags Lakes below Heightmap:
- // panel item "toggleLakes" is now after "toggleHeight" → el.insertAfter(#terrs)
+ // Simulate what moveLayer does when the user drags Lakes above Heightmap:
+ // panel item "toggleLakes" is now before "toggleHeight" → el.insertBefore(#terrs)
await page.evaluate(() => {
const $ = (window as any).$;
- $("#lakes").insertAfter($("#terrs"));
+ $("#lakes").insertBefore($("#terrs"));
});
- // After move: #lakes should be after #terrs in SVG → renders on top of heightmap
+ // After move: #lakes should be before #terrs in SVG → renders behind heightmap
const newOrder = await page.evaluate(() => {
const viewbox = document.getElementById("viewbox")!;
const ids = Array.from(viewbox.children).map((el) => el.id);
return { lakes: ids.indexOf("lakes"), terrs: ids.indexOf("terrs") };
});
- expect(newOrder.lakes).toBeGreaterThan(newOrder.terrs);
+ expect(newOrder.lakes).toBeLessThan(newOrder.terrs);
});
});
From dcd976c5d5d1910bbfd94931ad2e864077b76924 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 13:13:04 +0000
Subject: [PATCH 6/7] Add water mask to #lakes group so inner lake islands are
visible
Agent-Logs-Url: https://github.com/Azgaar/Fantasy-Map-Generator/sessions/d8572ce6-aa57-4ce6-b9bc-7b83354a19de
Co-authored-by: Azgaar <26469650+Azgaar@users.noreply.github.com>
---
public/main.js | 2 +-
public/modules/dynamic/auto-update.js | 5 +++++
src/renderers/draw-features.ts | 3 +++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/public/main.js b/public/main.js
index 6786852a6..9d99bf188 100644
--- a/public/main.js
+++ b/public/main.js
@@ -43,7 +43,7 @@ let oceanPattern = ocean.append("g").attr("id", "oceanPattern");
let landmass = viewbox.append("g").attr("id", "landmass");
let texture = viewbox.append("g").attr("id", "texture");
let terrs = viewbox.append("g").attr("id", "terrs");
-let lakes = viewbox.append("g").attr("id", "lakes");
+let lakes = viewbox.append("g").attr("id", "lakes").attr("mask", "url(#water)");
let biomes = viewbox.append("g").attr("id", "biomes");
let cells = viewbox.append("g").attr("id", "cells");
let gridOverlay = viewbox.append("g").attr("id", "gridOverlay");
diff --git a/public/modules/dynamic/auto-update.js b/public/modules/dynamic/auto-update.js
index 775a76a6d..98b910b46 100644
--- a/public/modules/dynamic/auto-update.js
+++ b/public/modules/dynamic/auto-update.js
@@ -1112,4 +1112,9 @@ export function resolveVersionConflicts(mapVersion) {
zone.cells = unique(zone.cells);
});
}
+
+ // ensure lakes group has water mask so inner islands are not hidden by lake fill
+ if (!lakes.attr("mask")) {
+ lakes.attr("mask", "url(#water)");
+ }
}
diff --git a/src/renderers/draw-features.ts b/src/renderers/draw-features.ts
index dbbb079cb..1704af508 100644
--- a/src/renderers/draw-features.ts
+++ b/src/renderers/draw-features.ts
@@ -42,6 +42,9 @@ const featuresRenderer = (): void => {
html.landMask.push(
``,
);
+ html.waterMask.push(
+ ``,
+ );
const lakeGroup = feature.group || "freshwater";
if (!html.lakes[lakeGroup]) html.lakes[lakeGroup] = [];
From 7a4cf60986f00974ff6ee8aafd98841b286dfffe Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Apr 2026 13:20:59 +0000
Subject: [PATCH 7/7] Move #lakes mask to index.css instead of JS attribute
Agent-Logs-Url: https://github.com/Azgaar/Fantasy-Map-Generator/sessions/4a790923-83ed-4063-8813-c0702329794e
Co-authored-by: Azgaar <26469650+Azgaar@users.noreply.github.com>
---
public/index.css | 4 ++++
public/main.js | 2 +-
public/modules/dynamic/auto-update.js | 5 -----
3 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/public/index.css b/public/index.css
index c46fded9a..8d5ed9053 100644
--- a/public/index.css
+++ b/public/index.css
@@ -133,6 +133,10 @@ a {
fill-rule: evenodd;
}
+#lakes {
+ mask: url(#water);
+}
+
#lakes,
#coastline,
#armies,
diff --git a/public/main.js b/public/main.js
index 9d99bf188..6786852a6 100644
--- a/public/main.js
+++ b/public/main.js
@@ -43,7 +43,7 @@ let oceanPattern = ocean.append("g").attr("id", "oceanPattern");
let landmass = viewbox.append("g").attr("id", "landmass");
let texture = viewbox.append("g").attr("id", "texture");
let terrs = viewbox.append("g").attr("id", "terrs");
-let lakes = viewbox.append("g").attr("id", "lakes").attr("mask", "url(#water)");
+let lakes = viewbox.append("g").attr("id", "lakes");
let biomes = viewbox.append("g").attr("id", "biomes");
let cells = viewbox.append("g").attr("id", "cells");
let gridOverlay = viewbox.append("g").attr("id", "gridOverlay");
diff --git a/public/modules/dynamic/auto-update.js b/public/modules/dynamic/auto-update.js
index 98b910b46..775a76a6d 100644
--- a/public/modules/dynamic/auto-update.js
+++ b/public/modules/dynamic/auto-update.js
@@ -1112,9 +1112,4 @@ export function resolveVersionConflicts(mapVersion) {
zone.cells = unique(zone.cells);
});
}
-
- // ensure lakes group has water mask so inner islands are not hidden by lake fill
- if (!lakes.attr("mask")) {
- lakes.attr("mask", "url(#water)");
- }
}