diff --git a/public/modules/dynamic/auto-update.js b/public/modules/dynamic/auto-update.js
index 8e3ef5bc..060bb2d0 100644
--- a/public/modules/dynamic/auto-update.js
+++ b/public/modules/dynamic/auto-update.js
@@ -1041,7 +1041,8 @@ export function resolveVersionConflicts(mapVersion) {
// v1.110.0 moved ice data from SVG to data model
// Migrate old ice SVG elements to new pack.ice structure
if (!pack.ice) {
- pack.ice = { glaciers: [], icebergs: [] };
+ pack.ice = [];
+ let iceId = 0;
const iceLayer = document.getElementById("ice");
if (iceLayer) {
@@ -1051,15 +1052,15 @@ export function resolveVersionConflicts(mapVersion) {
const points = [...polygon.points].map(svgPoint => [svgPoint.x, svgPoint.y]);
const transform = polygon.getAttribute("transform");
-
- if (transform) {
- pack.ice.glaciers.push({
+ const iceElement = {
+ i: iceId++,
points,
- offset: parseTransform(transform)
- });
- } else {
- pack.ice.glaciers.push({ points });
+ type: "glacier"
+ };
+ if (transform) {
+ iceElement.offset = parseTransform(transform);
}
+ pack.ice.push(iceElement);
});
// Migrate icebergs
@@ -1074,21 +1075,17 @@ export function resolveVersionConflicts(mapVersion) {
const points = [...polygon.points].map(svgPoint => [svgPoint.x, svgPoint.y]);
const transform = polygon.getAttribute("transform");
+ const iceElement = {
+ i: iceId++,
+ points,
+ type: "iceberg",
+ cellId,
+ size
+ };
if (transform) {
- pack.ice.icebergs.push({
- cellId,
- size,
- points,
- offset: parseTransform(transform)
- });
- } else {
- pack.ice.icebergs.push({
- cellId,
- size,
- points
- });
+ iceElement.offset = parseTransform(transform);
}
-
+ pack.ice.push(iceElement);
});
// Clear old SVG elements
diff --git a/public/modules/ice.js b/public/modules/ice.js
index d3d7ab36..e1e86b8e 100644
--- a/public/modules/ice.js
+++ b/public/modules/ice.js
@@ -2,17 +2,16 @@
// Ice layer data model - separates ice data from SVG rendering
window.Ice = (function () {
- // Initialize ice data structure
- function initialize() {
- pack.ice = {
- glaciers: [], // auto-generated glaciers on cold land
- icebergs: [] // manually edited and auto-generated icebergs on cold water
- };
+
+ // Find next available id for new ice element
+ function getNextId() {
+ if (pack.ice.length === 0) return 0;
+ return Math.max(...pack.ice.map(element => element.i)) + 1;
}
// Generate glaciers and icebergs based on temperature and height
function generate() {
- initialize();
+ clear();
const { cells, features } = grid;
const { temp, h } = cells;
Math.random = aleaPRNG(seed);
@@ -31,8 +30,10 @@ window.Ice = (function () {
if (isolines[type]?.polygons) {
isolines[type].polygons.forEach(points => {
const clipped = clipPoly(points);
- pack.ice.glaciers.push({
- points: clipped
+ pack.ice.push({
+ i: getNextId(),
+ points: clipped,
+ type: "glacier"
});
});
}
@@ -57,10 +58,12 @@ window.Ice = (function () {
rn(lerp(cy, y, size), 2)
]);
- pack.ice.icebergs.push({
+ pack.ice.push({
+ i: getNextId(),
+ points,
+ type: "iceberg",
cellId,
- size,
- points
+ size
});
}
}
@@ -71,44 +74,41 @@ window.Ice = (function () {
rn(lerp(cx, x, size), 2),
rn(lerp(cy, y, size), 2)
]);
- //here we use the lose equality to find the first undefined or empty or null slot
- const nextIndex = pack.ice.icebergs.findIndex(iceberg => iceberg == undefined);
- if (nextIndex !== -1) {
- pack.ice.icebergs[nextIndex] = {
- cellId,
- size,
- points
- };
- redrawIceberg(nextIndex);
- } else {
- pack.ice.icebergs.push({
- cellId,
- size,
- points
- });
- redrawIceberg(pack.ice.icebergs.length - 1);
+ const id = getNextId();
+ pack.ice.push({
+ i: id,
+ points,
+ type: "iceberg",
+ cellId,
+ size
+ });
+ redrawIceberg(id);
+ }
+
+ function removeIce(id) {
+ const index = pack.ice.findIndex(element => element.i === id);
+ if (index !== -1) {
+ const type = pack.ice.find(element => element.i === id).type;
+ pack.ice.splice(index, 1);
+ if (type === "glacier") {
+ redrawGlacier(id);
+ } else {
+ redrawIceberg(id);
+ }
+
}
}
- function removeIce(type, index) {
- if (type === "glacier" && pack.ice.glaciers[index]) {
- delete pack.ice.glaciers[index];
- redrawGlacier(index);
- } else if (type === "iceberg" && pack.ice.icebergs[index]) {
- delete pack.ice.icebergs[index];
- redrawIceberg(index);
+ function updateIceberg(id, points, size) {
+ const iceberg = pack.ice.find(element => element.i === id);
+ if (iceberg) {
+ iceberg.points = points;
+ iceberg.size = size;
}
}
- function updateIceberg(index, points, size) {
- if (pack.ice.icebergs[index]) {
- pack.ice.icebergs[index].points = points;
- pack.ice.icebergs[index].size = size;
- }
- }
-
- function randomizeIcebergShape(index) {
- const iceberg = pack.ice.icebergs[index];
+ function randomizeIcebergShape(id) {
+ const iceberg = pack.ice.find(element => element.i === id);
if (!iceberg) return;
const cellId = iceberg.cellId;
@@ -127,8 +127,8 @@ window.Ice = (function () {
iceberg.points = points;
}
- function changeIcebergSize(index, newSize) {
- const iceberg = pack.ice.icebergs[index];
+ function changeIcebergSize(id, newSize) {
+ const iceberg = pack.ice.find(element => element.i === id);
if (!iceberg) return;
const cellId = iceberg.cellId;
@@ -150,12 +150,10 @@ window.Ice = (function () {
// Clear all ice
function clear() {
- pack.ice.glaciers = [];
- pack.ice.icebergs = [];
+ pack.ice = [];
}
return {
- initialize,
generate,
addIceberg,
removeIce,
diff --git a/public/modules/io/load.js b/public/modules/io/load.js
index 371547ec..9b401733 100644
--- a/public/modules/io/load.js
+++ b/public/modules/io/load.js
@@ -406,7 +406,7 @@ async function parseLoadedData(data, mapVersion) {
pack.cells.province = data[27] ? Uint16Array.from(data[27].split(",")) : new Uint16Array(pack.cells.i.length);
// data[28] had deprecated cells.crossroad
pack.cells.routes = data[36] ? JSON.parse(data[36]) : {};
- pack.ice = data[39] ? JSON.parse(data[39]) : {glaciers: [], icebergs: []};
+ pack.ice = data[39] ? JSON.parse(data[39]) : [];
if (data[31]) {
const namesDL = data[31].split("/");
diff --git a/public/modules/io/save.js b/public/modules/io/save.js
index 33ded975..25cd7493 100644
--- a/public/modules/io/save.js
+++ b/public/modules/io/save.js
@@ -32,7 +32,7 @@ async function saveMap(method) {
$(this).dialog("close");
}
},
- position: {my: "center", at: "center", of: "svg"}
+ position: { my: "center", at: "center", of: "svg" }
});
}
}
@@ -90,8 +90,8 @@ function prepareMapData() {
const serializedSVG = new XMLSerializer().serializeToString(cloneEl);
- const {spacing, cellsX, cellsY, boundary, points, features, cellsDesired} = grid;
- const gridGeneral = JSON.stringify({spacing, cellsX, cellsY, boundary, points, features, cellsDesired});
+ const { spacing, cellsX, cellsY, boundary, points, features, cellsDesired } = grid;
+ const gridGeneral = JSON.stringify({ spacing, cellsX, cellsY, boundary, points, features, cellsDesired });
const packFeatures = JSON.stringify(pack.features);
const cultures = JSON.stringify(pack.cultures);
const states = JSON.stringify(pack.states);
@@ -103,10 +103,7 @@ function prepareMapData() {
const cellRoutes = JSON.stringify(pack.cells.routes);
const routes = JSON.stringify(pack.routes);
const zones = JSON.stringify(pack.zones);
-
- const icebergs = pack.ice.icebergs.filter(iceberg => iceberg !== undefined);
- const glaciers = pack.ice.glaciers.filter(glacier => glacier !== undefined);
- const ice = JSON.stringify({icebergs, glaciers});
+ const ice = JSON.stringify(pack.ice);
// store name array only if not the same as default
const defaultNB = Names.getNameBases();
@@ -168,14 +165,14 @@ function prepareMapData() {
// save map file to indexedDB
async function saveToStorage(mapData, showTip = false) {
- const blob = new Blob([mapData], {type: "text/plain"});
+ const blob = new Blob([mapData], { type: "text/plain" });
await ldb.set("lastMap", blob);
showTip && tip("Map is saved to the browser storage", false, "success");
}
// download map file
function saveToMachine(mapData, filename) {
- const blob = new Blob([mapData], {type: "text/plain"});
+ const blob = new Blob([mapData], { type: "text/plain" });
const URL = window.URL.createObjectURL(blob);
const link = document.createElement("a");
diff --git a/public/modules/renderers/draw-ice.js b/public/modules/renderers/draw-ice.js
index ede5d8fc..4b35f75c 100644
--- a/public/modules/renderers/draw-ice.js
+++ b/public/modules/renderers/draw-ice.js
@@ -9,14 +9,13 @@ function drawIce() {
let html = "";
- // Draw glaciers
- pack.ice.glaciers.forEach((glacier, index) => {
- html += getGlacierHtml(glacier, index);
- });
-
- // Draw icebergs
- pack.ice.icebergs.forEach((iceberg, index) => {
- html += getIcebergHtml(iceberg, index);
+ // Draw all ice elements
+ pack.ice.forEach(iceElement => {
+ if (iceElement.type === "glacier") {
+ html += getGlacierHtml(iceElement);
+ } else if (iceElement.type === "iceberg") {
+ html += getIcebergHtml(iceElement);
+ }
});
ice.html(html);
@@ -24,18 +23,18 @@ function drawIce() {
TIME && console.timeEnd("drawIce");
}
-function redrawIceberg(index) {
+function redrawIceberg(id) {
TIME && console.time("redrawIceberg");
- const iceberg = pack.ice.icebergs[index];
- let el = ice.selectAll(`polygon[data-index="${index}"]:not([type="glacier"])`);
+ const iceberg = pack.ice.find(element => element.i === id);
+ let el = ice.selectAll(`polygon[data-id="${id}"]:not([type="glacier"])`);
if (!iceberg && !el.empty()) {
el.remove();
} else {
if (el.empty()) {
// Create new element if it doesn't exist
- const polygon = getIcebergHtml(iceberg, index);
+ const polygon = getIcebergHtml(iceberg);
ice.node().insertAdjacentHTML("beforeend", polygon);
- el = ice.selectAll(`polygon[data-index="${index}"]:not([type="glacier"])`);
+ el = ice.selectAll(`polygon[data-id="${id}"]:not([type="glacier"])`);
}
el.attr("points", iceberg.points);
el.attr("transform", iceberg.offset ? `translate(${iceberg.offset[0]},${iceberg.offset[1]})` : null);
@@ -43,18 +42,18 @@ function redrawIceberg(index) {
TIME && console.timeEnd("redrawIceberg");
}
-function redrawGlacier(index) {
+function redrawGlacier(id) {
TIME && console.time("redrawGlacier");
- const glacier = pack.ice.glaciers[index];
- let el = ice.selectAll(`polygon[data-index="${index}"][type="glacier"]`);
+ const glacier = pack.ice.find(element => element.i === id);
+ let el = ice.selectAll(`polygon[data-id="${id}"][type="glacier"]`);
if (!glacier && !el.empty()) {
el.remove();
} else {
if (el.empty()) {
// Create new element if it doesn't exist
- const polygon = getGlacierHtml(glacier, index);
+ const polygon = getGlacierHtml(glacier);
ice.node().insertAdjacentHTML("beforeend", polygon);
- el = ice.selectAll(`polygon[data-index="${index}"][type="glacier"]`);
+ el = ice.selectAll(`polygon[data-id="${id}"][type="glacier"]`);
}
el.attr("points", glacier.points);
el.attr("transform", glacier.offset ? `translate(${glacier.offset[0]},${glacier.offset[1]})` : null);
@@ -62,10 +61,10 @@ function redrawGlacier(index) {
TIME && console.timeEnd("redrawGlacier");
}
-function getGlacierHtml(glacier, index) {
- return ``;
+function getGlacierHtml(glacier) {
+ return ``;
}
-function getIcebergHtml(iceberg, index) {
- return ``;
+function getIcebergHtml(iceberg) {
+ return ``;
}
\ No newline at end of file
diff --git a/public/modules/ui/ice-editor.js b/public/modules/ui/ice-editor.js
index 1a23e304..16818b4c 100644
--- a/public/modules/ui/ice-editor.js
+++ b/public/modules/ui/ice-editor.js
@@ -7,13 +7,14 @@ function editIce(element) {
if (!layerIsOn("toggleIce")) toggleIce();
elSelected = d3.select(d3.event.target);
- const index = +elSelected.attr("data-index");
+ const id = +elSelected.attr("data-id");
+ const iceElement = pack.ice.find(el => el.i === id);
const isGlacier = elSelected.attr("type") === "glacier";
const type = isGlacier ? "Glacier" : "Iceberg";
document.getElementById("iceRandomize").style.display = isGlacier ? "none" : "inline-block";
document.getElementById("iceSize").style.display = isGlacier ? "none" : "inline-block";
- if (!isGlacier) document.getElementById("iceSize").value = isGlacier ? "" : pack.ice.icebergs[index].size;
+ if (!isGlacier) document.getElementById("iceSize").value = iceElement?.size || "";
ice.selectAll("*").classed("draggable", true).call(d3.drag().on("drag", dragElement));
@@ -35,16 +36,16 @@ function editIce(element) {
function randomizeShape() {
- const idx = +elSelected.attr("data-index");
- Ice.randomizeIcebergShape(idx);
- redrawIceberg(idx);
+ const selectedId = +elSelected.attr("data-id");
+ Ice.randomizeIcebergShape(selectedId);
+ redrawIceberg(selectedId);
}
function changeSize() {
const newSize = +this.value;
- const idx = +elSelected.attr("data-index");
- Ice.changeIcebergSize(idx, newSize);
- redrawIceberg(idx);
+ const selectedId = +elSelected.attr("data-id");
+ Ice.changeIcebergSize(selectedId, newSize);
+ redrawIceberg(selectedId);
}
function toggleAdd() {
@@ -77,7 +78,7 @@ function editIce(element) {
buttons: {
Remove: function () {
$(this).dialog("close");
- Ice.removeIce(type.toLowerCase(), +elSelected.attr("data-index"));
+ Ice.removeIce(+elSelected.attr("data-id"));
$("#iceEditor").dialog("close");
},
Cancel: function () {
@@ -88,7 +89,7 @@ function editIce(element) {
}
function dragElement() {
- const idx = +elSelected.attr("data-index");
+ const selectedId = +elSelected.attr("data-id");
const initialTransform = parseTransform(this.getAttribute("transform"));
const dx = initialTransform[0] - d3.event.x;
const dy = initialTransform[1] - d3.event.y;
@@ -101,7 +102,7 @@ function editIce(element) {
// Update data model with new position
const offset = [dx + x, dy + y];
- const iceData = elSelected.attr("type") === "glacier" ? pack.ice.glaciers[idx] : pack.ice.icebergs[idx];
+ const iceData = pack.ice.find(element => element.i === selectedId);
if (iceData) {
// Store offset for visual positioning, actual geometry stays in points
iceData.offset = offset;