diff --git a/index.html b/index.html
index 9d8c9538..6efbd818 100644
--- a/index.html
+++ b/index.html
@@ -3555,9 +3555,9 @@
-
-
-
-
Select from the list or paste a Unicode character here:
-
-
. See Emojipedia for reference
+
+
Unicode emojis
+
+
Select from the list or paste a Unicode character here:
+
+
. See EmojiDB to search for emojis
+
+
+
+
+
+
External images
+
+ Paste link to the image here:
+
+
+
+
@@ -8087,8 +8100,8 @@
-
-
+
+
@@ -8106,8 +8119,8 @@
-
-
+
+
@@ -8134,13 +8147,13 @@
-
-
-
-
+
+
+
+
-
+
@@ -8149,18 +8162,18 @@
-
+
-
+
-
+
diff --git a/modules/dynamic/auto-update.js b/modules/dynamic/auto-update.js
index 10a9a375..afa91fca 100644
--- a/modules/dynamic/auto-update.js
+++ b/modules/dynamic/auto-update.js
@@ -977,4 +977,10 @@ export function resolveVersionConflicts(mapVersion) {
BurgsAndStates.getPoles();
Provinces.getPoles();
}
+
+ if (isOlderThan("1.107.0")) {
+ // v1.107.0 allowed custom images for markers and regiments
+ if (layerIsOn("toggleMarkers")) drawMarkers();
+ if (layerIsOn("toggleMilitary")) drawMilitary();
+ }
}
diff --git a/modules/io/load.js b/modules/io/load.js
index 8e05a798..0ec0b8b4 100644
--- a/modules/io/load.js
+++ b/modules/io/load.js
@@ -471,7 +471,7 @@ async function parseLoadedData(data, mapVersion) {
{
// dynamically import and run auto-update script
- const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.105.24");
+ const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.107.0");
resolveVersionConflicts(mapVersion);
}
diff --git a/modules/markers-generator.js b/modules/markers-generator.js
index 93db4368..367cdd5f 100644
--- a/modules/markers-generator.js
+++ b/modules/markers-generator.js
@@ -11,7 +11,7 @@ window.Markers = (function () {
/*
Default markers config:
type - short description (snake-case)
- icon - unicode character, make sure it's supported by most of the browsers. Source: emojipedia.org
+ icon - unicode character or url to image
dx: icon offset in x direction, in pixels
dy: icon offset in y direction, in pixels
min: minimum number of candidates to add at least 1 marker
diff --git a/modules/military-generator.js b/modules/military-generator.js
index 61224d69..5aea87db 100644
--- a/modules/military-generator.js
+++ b/modules/military-generator.js
@@ -380,7 +380,7 @@ window.Military = (function () {
: gauss(options.year - 100, 150, 1, options.year - 6);
const conflict = campaign ? ` during the ${campaign.name}` : "";
const legend = `Regiment was formed in ${year} ${options.era}${conflict}. ${station}${troops}`;
- notes.push({id: `regiment${s.i}-${r.i}`, name: `${r.icon} ${r.name}`, legend});
+ notes.push({id: `regiment${s.i}-${r.i}`, name: r.name, legend});
};
return {
diff --git a/modules/renderers/draw-markers.js b/modules/renderers/draw-markers.js
index 0f45f31f..d9d6b816 100644
--- a/modules/renderers/draw-markers.js
+++ b/modules/renderers/draw-markers.js
@@ -42,9 +42,12 @@ function drawMarker(marker, rescale = 1) {
const viewX = rn(x - zoomSize / 2, 1);
const viewY = rn(y - zoomSize, 1);
+ const isExternal = icon.startsWith("http");
+
return /* html */ `
`;
}
diff --git a/modules/renderers/draw-military.js b/modules/renderers/draw-military.js
index 2a5614e3..96ed52e4 100644
--- a/modules/renderers/draw-military.js
+++ b/modules/renderers/draw-military.js
@@ -54,7 +54,14 @@ const drawRegiments = function (regiments, s) {
.attr("class", "regimentIcon")
.attr("x", d => x(d) - size)
.attr("y", d => d.y)
- .text(d => d.icon);
+ .text(d => (d.icon.startsWith("http") ? "" : d.icon));
+ g.append("image")
+ .attr("class", "regimentImage")
+ .attr("x", d => x(d) - h)
+ .attr("y", d => y(d))
+ .attr("height", h)
+ .attr("width", h)
+ .attr("href", d => (d.icon.startsWith("http") ? d.icon : ""));
};
const drawRegiment = function (reg, stateId) {
@@ -95,7 +102,14 @@ const drawRegiment = function (reg, stateId) {
.attr("class", "regimentIcon")
.attr("x", x1 - size)
.attr("y", reg.y)
- .text(reg.icon);
+ .text(reg.icon.startsWith("http") ? "" : reg.icon);
+ g.append("image")
+ .attr("class", "regimentImage")
+ .attr("x", x1 - h)
+ .attr("y", y1)
+ .attr("height", h)
+ .attr("width", h)
+ .attr("href", reg.icon.startsWith("http") ? reg.icon : "");
};
// move one regiment to another
@@ -122,5 +136,13 @@ const moveRegiment = function (reg, x, y) {
el.select(".regimentIcon")
.transition(move)
.attr("x", x1(x) - size)
- .attr("y", y);
+ .attr("y", y)
+ .attr("height", "6")
+ .attr("width", "6");
+ el.select(".regimentImage")
+ .transition(move)
+ .attr("x", x1(x) - h)
+ .attr("y", y1(y))
+ .attr("height", "6")
+ .attr("width", "6");
};
diff --git a/modules/ui/editors.js b/modules/ui/editors.js
index 752593dd..c11166c6 100644
--- a/modules/ui/editors.js
+++ b/modules/ui/editors.js
@@ -1165,25 +1165,66 @@ function selectIcon(initial, callback) {
const cell = row.insertCell(i % 17);
cell.innerHTML = icons[i];
}
+
+ // find external images used as icons and show them
+ const externalResources = new Set();
+ const isExternal = url => url.startsWith("http");
+
+ options.military.forEach(unit => {
+ if (isExternal(unit.icon)) externalResources.add(unit.icon);
+ });
+
+ pack.states.forEach(state => {
+ state?.military?.forEach(regiment => {
+ if (isExternal(regiment.icon)) externalResources.add(regiment.icon);
+ });
+ });
+
+ externalResources.forEach(addExternalImage);
}
- input.oninput = e => callback(input.value);
+ input.oninput = () => callback(input.value);
+
table.onclick = e => {
if (e.target.tagName === "TD") {
input.value = e.target.textContent;
callback(input.value);
}
};
+
table.onmouseover = e => {
if (e.target.tagName === "TD") tip(`Click to select ${e.target.textContent} icon`);
};
+ function addExternalImage(url) {
+ const addedIcons = byId("addedIcons");
+ const image = document.createElement("div");
+ image.style.cssText = `width: 2.2em; height: 2.2em; background-size: cover; background-image: url(${url})`;
+ addedIcons.appendChild(image);
+ image.onclick = () => callback(ulr);
+ }
+
+ byId("addImage").onclick = function () {
+ const input = this.previousElementSibling;
+ const ulr = input.value;
+ if (!ulr) return tip("Enter image URL to add", false, "error", 4000);
+ if (!ulr.match(/^(http|https):\/\//)) return tip("Enter valid URL", false, "error", 4000);
+ addExternalImage(ulr);
+ callback(ulr);
+ input.value = "";
+ };
+
+ byId("addedIcons")
+ .querySelectorAll("div")
+ .forEach(div => {
+ div.onclick = () => callback(div.style.backgroundImage.slice(5, -2));
+ });
+
$("#iconSelector").dialog({
width: fitContent(),
title: "Select Icon",
buttons: {
Apply: function () {
- callback(input.value || "â €");
$(this).dialog("close");
},
Close: function () {
diff --git a/modules/ui/markers-editor.js b/modules/ui/markers-editor.js
index 26f035fa..2147e09b 100644
--- a/modules/ui/markers-editor.js
+++ b/modules/ui/markers-editor.js
@@ -8,25 +8,24 @@ function editMarker(markerI) {
elSelected = d3.select(element).raise().call(d3.drag().on("start", dragMarker)).classed("draggable", true);
- if (document.getElementById("notesEditor").offsetParent) editNotes(element.id, element.id);
+ if (byId("notesEditor").offsetParent) editNotes(element.id, element.id);
// dom elements
- const markerType = document.getElementById("markerType");
- const markerIcon = document.getElementById("markerIcon");
- const markerIconSelect = document.getElementById("markerIconSelect");
- const markerIconSize = document.getElementById("markerIconSize");
- const markerIconShiftX = document.getElementById("markerIconShiftX");
- const markerIconShiftY = document.getElementById("markerIconShiftY");
- const markerSize = document.getElementById("markerSize");
- const markerPin = document.getElementById("markerPin");
- const markerFill = document.getElementById("markerFill");
- const markerStroke = document.getElementById("markerStroke");
+ const markerType = byId("markerType");
+ const markerIconSelect = byId("markerIconSelect");
+ const markerIconSize = byId("markerIconSize");
+ const markerIconShiftX = byId("markerIconShiftX");
+ const markerIconShiftY = byId("markerIconShiftY");
+ const markerSize = byId("markerSize");
+ const markerPin = byId("markerPin");
+ const markerFill = byId("markerFill");
+ const markerStroke = byId("markerStroke");
- const markerNotes = document.getElementById("markerNotes");
- const markerLock = document.getElementById("markerLock");
- const addMarker = document.getElementById("addMarker");
- const markerAdd = document.getElementById("markerAdd");
- const markerRemove = document.getElementById("markerRemove");
+ const markerNotes = byId("markerNotes");
+ const markerLock = byId("markerLock");
+ const addMarker = byId("addMarker");
+ const markerAdd = byId("markerAdd");
+ const markerRemove = byId("markerRemove");
updateInputs();
@@ -39,8 +38,7 @@ function editMarker(markerI) {
const listeners = [
listen(markerType, "change", changeMarkerType),
- listen(markerIcon, "input", changeMarkerIcon),
- listen(markerIconSelect, "click", selectMarkerIcon),
+ listen(markerIconSelect, "click", changeMarkerIcon),
listen(markerIconSize, "input", changeIconSize),
listen(markerIconShiftX, "input", changeIconShiftX),
listen(markerIconShiftY, "input", changeIconShiftY),
@@ -61,7 +59,7 @@ function editMarker(markerI) {
return [element, marker];
}
- const element = document.getElementById(`marker${markerI}`);
+ const element = byId(`marker${markerI}`);
const marker = pack.markers.find(({i}) => i === markerI);
return [element, marker];
}
@@ -97,19 +95,20 @@ function editMarker(markerI) {
}
function updateInputs() {
- const {icon, type = "", size = 30, dx = 50, dy = 50, px = 12, stroke = "#000000", fill = "#ffffff", pin = "bubble", lock} = marker;
+ byId("markerIcon").innerHTML = marker.icon.startsWith("http")
+ ? `

`
+ : marker.icon;
- markerType.value = type;
- markerIcon.value = icon;
- markerIconSize.value = px;
- markerIconShiftX.value = dx;
- markerIconShiftY.value = dy;
- markerSize.value = size;
- markerPin.value = pin;
- markerFill.value = fill;
- markerStroke.value = stroke;
+ markerType.value = marker.type || "";
+ markerIconSize.value = marker.px || 12;
+ markerIconShiftX.value = marker.dx || 50;
+ markerIconShiftY.value = marker.dy || 50;
+ markerSize.value = marker.size || 30;
+ markerPin.value = marker.pin || "bubble";
+ markerFill.value = marker.fill || "#ffffff";
+ markerStroke.value = marker.stroke || "#000000";
- markerLock.className = lock ? "icon-lock" : "icon-lock-open";
+ markerLock.className = marker.lock ? "icon-lock" : "icon-lock-open";
}
function changeMarkerType() {
@@ -117,18 +116,12 @@ function editMarker(markerI) {
}
function changeMarkerIcon() {
- const icon = this.value;
- getSameTypeMarkers().forEach(marker => {
- marker.icon = icon;
- redrawIcon(marker);
- });
- }
+ selectIcon(marker.icon, value => {
+ const isExternal = value.startsWith("http");
+ byId("markerIcon").innerHTML = isExternal ? `

` : value;
- function selectMarkerIcon() {
- selectIcon(marker.icon, icon => {
- markerIcon.value = icon;
getSameTypeMarkers().forEach(marker => {
- marker.icon = icon;
+ marker.icon = value;
redrawIcon(marker);
});
});
@@ -165,7 +158,7 @@ function editMarker(markerI) {
getSameTypeMarkers().forEach(marker => {
marker.size = size;
const {i, x, y, hidden} = marker;
- const el = !hidden && document.getElementById(`marker${i}`);
+ const el = !hidden && byId(`marker${i}`);
if (!el) return;
const zoomedSize = rescale ? Math.max(rn(size / 5 + 24 / scale, 2), 1) : size;
@@ -201,12 +194,23 @@ function editMarker(markerI) {
}
function redrawIcon({i, hidden, icon, dx = 50, dy = 50, px = 12}) {
- const iconElement = !hidden && document.querySelector(`#marker${i} > text`);
- if (iconElement) {
- iconElement.innerHTML = icon;
- iconElement.setAttribute("x", dx + "%");
- iconElement.setAttribute("y", dy + "%");
- iconElement.setAttribute("font-size", px + "px");
+ const isExternal = icon.startsWith("http");
+
+ const iconText = !hidden && document.querySelector(`#marker${i} > text`);
+ if (iconText) {
+ iconText.innerHTML = isExternal ? "" : icon;
+ iconText.setAttribute("x", dx + "%");
+ iconText.setAttribute("y", dy + "%");
+ iconText.setAttribute("font-size", px + "px");
+ }
+
+ const iconImage = !hidden && document.querySelector(`#marker${i} > image`);
+ if (iconImage) {
+ iconImage.setAttribute("x", dx / 2 + "%");
+ iconImage.setAttribute("y", dy / 2 + "%");
+ iconImage.setAttribute("width", px + "px");
+ iconImage.setAttribute("height", px + "px");
+ iconImage.setAttribute("href", isExternal ? icon : "");
}
}
@@ -241,10 +245,10 @@ function editMarker(markerI) {
}
function deleteMarker() {
- Markers.deleteMarker(marker.i)
+ Markers.deleteMarker(marker.i);
element.remove();
$("#markerEditor").dialog("close");
- if (document.getElementById("markersOverviewRefresh").offsetParent) markersOverviewRefresh.click();
+ if (byId("markersOverviewRefresh").offsetParent) markersOverviewRefresh.click();
}
function closeMarkerEditor() {
diff --git a/modules/ui/markers-overview.js b/modules/ui/markers-overview.js
index af0cc11f..4980dd9b 100644
--- a/modules/ui/markers-overview.js
+++ b/modules/ui/markers-overview.js
@@ -69,18 +69,24 @@ function overviewMarkers() {
function addLines() {
const lines = pack.markers
.map(({i, type, icon, pinned, lock}) => {
- return `
-
${icon} ${type}
-
-
-
-
-
-
`;
+ return /* html */ `
+
+ ${
+ icon.startsWith("http")
+ ? `

`
+ : `
${icon}`
+ }
+
${type}
+
+
+
+
+
+
`;
})
.join("");
diff --git a/modules/ui/military-overview.js b/modules/ui/military-overview.js
index 2382cb27..2533f1c5 100644
--- a/modules/ui/military-overview.js
+++ b/modules/ui/military-overview.js
@@ -284,7 +284,14 @@ function overviewMilitary() {
if (el.tagName !== "BUTTON") return;
const type = el.dataset.type;
- if (type === "icon") return selectIcon(el.textContent, v => (el.textContent = v));
+ if (type === "icon") {
+ return selectIcon(el.textContent, function (value) {
+ el.innerHTML = value.startsWith("http")
+ ? `

`
+ : value;
+ });
+ }
+
if (type === "biomes") {
const {i, name, color} = biomesData;
const biomesArray = Array(i.length).fill(null);
@@ -329,9 +336,15 @@ function overviewMilitary() {
${getLimitText(unit[attr])}
`;
- row.innerHTML = /* html */ `
|
+ row.innerHTML = /* html */ `
+
+ |
|
${getLimitButton("biomes")} |
${getLimitButton("states")} |
@@ -424,7 +437,11 @@ function overviewMilitary() {
const [icon, name, biomes, states, cultures, religions, rural, urban, crew, power, type, separate] =
elements.map(el => {
const {type, value} = el.dataset || {};
- if (type === "icon") return el.textContent || "â €";
+ if (type === "icon") {
+ const value = el.innerHTML.trim();
+ const isImage = value.startsWith("
![]()
parseInt(v)) : null;
if (el.type === "number") return +el.value || 0;
if (el.type === "checkbox") return +el.checked || 0;
diff --git a/modules/ui/regiment-editor.js b/modules/ui/regiment-editor.js
index 707aff2b..6a677923 100644
--- a/modules/ui/regiment-editor.js
+++ b/modules/ui/regiment-editor.js
@@ -24,18 +24,17 @@ function editRegiment(selector) {
modules.editRegiment = true;
// add listeners
- document.getElementById("regimentNameRestore").addEventListener("click", restoreName);
- document.getElementById("regimentType").addEventListener("click", changeType);
- document.getElementById("regimentName").addEventListener("change", changeName);
- document.getElementById("regimentEmblem").addEventListener("input", changeEmblem);
- document.getElementById("regimentEmblemSelect").addEventListener("click", selectEmblem);
- document.getElementById("regimentAttack").addEventListener("click", toggleAttack);
- document.getElementById("regimentRegenerateLegend").addEventListener("click", regenerateLegend);
- document.getElementById("regimentLegend").addEventListener("click", editLegend);
- document.getElementById("regimentSplit").addEventListener("click", splitRegiment);
- document.getElementById("regimentAdd").addEventListener("click", toggleAdd);
- document.getElementById("regimentAttach").addEventListener("click", toggleAttach);
- document.getElementById("regimentRemove").addEventListener("click", removeRegiment);
+ byId("regimentNameRestore").addEventListener("click", restoreName);
+ byId("regimentType").addEventListener("click", changeType);
+ byId("regimentName").addEventListener("change", changeName);
+ byId("regimentEmblemChange").addEventListener("click", changeEmblem);
+ byId("regimentAttack").addEventListener("click", toggleAttack);
+ byId("regimentRegenerateLegend").addEventListener("click", regenerateLegend);
+ byId("regimentLegend").addEventListener("click", editLegend);
+ byId("regimentSplit").addEventListener("click", splitRegiment);
+ byId("regimentAdd").addEventListener("click", toggleAdd);
+ byId("regimentAttach").addEventListener("click", toggleAttach);
+ byId("regimentRemove").addEventListener("click", removeRegiment);
// get regiment data element
function getRegiment() {
@@ -43,11 +42,13 @@ function editRegiment(selector) {
}
function updateRegimentData(regiment) {
- document.getElementById("regimentType").className = regiment.n ? "icon-anchor" : "icon-users";
- document.getElementById("regimentName").value = regiment.name;
- document.getElementById("regimentEmblem").value = regiment.icon;
- const composition = document.getElementById("regimentComposition");
+ byId("regimentType").className = regiment.n ? "icon-anchor" : "icon-users";
+ byId("regimentName").value = regiment.name;
+ byId("regimentEmblem").innerHTML = regiment.icon.startsWith("http")
+ ? `

`
+ : regiment.icon;
+ const composition = byId("regimentComposition");
composition.innerHTML = options.military
.map(u => {
return `
@@ -126,12 +127,13 @@ function editRegiment(selector) {
function changeType() {
const reg = getRegiment();
reg.n = +!reg.n;
- document.getElementById("regimentType").className = reg.n ? "icon-anchor" : "icon-users";
+ byId("regimentType").className = reg.n ? "icon-anchor" : "icon-users";
const size = +armies.attr("box-size");
const baseRect = elSelected.querySelectorAll("rect")[0];
const iconRect = elSelected.querySelectorAll("rect")[1];
const icon = elSelected.querySelector(".regimentIcon");
+ const image = elSelected.querySelector(".regimentIcon");
const x = reg.n ? reg.x - size * 2 : reg.x - size * 3;
baseRect.setAttribute("x", x);
baseRect.setAttribute("width", reg.n ? size * 4 : size * 6);
@@ -148,19 +150,19 @@ function editRegiment(selector) {
const reg = getRegiment(),
regs = pack.states[elSelected.dataset.state].military;
const name = Military.getName(reg, regs);
- elSelected.dataset.name = reg.name = document.getElementById("regimentName").value = name;
- }
-
- function selectEmblem() {
- selectIcon(regimentEmblem.value, v => {
- regimentEmblem.value = v;
- changeEmblem();
- });
+ elSelected.dataset.name = reg.name = byId("regimentName").value = name;
}
function changeEmblem() {
- const emblem = document.getElementById("regimentEmblem").value;
- getRegiment().icon = elSelected.querySelector(".regimentIcon").innerHTML = emblem;
+ const regiment = getRegiment();
+
+ selectIcon(regiment.icon, value => {
+ regiment.icon = value;
+ const isExternal = value.startsWith("http");
+ byId("regimentEmblem").innerHTML = isExternal ? `

` : value;
+ elSelected.querySelector(".regimentIcon").innerHTML = isExternal ? "" : value;
+ elSelected.querySelector(".regimentImage").setAttribute("href", isExternal ? value : "");
+ });
}
function changeUnit() {
@@ -224,8 +226,8 @@ function editRegiment(selector) {
}
function toggleAdd() {
- document.getElementById("regimentAdd").classList.toggle("pressed");
- if (document.getElementById("regimentAdd").classList.contains("pressed")) {
+ byId("regimentAdd").classList.toggle("pressed");
+ if (byId("regimentAdd").classList.contains("pressed")) {
viewbox.style("cursor", "crosshair").on("click", addRegimentOnClick);
tip("Click on map to create new regiment or fleet", true);
} else {
@@ -252,8 +254,8 @@ function editRegiment(selector) {
}
function toggleAttack() {
- document.getElementById("regimentAttack").classList.toggle("pressed");
- if (document.getElementById("regimentAttack").classList.contains("pressed")) {
+ byId("regimentAttack").classList.toggle("pressed");
+ if (byId("regimentAttack").classList.contains("pressed")) {
viewbox.style("cursor", "crosshair").on("click", attackRegimentOnClick);
tip("Click on another regiment to initiate battle", true);
armies.selectAll(":scope > g").classed("draggable", false);
@@ -324,8 +326,8 @@ function editRegiment(selector) {
}
function toggleAttach() {
- document.getElementById("regimentAttach").classList.toggle("pressed");
- if (document.getElementById("regimentAttach").classList.contains("pressed")) {
+ byId("regimentAttach").classList.toggle("pressed");
+ if (byId("regimentAttach").classList.contains("pressed")) {
viewbox.style("cursor", "crosshair").on("click", attachRegimentOnClick);
tip("Click on another regiment to unite both regiments. The current regiment will be removed", true);
armies.selectAll(":scope > g").classed("draggable", false);
@@ -427,6 +429,7 @@ function editRegiment(selector) {
const text = this.querySelector("text");
const iconRect = this.querySelectorAll("rect")[1];
const icon = this.querySelector(".regimentIcon");
+ const image = this.querySelector(".regimentImage");
const self = elSelected === this;
const baseLine = viewbox.select("g#regimentBase > line");
@@ -448,6 +451,8 @@ function editRegiment(selector) {
iconRect.setAttribute("y", y1);
icon.setAttribute("x", x1 - size);
icon.setAttribute("y", y);
+ image.setAttribute("x", x1 - h);
+ image.setAttribute("y", y1);
if (self) {
baseLine.attr("x2", x).attr("y2", y);
rotationControl
@@ -479,9 +484,9 @@ function editRegiment(selector) {
viewbox.selectAll("g#regimentBase").remove();
armies.selectAll(":scope > g").classed("draggable", false);
armies.selectAll("g>g").call(d3.drag().on("drag", null));
- document.getElementById("regimentAdd").classList.remove("pressed");
- document.getElementById("regimentAttack").classList.remove("pressed");
- document.getElementById("regimentAttach").classList.remove("pressed");
+ byId("regimentAdd").classList.remove("pressed");
+ byId("regimentAttack").classList.remove("pressed");
+ byId("regimentAttach").classList.remove("pressed");
restoreDefaultEvents();
elSelected = null;
}
diff --git a/modules/ui/regiments-overview.js b/modules/ui/regiments-overview.js
index fee7c480..848458b9 100644
--- a/modules/ui/regiments-overview.js
+++ b/modules/ui/regiments-overview.js
@@ -67,14 +67,24 @@ function overviewRegiments(state) {
)
.join(" ");
- lines += /* html */ `
+ lines += /* html */ `
-
${r.icon}
+ ${
+ r.icon.startsWith("http")
+ ? `

`
+ : `
${r.icon}`
+ }
${lineData}
-
${r.a}
-
+
${
+ r.a
+ }
+
`;
regiments.push(r);
diff --git a/modules/ui/tools.js b/modules/ui/tools.js
index 5c67ca0f..359842ad 100644
--- a/modules/ui/tools.js
+++ b/modules/ui/tools.js
@@ -860,33 +860,47 @@ function configMarkersGeneration() {
drawConfigTable();
function drawConfigTable() {
- const {markers} = pack;
const config = Markers.getConfig();
- const headers = `
+
+ const headers = /* html */ `
| Type |
Icon |
Multiplier |
Number |
`;
- const lines = config.map(({type, icon, multiplier}, index) => {
- const inputId = `markerIconInput${index}`;
- return `
- |
+
+ const lines = config.map(({type, icon, multiplier}) => {
+ const isExternal = icon.startsWith("http");
+
+ return /* html */ `
+ |
-
-
+
+ ${isExternal ? "" : icon}
+
|
- |
- ${markers.filter(marker => marker.type === type).length} |
+ |
+ ${pack.markers.filter(marker => marker.type === type).length} |
`;
});
+
const table = `${headers}${lines.join("")}
`;
alertMessage.innerHTML = table;
- alertMessage.querySelectorAll("i").forEach(selectIconButton => {
+ alertMessage.querySelectorAll("button.changeIcon").forEach(selectIconButton => {
selectIconButton.addEventListener("click", function () {
- const input = this.previousElementSibling;
- selectIcon(input.value, icon => (input.value = icon));
+ const image = this.parentElement.querySelector(".image");
+ const emoji = this.parentElement.querySelector(".emoji");
+ const icon = image.getAttribute("src") || emoji.textContent;
+
+ selectIcon(icon, value => {
+ const isExternal = value.startsWith("http");
+ image.setAttribute("src", isExternal ? value : "");
+ image.hidden = !isExternal;
+ emoji.textContent = isExternal ? "" : value;
+ });
});
});
}
@@ -894,12 +908,14 @@ function configMarkersGeneration() {
const applyChanges = () => {
const rows = alertMessage.querySelectorAll("tbody > tr");
const rowsData = Array.from(rows).map(row => {
- const inputs = row.querySelectorAll("input");
- return {
- type: inputs[0].value,
- icon: inputs[1].value,
- multiplier: parseFloat(inputs[2].value)
- };
+ const type = row.querySelector(".type").value;
+
+ const image = row.querySelector(".image");
+ const emoji = row.querySelector(".emoji");
+ const icon = image.getAttribute("src") || emoji.textContent;
+
+ const multiplier = parseFloat(row.querySelector(".multiplier").value);
+ return {type, icon, multiplier};
});
const config = Markers.getConfig();
diff --git a/versioning.js b/versioning.js
index e12cea06..5dcbb6a6 100644
--- a/versioning.js
+++ b/versioning.js
@@ -13,7 +13,7 @@
* Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2
*/
-const VERSION = "1.106.7";
+const VERSION = "1.107.0";
if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function");
{
@@ -37,6 +37,7 @@ if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format o
Latest changes:
+ - Ability to set custom image as Marker or Regiment icon
- Submap and Transform tools rework
- Azgaar Bot to answer questions and provide help
- Labels: ability to set letter spacing