feat: relief three.js renderer

This commit is contained in:
Azgaar 2026-03-09 02:47:13 +01:00
parent 7a49098425
commit 7481a2843e
19 changed files with 828 additions and 120 deletions

View file

@ -27,7 +27,6 @@ function clicked() {
else if (grand.id === "burgLabels") editBurg();
else if (grand.id === "burgIcons") editBurg();
else if (parent.id === "ice") editIce(el);
else if (parent.id === "terrain") editReliefIcon();
else if (grand.id === "markers" || great.id === "markers") editMarker();
else if (grand.id === "coastline") editCoastline();
else if (grand.id === "lakes") editLake();
@ -544,8 +543,8 @@ function changePickerSpace() {
space === "hex"
? d3.rgb(this.value)
: space === "rgb"
? d3.rgb(i[0], i[1], i[2])
: d3.hsl(i[0], i[1] / 100, i[2] / 100);
? d3.rgb(i[0], i[1], i[2])
: d3.hsl(i[0], i[1] / 100, i[2] / 100);
const hsl = d3.hsl(fill);
if (isNaN(hsl.l)) {

View file

@ -129,8 +129,8 @@ function showMapTooltip(point, e, i, g) {
parent.id === "burgEmblems"
? [pack.burgs, "burg"]
: parent.id === "provinceEmblems"
? [pack.provinces, "province"]
: [pack.states, "state"];
? [pack.provinces, "province"]
: [pack.states, "state"];
const i = +e.target.dataset.i;
if (event.shiftKey) highlightEmblemElement(type, g[i]);
@ -160,8 +160,6 @@ function showMapTooltip(point, e, i, g) {
}
}
if (group === "terrain") return tip("Click to edit the Relief Icon");
if (subgroup === "burgLabels" || subgroup === "burgIcons") {
const burgId = +path[path.length - 10].dataset.id;
if (burgId) {
@ -346,7 +344,8 @@ function getFriendlyHeight([x, y]) {
function getHeight(h, abs) {
const unit = heightUnit.value;
let unitRatio = 3.281; // default calculations are in feet
if (unit === "m") unitRatio = 1; // if meter
if (unit === "m")
unitRatio = 1; // if meter
else if (unit === "f") unitRatio = 0.5468; // if fathom
let height = -990;

View file

@ -699,7 +699,16 @@ function toggleCompass(event) {
function toggleRelief(event) {
if (!layerIsOn("toggleRelief")) {
turnButtonOn("toggleRelief");
if (!terrain.selectAll("*").size()) drawReliefIcons();
if (!terrain.selectAll("*").size()) {
drawReliefIcons();
} else if (
terrain.selectAll("use").size() &&
!terrain.select("#terrainCanvasImage").size() &&
!terrain.select("#terrainGlFo").size()
) {
// Legacy SVG use elements present but no canvas/GL render yet migrate now
if (typeof migrateReliefFromSvg === "function") migrateReliefFromSvg();
}
$("#terrain").fadeIn();
if (event && isCtrlClick(event)) editStyle("terrain");
} else {

View file

@ -4,8 +4,16 @@ function editReliefIcon() {
closeDialogs(".stable");
if (!layerIsOn("toggleRelief")) toggleRelief();
// Switch from canvas image to editable SVG <use> elements
if (typeof enterReliefSvgEditMode === "function") enterReliefSvgEditMode();
terrain.selectAll("use").call(d3.drag().on("drag", dragReliefIcon)).classed("draggable", true);
elSelected = d3.select(d3.event.target);
// When called from the Tools button there is no d3 click event; fall back to the first <use>.
// When called from a map click, prefer the actual clicked element if it is a <use>.
const clickTarget = d3.event && d3.event.target;
const useTarget = clickTarget && clickTarget.tagName === "use" ? clickTarget : terrain.select("use").node();
elSelected = d3.select(useTarget);
restoreEditMode();
updateReliefIconSelected();
@ -59,6 +67,7 @@ function editReliefIcon() {
function updateReliefIconSelected() {
const type = elSelected.attr("href") || elSelected.attr("data-type");
const button = reliefIconsDiv.querySelector("svg[data-type='" + type + "']");
if (!button) return;
reliefIconsDiv.querySelectorAll("svg.pressed").forEach(b => b.classList.remove("pressed"));
button.classList.add("pressed");
@ -260,7 +269,9 @@ function editReliefIcon() {
const type = reliefIconsDiv.querySelector("svg.pressed")?.dataset.type;
selection = type ? terrain.selectAll("use[href='" + type + "']") : terrain.selectAll("use");
const size = selection.size();
alertMessage.innerHTML = type ? `Are you sure you want to remove all ${type} icons (${size})?` : `Are you sure you want to remove all icons (${size})?`;
alertMessage.innerHTML = type
? `Are you sure you want to remove all ${type} icons (${size})?`
: `Are you sure you want to remove all icons (${size})?`;
}
$("#alert").dialog({
@ -284,5 +295,7 @@ function editReliefIcon() {
removeCircle();
unselect();
clearMainTip();
// Read back edits and switch terrain to canvas rendering
if (typeof exitReliefSvgEditMode === "function") exitReliefSvgEditMode();
}
}