Skip to content

Add Lakes as a movable, toggleable layer#1383

Merged
Azgaar merged 7 commits intomasterfrom
copilot/move-lakes-to-own-layer
Apr 22, 2026
Merged

Add Lakes as a movable, toggleable layer#1383
Azgaar merged 7 commits intomasterfrom
copilot/move-lakes-to-own-layer

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 22, 2026

Description

Custom-colored lakes (lava, abyss, etc.) were invisible when Ocean Height rendering was enabled — the heightmap (#terrs) sits above #lakes in SVG z-order and paints over them with ocean height colors. The fix is to make #lakes a proper movable layer so users can drag it relative to the heightmap, render it above the heightmap by default, and correctly mask inner lake islands so they are never hidden by the lake fill.

Changes

  • public/main.js — Moved #lakes group declaration to after #terrs so lakes render above the heightmap by default
  • public/index.css — Added #lakes { mask: url(#water); } so inner lake islands are not hidden by the lake fill (consistent with how #landmass uses mask: url(#land))
  • src/renderers/draw-features.ts — Lake features now also push a white <use> into html.waterMask so the lake area is explicitly white in the water mask while lake-island features remain black, correctly cutting holes for inner islands
  • src/index.html — New Lakes entry in #mapLayers sortable list, positioned just after the Heightmap entry; shortcut Q
  • public/modules/ui/layers.js
    • toggleLakes() — fade show/hide of #lakes; Ctrl+click opens style editor
    • getLayer("toggleLakes") — wires the list item to #lakes for drag-reorder support
    • All default presets updated to include "toggleLakes" (backward-compat: lakes were always visible before); landmass preset intentionally excludes lakes
  • public/modules/io/load.js — Restores toggle button state on map load via isVisible(lakes) check
  • public/modules/ui/hotkeys.jsKeyQ bound to toggleLakes()
  • tests/e2e/lakes-layer.spec.ts — New focused e2e tests covering: button toggle, KeyQ toggle, panel position (just after Heightmap), and SVG DOM reorder when Lakes is dragged above Heightmap

By default, #lakes now renders on top of the heightmap with inner islands properly visible. To make lakes render behind the heightmap, drag the Lakes entry above Heightmap in the layers panel.

Copilot AI requested review from Copilot and removed request for Copilot April 22, 2026 10:58
Copilot AI linked an issue Apr 22, 2026 that may be closed by this pull request
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 22, 2026

Deploy Preview for afmg ready!

Name Link
🔨 Latest commit 7a4cf60
🔍 Latest deploy log https://app.netlify.com/projects/afmg/deploys/69e8cb4076fb610008217914
😎 Deploy Preview https://deploy-preview-1383--afmg.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI requested review from Copilot and removed request for Copilot April 22, 2026 11:18
Copilot AI changed the title [WIP] Allow custom lake colors in render ocean height mode Add Lakes as a movable, toggleable layer Apr 22, 2026
Copilot AI requested a review from Azgaar April 22, 2026 11:19
@Azgaar Azgaar marked this pull request as ready for review April 22, 2026 11:43
Copilot AI review requested due to automatic review settings April 22, 2026 11:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Lakes as a first-class, movable/toggleable map layer so users can reorder it above the heightmap and keep custom-colored lakes visible when ocean-height rendering is enabled.

Changes:

  • Adds a Lakes entry to the Layers panel sortable list (with shortcut Q) and wires it to a new toggleLakes handler.
  • Implements toggleLakes() (show/hide + Ctrl+click style edit) and connects toggleLakes to the SVG #lakes group for drag-reordering.
  • Restores the Lakes toggle state on map load and binds KeyQ to toggle lakes.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/index.html Adds the Lakes list item to #mapLayers so it can be toggled and reordered by the user.
public/modules/ui/layers.js Adds toggleLakes, maps it to #lakes for sortable reordering, and updates default presets to include lakes.
public/modules/ui/hotkeys.js Binds KeyQ to toggleLakes().
public/modules/io/load.js Restores the Lakes toggle button state on load based on #lakes visibility.

Comment thread public/modules/ui/layers.js
Copy link
Copy Markdown
Owner

@Azgaar Azgaar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default, lakes should be ordered just after (above) the Heightmap layer.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 22, 2026

By default, lakes should be ordered just after (above) the Heightmap layer.

Done in commit 5374a18. The Lakes entry is now placed just after Heightmap in the layers panel. This means lakes render below the heightmap by default (matching the existing SVG z-order), and users can drag it below Heightmap in the panel when they want lakes — including custom-colored ones like lava/abyss — to render on top.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cdn.openwidget.com
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD odules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/sh (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD -main/dist/gh-gpgsign/gh-gpgsign-linux-x86_64 (dns block)
  • fonts.gstatic.com
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD odules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/sh (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD -main/dist/gh-gpgsign/gh-gpgsign-linux-x86_64 (dns block)
  • www.googletagmanager.com
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD odules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/sh (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD -main/dist/gh-gpgsign/gh-gpgsign-linux-x86_64 (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from Azgaar April 22, 2026 12:10
Copy link
Copy Markdown
Owner

@Azgaar Azgaar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove landmass from the landmass preset.

@Azgaar
Copy link
Copy Markdown
Owner

Azgaar commented Apr 22, 2026

Lakes g group is still rendered before the terrs. It should be rendered after it by default.

Copy link
Copy Markdown
Owner

@Azgaar Azgaar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lakes g group is still rendered before the terrs. It should be rendered after it by default.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 22, 2026

remove landmass from the landmass preset.

Done in commit c8ff7ba. The landmass preset is now ["toggleScaleBar"] only.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 22, 2026

Lakes g group is still rendered before the terrs. It should be rendered after it by default.

Fixed in commit ca62139. In public/main.js, the #lakes group declaration was moved from before #terrs to after it, so lakes now render on top of the heightmap by default.

Lakes g group is still rendered before the terrs. It should be rendered after it by default.

Fixed in commit ca62139. In public/main.js, the #lakes group declaration was moved from before #terrs to after it, so lakes now render on top of the heightmap by default.

Copy link
Copy Markdown
Owner

@Azgaar Azgaar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is with featurePaths rendering. Lakes may have inner island that in the current code will be hidden by lakes. To fix mask rendering need to add mask to lake group and render lake paths in water mask as white elements.
src/renderers/draw-features.ts
if (feature.type === "lake") {
html.landMask.push(
<use href="#feature_${feature.i}" data-f="${feature.i}" fill="black"></use>,
);
html.waterMask.push(
<use href="#feature_${feature.i}" data-f="${feature.i}" fill="white"></use>,
);

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 22, 2026

The problem is with featurePaths rendering. Lakes may have inner island that in the current code will be hidden by lakes. To fix mask rendering need to add mask to lake group and render lake paths...

Done in commit dcd976c. Three changes:

  1. src/renderers/draw-features.ts — lake features now also push a white <use> into html.waterMask, so the lake area is explicitly white in the water mask while lake-island features remain black (cutting holes).
  2. public/main.js — the #lakes group is created with mask="url(#water)" so inner islands are never painted over by the lake fill.
  3. public/modules/dynamic/auto-update.js — adds a migration at the end of resolveVersionConflicts that sets mask="url(#water)" on the lakes group when loading older saved maps that don't have the attribute.

Copilot AI requested a review from Azgaar April 22, 2026 13:15
Comment thread public/main.js Outdated
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)");
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only add mask at level, see index.css

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit 7a4cf60. Moved the mask to CSS level — added #lakes { mask: url(#water); } in public/index.css and removed the .attr("mask", ...) call from main.js and the auto-update migration.

Copilot AI requested a review from Azgaar April 22, 2026 13:22
@Azgaar Azgaar merged commit f47467a into master Apr 22, 2026
8 checks passed
@Azgaar Azgaar deleted the copilot/move-lakes-to-own-layer branch April 22, 2026 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow Custom Lake Colors in "Render Ocean Height" mode

3 participants