v1.5.04 - smarter coa generation, coa download

This commit is contained in:
Azgaar 2021-01-31 15:29:25 +03:00
parent 32c4566aa7
commit 3aaddcf1a7
7 changed files with 294 additions and 88 deletions

View file

@ -1573,12 +1573,17 @@ rect.fillRect {
} }
#emblemBody .label { #emblemBody .label {
width: 5.5em; width: 6em;
display: inline-block; display: inline-block;
} }
#emblemBody select { #emblemBody select {
width: 8em; width: 9em;
}
#emblemsBottom {
margin-top: 4px;
} }
#picker text { #picker text {

View file

@ -37,7 +37,7 @@
<link rel="stylesheet" href="libs/jquery-ui.css"> <link rel="stylesheet" href="libs/jquery-ui.css">
</head> </head>
<body> <body>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="map" width="100%" height="100%"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="map" width="100%" height="100%">
<defs> <defs>
<g id="filters"> <g id="filters">
<filter id="blurFilter" x="-1" y="-1" width="100" height="100"> <filter id="blurFilter" x="-1" y="-1" width="100" height="100">
@ -1745,27 +1745,38 @@
<td>Emblem shape</td> <td>Emblem shape</td>
<td> <td>
<select id="emblemShape" data-stored="emblemShape"> <select id="emblemShape" data-stored="emblemShape">
<optgroup label="Diversiform">
<option value="culture" selected>Culture-specific</option> <option value="culture" selected>Culture-specific</option>
<option value="random">Culture-random</option> <option value="random">Culture-random</option>
<option value="state">State-specific</option> <option value="state">State-specific</option>
</optgroup>
<optgroup label="Basic">
<option value="heater">Heater</option> <option value="heater">Heater</option>
<option value="spanish">Spanish</option> <option value="spanish">Spanish</option>
<option value="french">French</option> <option value="french">French</option>
</optgroup>
<optgroup label="Regional">
<option value="horsehead">Horsehead</option> <option value="horsehead">Horsehead</option>
<option value="horsehead2">Horsehead Edgy</option> <option value="horsehead2">Horsehead Edgy</option>
<option value="polish">Polish</option> <option value="polish">Polish</option>
<option value="hessen">Hessen</option> <option value="hessen">Hessen</option>
<option value="swiss">Swiss</option> <option value="swiss">Swiss</option>
</optgroup>
<optgroup label="Historical">
<option value="boeotian">Boeotian</option> <option value="boeotian">Boeotian</option>
<option value="roman">Roman</option> <option value="roman">Roman</option>
<option value="kite">Kite</option> <option value="kite">Kite</option>
<option value="oldFrench">Old French</option> <option value="oldFrench">Old French</option>
<option value="renaissance">Renaissance</option> <option value="renaissance">Renaissance</option>
<option value="baroque">Baroque</option> <option value="baroque">Baroque</option>
</optgroup>
<optgroup label="Specific">
<option value="targe">Targe</option> <option value="targe">Targe</option>
<option value="targe2">Targe2</option> <option value="targe2">Targe2</option>
<option value="pavise">Pavise</option> <option value="pavise">Pavise</option>
<option value="wedged">Wedged</option> <option value="wedged">Wedged</option>
</optgroup>
<optgroup label="Banner">
<option value="flag">Flag</option> <option value="flag">Flag</option>
<option value="pennon">Pennon</option> <option value="pennon">Pennon</option>
<option value="guidon">Guidon</option> <option value="guidon">Guidon</option>
@ -1773,16 +1784,22 @@
<option value="dovetail">Dovetail</option> <option value="dovetail">Dovetail</option>
<option value="gonfalon">Gonfalon</option> <option value="gonfalon">Gonfalon</option>
<option value="pennant">Pennant</option> <option value="pennant">Pennant</option>
</optgroup>
<optgroup label="Simple">
<option value="round">Round</option> <option value="round">Round</option>
<option value="oval">Oval</option> <option value="oval">Oval</option>
<option value="vesicaPiscis">Vesica Piscis</option> <option value="vesicaPiscis">Vesica Piscis</option>
<option value="square">Square</option> <option value="square">Square</option>
<option value="diamond">Diamond</option> <option value="diamond">Diamond</option>
</optgroup>
<optgroup label="Fantasy">
<option value="fantasy1">Fantasy1</option> <option value="fantasy1">Fantasy1</option>
<option value="fantasy2">Fantasy2</option> <option value="fantasy2">Fantasy2</option>
<option value="fantasy3">Fantasy3</option> <option value="fantasy3">Fantasy3</option>
<option value="fantasy4">Fantasy4</option> <option value="fantasy4">Fantasy4</option>
<option value="fantasy5">Fantasy5</option> <option value="fantasy5">Fantasy5</option>
</optgroup>
<optgroup label="Middle Earth">
<option value="noldor">Noldor</option> <option value="noldor">Noldor</option>
<option value="gondor">Gondor</option> <option value="gondor">Gondor</option>
<option value="easterling">Easterling</option> <option value="easterling">Easterling</option>
@ -1790,6 +1807,7 @@
<option value="ironHills">Iron Hills</option> <option value="ironHills">Iron Hills</option>
<option value="urukHai">UrukHai</option> <option value="urukHai">UrukHai</option>
<option value="moriaOrc">Moria Orc</option> <option value="moriaOrc">Moria Orc</option>
</optgroup>
</select> </select>
</td> </td>
<td> <td>
@ -3337,8 +3355,77 @@
<div class="label">Burg:</div> <div class="label">Burg:</div>
<select id="emblemBurgs"></select> <select id="emblemBurgs"></select>
</div> </div>
<hr/>
<div data-tip="Select shape of the emblem">
<div class="label">Shape:</div>
<select id="emblemShapeSelector">
<optgroup label="Basic">
<option value="heater">Heater</option>
<option value="spanish">Spanish</option>
<option value="french">French</option>
</optgroup>
<optgroup label="Regional">
<option value="horsehead">Horsehead</option>
<option value="horsehead2">Horsehead Edgy</option>
<option value="polish">Polish</option>
<option value="hessen">Hessen</option>
<option value="swiss">Swiss</option>
</optgroup>
<optgroup label="Historical">
<option value="boeotian">Boeotian</option>
<option value="roman">Roman</option>
<option value="kite">Kite</option>
<option value="oldFrench">Old French</option>
<option value="renaissance">Renaissance</option>
<option value="baroque">Baroque</option>
</optgroup>
<optgroup label="Specific">
<option value="targe">Targe</option>
<option value="targe2">Targe2</option>
<option value="pavise">Pavise</option>
<option value="wedged">Wedged</option>
</optgroup>
<optgroup label="Banner">
<option value="flag">Flag</option>
<option value="pennon">Pennon</option>
<option value="guidon">Guidon</option>
<option value="banner">Banner</option>
<option value="dovetail">Dovetail</option>
<option value="gonfalon">Gonfalon</option>
<option value="pennant">Pennant</option>
</optgroup>
<optgroup label="Simple">
<option value="round">Round</option>
<option value="oval">Oval</option>
<option value="vesicaPiscis">Vesica Piscis</option>
<option value="square">Square</option>
<option value="diamond">Diamond</option>
</optgroup>
<optgroup label="Fantasy">
<option value="fantasy1">Fantasy1</option>
<option value="fantasy2">Fantasy2</option>
<option value="fantasy3">Fantasy3</option>
<option value="fantasy4">Fantasy4</option>
<option value="fantasy5">Fantasy5</option>
</optgroup>
<optgroup label="Middle Earth">
<option value="noldor">Noldor</option>
<option value="gondor">Gondor</option>
<option value="easterling">Easterling</option>
<option value="erebor">Erebor</option>
<option value="ironHills">Iron Hills</option>
<option value="urukHai">UrukHai</option>
<option value="moriaOrc">Moria Orc</option>
</optgroup>
</select>
</div>
</div> </div>
<div id="emblemsBottom"> <div id="emblemsBottom">
<button id="emblemsRegenerate" data-tip="Regenerate emblem" class="icon-shuffle"></button>
<button id="emblemsArmoria" data-tip="Edit the emblem in Armoria: our dedicated rich heraldry editor" class="icon-brush"></button>
<button id="emblemsUpload" data-tip="Upload png, jpg or svg image from Armoria or other sources as emblem" class="icon-upload"></button>
<button id="emblemsDownload" data-tip="Download emblem as png image" class="icon-download"></button>
<button id="emblemsGallery" data-tip="Download emblems gallery as html table (open in browser)" class="icon-layer-group"></button>
<button id="emblemsFocus" data-tip="Show emblem associated area or place" class="icon-target"></button> <button id="emblemsFocus" data-tip="Show emblem associated area or place" class="icon-target"></button>
</div> </div>
</div> </div>
@ -3956,7 +4043,7 @@
</template> </template>
<template id="vairInPale"> <template id="vairInPale">
<pattern id="{id}" width=.125 height=.125 viewBox="0 0 25 25"> <pattern id="{id}" width=.125 height=.125 viewBox="0 0 25 25">
<rect x=0 y=0 width="100%" height="100%" fill="{c2}"/> <rect x=0 y=0 width=25 height=25 fill="{c2}"/>
<path d="m12.5,0 l6.25,6.25 v12.5 l6.25,6.25 h-25 l6.25,-6.25 v-12.5 z" fill="{c1}" stroke="#000" stroke-width=".2"/> <path d="m12.5,0 l6.25,6.25 v12.5 l6.25,6.25 h-25 l6.25,-6.25 v-12.5 z" fill="{c1}" stroke="#000" stroke-width=".2"/>
</pattern> </pattern>
</template> </template>

View file

@ -186,8 +186,14 @@
if (cells.r[i]%2) b.y = rn(b.y + shift, 2); else b.y = rn(b.y - shift, 2); if (cells.r[i]%2) b.y = rn(b.y + shift, 2); else b.y = rn(b.y - shift, 2);
} }
const stateCOA = pack.states[b.state].coa; // define emblem
b.coa = COA.generate(stateCOA); const state = pack.states[b.state];
const stateCOA = state.coa;
let kinship = .25;
if (b.capital) kinship += .1;
else if (b.port) kinship -= .1;
if (b.culture !== state.culture) kinship -= .25;
b.coa = COA.generate(stateCOA, kinship);
b.coa.shield = getShield(b.culture, b.state); b.coa.shield = getShield(b.culture, b.state);
} }
@ -949,7 +955,8 @@
form[formName] += 5; form[formName] += 5;
const fullName = name + " " + formName; const fullName = name + " " + formName;
const color = getMixedColor(s.color); const color = getMixedColor(s.color);
const coa = COA.generate(stateBurgs[i].coa); const kinship = nameByBurg ? .8 : .4;
const coa = COA.generate(stateBurgs[i].coa, kinship);
coa.shield = getShield(c, s.i); coa.shield = getShield(c, s.i);
provinces.push({i:province, state:s.i, center, burg, name, formName, fullName, color, coa}); provinces.push({i:province, state:s.i, center, burg, name, formName, fullName, color, coa});
} }
@ -1045,7 +1052,9 @@
const formName = singleIsle ? "Island" : isleGroup ? "Islands" : colony ? "Colony" : rw(forms["Wild"]); const formName = singleIsle ? "Island" : isleGroup ? "Islands" : colony ? "Colony" : rw(forms["Wild"]);
const fullName = name + " " + formName; const fullName = name + " " + formName;
const color = getMixedColor(s.color); const color = getMixedColor(s.color);
const coa = COA.generate(s.coa); const dominion = colony ? P(.95) : singleIsle || isleGroup ? P(.7) : P(.3);
const kinship = dominion ? 0 : .4;
const coa = COA.generate(s.coa, kinship, dominion);
coa.shield = getShield(c, s.i); coa.shield = getShield(c, s.i);
provinces.push({i:province, state:s.i, center, burg, name, formName, fullName, color, coa}); provinces.push({i:province, state:s.i, center, burg, name, formName, fullName, color, coa});
s.provinces.push(province); s.provinces.push(province);

View file

@ -101,7 +101,7 @@
crossParted: { e: 5, ee: 1 }, crossParted: { e: 5, ee: 1 },
saltire: { ee: 5, jlemo: 1 }, saltire: { ee: 5, jlemo: 1 },
saltireParted: { e: 5, ee: 1 }, saltireParted: { e: 5, ee: 1 },
pall: { ee: 1, acez: 5, jlhh: 3 }, pall: { ee: 1, jleh: 5, jlhh: 3 },
pallReversed: { ee: 1, bemo: 5 }, pallReversed: { ee: 1, bemo: 5 },
pile: { bbb: 1 }, pile: { bbb: 1 },
pileInBend: { eeee: 1, eeoo: 1 }, pileInBend: { eeee: 1, eeoo: 1 },
@ -190,7 +190,7 @@
} }
}; };
const generate = function(parent) { const generate = function(parent, kinship, dominion) {
let usedPattern = null, usedTinctures = []; let usedPattern = null, usedTinctures = [];
// TODO // TODO
@ -207,17 +207,19 @@
// style settings for emblems layer // style settings for emblems layer
// fix download svg/png // fix download svg/png
// test in FF // test in FF
// generate all?
// layout preset
const t1 = parent && P(.3) ? parent.t1 : getTincture("field"); const t1 = P(kinship) ? parent.t1 : getTincture("field");
const coa = {t1}; const coa = {t1};
let charge = P(usedPattern ? .5 : .93) ? true : false; // 80% for charge let charge = P(usedPattern ? .5 : .93) ? true : false; // 80% for charge
const linedOrdinary = charge && P(.3) || P(.5) ? parent?.ordinaries && P(.3) ? parent.ordinaries[0].ordinary : rw(ordinaries.lined) : null; const linedOrdinary = charge && P(.3) || P(.5) ? parent?.ordinaries && P(kinship) ? parent.ordinaries[0].ordinary : rw(ordinaries.lined) : null;
const ordinary = !charge && P(.65) || P(.3) ? linedOrdinary ? linedOrdinary : rw(ordinaries.straight) : null; // 36% for ordinary const ordinary = !charge && P(.65) || P(.3) ? linedOrdinary ? linedOrdinary : rw(ordinaries.straight) : null; // 36% for ordinary
const rareDivided = ["chief", "terrace", "chevron", "quarter", "flaunches"].includes(ordinary); const rareDivided = ["chief", "terrace", "chevron", "quarter", "flaunches"].includes(ordinary);
const divisioned = rareDivided ? P(.03) : charge && ordinary ? P(.03) : charge ? P(.3) : ordinary ? P(.7) : P(.995); // 33% for division const divisioned = rareDivided ? P(.03) : charge && ordinary ? P(.03) : charge ? P(.3) : ordinary ? P(.7) : P(.995); // 33% for division
const division = divisioned ? parent?.division && P(.2) ? parent.division.division : rw(divisions.variants) : null; const division = divisioned ? parent?.division && P(kinship - .1) ? parent.division.division : rw(divisions.variants) : null;
if (charge) charge = parent?.charges && P(.2) ? parent.charges[0].charge : selectCharge(); if (charge) charge = parent?.charges && P(kinship - .1) ? parent.charges[0].charge : selectCharge();
if (division) { if (division) {
const t = getTincture("division", usedTinctures, P(.98) ? coa.t1 : null); const t = getTincture("division", usedTinctures, P(.98) ? coa.t1 : null);
@ -335,6 +337,32 @@
} }
} }
// dominions have canton with parent coa
if (P(dominion)) {
const t = getType(parent.t1) === getType(coa.t1) ? getTincture("division", usedTinctures, coa.t1) : parent.t1;
const canton = {ordinary: "canton", t};
if (coa.charges) {
coa.charges.forEach((charge, i) => {
if (charge.p.includes("a")) charge.p = charge.p.replaceAll("a", "");
if (charge.p.includes("j")) charge.p = charge.p.replaceAll("j", "");
if (charge.p.includes("y")) charge.p = charge.p.replaceAll("y", "");
if (!charge.p) coa.charges.splice(i, 1);
});
}
if (parent.charges) {
let charge = parent.charges[0].charge;
if (charge === "inescutcheon" && parent.charges[1]) charge = parent.charges[1].charge;
let t2 = parent.charges[0].t;
if (getType(t) === getType(t2)) t2 = getTincture("charge", usedTinctures, t);
if (!coa.charges) coa.charges = [];
coa.charges.push({charge, t: t2, p: "y", size: 0.5});
} else canton.above = 1;
coa.ordinaries ? coa.ordinaries.push(canton) : coa.ordinaries = [canton];
}
function selectCharge(set) { function selectCharge(set) {
const type = set ? rw(set) : ordinary || divisioned ? rw(charges.types): rw(charges.single); const type = set ? rw(set) : ordinary || divisioned ? rw(charges.types): rw(charges.single);
return type === "inescutcheon" ? "inescutcheon" : rw(charges[type]); return type === "inescutcheon" ? "inescutcheon" : rw(charges[type]);
@ -366,7 +394,6 @@
if (Object.keys(tinctures.metals).includes(tincture)) return "metals"; if (Object.keys(tinctures.metals).includes(tincture)) return "metals";
if (Object.keys(tinctures.colours).includes(tincture)) return "colours"; if (Object.keys(tinctures.colours).includes(tincture)) return "colours";
if (Object.keys(tinctures.stains).includes(tincture)) return "stains"; if (Object.keys(tinctures.stains).includes(tincture)) return "stains";
debugger; // exception
} }
function definePattern(pattern, element, size = "") { function definePattern(pattern, element, size = "") {

View file

@ -545,9 +545,7 @@ function unfog(id) {
} }
function getFileName(dataType) { function getFileName(dataType) {
const formatTime = (time) => { const formatTime = time => time < 10 ? "0" + time : time;
return (time < 10) ? "0" + time : time;
};
const name = mapName.value; const name = mapName.value;
const type = dataType ? dataType + " " : ""; const type = dataType ? dataType + " " : "";
const date = new Date(); const date = new Date();

View file

@ -1,17 +1,7 @@
"use strict"; "use strict";
function editEmblem(type, id, el) { function editEmblem(type, id, el) {
if (customization) return; if (customization) return;
if (!id && d3.event) defineEmblemData(d3.event);
if (!id && d3.event) {
const parent = d3.event.target.parentNode;
const [g, t] = parent.id === "burgEmblems" ? [pack.burgs, "burg"] :
parent.id === "provinceEmblems" ? [pack.provinces, "province"] :
[pack.states, "state"];
const i = +d3.event.target.dataset.i;
type = t;
id = type+"COA"+i;
el = g[i];
}
emblems.selectAll(":scope > use").call(d3.drag().on("drag", dragEmblem)).classed("draggable", true); emblems.selectAll(":scope > use").call(d3.drag().on("drag", dragEmblem)).classed("draggable", true);
@ -23,19 +13,31 @@ function editEmblem(type, id, el) {
updateElementSelectors(type, id, el); updateElementSelectors(type, id, el);
$("#emblemEditor").dialog({ $("#emblemEditor").dialog({
title: "Edit Emblem", resizable: true, width: "auto", height: "auto", title: "Edit Emblem", resizable: true, width: "18em", height: "auto",
position: {my: "left top", at: "left+10 top+10", of: "svg", collision: "fit"}, position: {my: "left top", at: "left+10 top+10", of: "svg", collision: "fit"},
close: closeEmblemEditor close: closeEmblemEditor
}); });
if (modules.editEmblem) return; // add listeners,then remove on closure
modules.editEmblem = true; emblemStates.oninput = selectState;
emblemProvinces.oninput = selectProvince;
emblemBurgs.oninput = selectBurg;
document.getElementById("emblemShapeSelector").oninput = changeShape;
document.getElementById("emblemsRegenerate").onclick = regenerate;
document.getElementById("emblemsArmoria").onclick = openInArmoria;
document.getElementById("emblemsDownload").onclick = download;
document.getElementById("emblemsFocus").onclick = showArea;
// add listeners function defineEmblemData(e) {
emblemStates.addEventListener("input", selectState); const parent = e.target.parentNode;
emblemProvinces.addEventListener("input", selectProvince); const [g, t] = parent.id === "burgEmblems" ? [pack.burgs, "burg"] :
emblemBurgs.addEventListener("input", selectBurg); parent.id === "provinceEmblems" ? [pack.provinces, "province"] :
document.getElementById("emblemsFocus").addEventListener("click", showArea); [pack.states, "state"];
const i = +e.target.dataset.i;
type = t;
id = type+"COA"+i;
el = g[i];
}
function updateElementSelectors(type, id, el) { function updateElementSelectors(type, id, el) {
let state = 0, province = 0, burg = 0; let state = 0, province = 0, burg = 0;
@ -81,7 +83,10 @@ function editEmblem(type, id, el) {
function updateEmblemData(type, id, el) { function updateEmblemData(type, id, el) {
if (!el.coa) return; if (!el.coa) return;
document.getElementById("emblemImage").setAttribute("href", "#" + id); document.getElementById("emblemImage").setAttribute("href", "#" + id);
document.getElementById("emblemArmiger").innerText = el.fullName || el.name; document.getElementById("emblemShapeSelector").value = el.coa.shield;
let name = el.fullName || el.name;
if (type === "burg") name = "Burg of " + name;
document.getElementById("emblemArmiger").innerText = name;
} }
function selectState() { function selectState() {
@ -127,6 +132,85 @@ function editEmblem(type, id, el) {
updateElementSelectors(type, id, el); updateElementSelectors(type, id, el);
} }
function changeShape() {
el.coa.shield = this.value;
document.getElementById(id).remove();
COArenderer.trigger(id, el.coa);
}
function showArea() {
highlightEmblemElement(type, el);
}
function regenerate() {
let parent = null;
if (type === "province") parent = pack.states[el.state].coa;
else if (type === "burg") {
const province = pack.cells.province[el.cell];
parent = province ? pack.provinces[province].coa : pack.states[el.state].coa;
}
const shield = el.coa.shield;
el.coa = COA.generate(parent);
el.coa.shield = shield;
document.getElementById(id).remove();
COArenderer.trigger(id, el.coa);
}
function openInArmoria() {
const json = JSON.stringify(el.coa).replaceAll("#", "%23");
const url = `http://azgaar.github.io/Armoria/?coa=${json}`;
openURL(url);
}
function download() {
const coa = document.getElementById(id);
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
const url = getURL(coa, el.coa);
const img = new Image();
img.src = url;
img.onload = () => {
URL.revokeObjectURL(url);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
drawCanvas(canvas, el);
}
function drawCanvas(canvas, el) {
const link = document.createElement("a");
link.download = getFileName(`Emblem ${el.fullName || el.name}`) + ".png";
canvas.toBlob(function (blob) {
link.href = window.URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
setTimeout(function () {
canvas.remove();
window.URL.revokeObjectURL(link.href);
}, 5000);
});
}
}
function getURL(svg, coa) {
const clone = svg.cloneNode(true); // clone svg
const d = clone.getElementsByTagName("defs")[0];
d.insertAdjacentHTML("beforeend", document.getElementById(coa.shield).outerHTML); // copy shield to defs
svg.querySelectorAll("[fill^=url]").forEach(el => {
const id = el.getAttribute("fill").match(/\#([^)]+)\)/)[1];
d.insertAdjacentHTML("beforeend", document.getElementById(id).outerHTML);
});
const serialized = (new XMLSerializer()).serializeToString(clone);
const blob = new Blob([serialized], { type: 'image/svg+xml;charset=utf-8' });
const url = window.URL.createObjectURL(blob);
return url;
}
function dragEmblem() { function dragEmblem() {
const tr = parseTransform(this.getAttribute("transform")); const tr = parseTransform(this.getAttribute("transform"));
const x = +tr[0] - d3.event.x, y = +tr[1] - d3.event.y; const x = +tr[0] - d3.event.x, y = +tr[1] - d3.event.y;
@ -137,10 +221,6 @@ function editEmblem(type, id, el) {
}); });
} }
function showArea() {
highlightEmblemElement(type, el);
}
function closeEmblemEditor() { function closeEmblemEditor() {
emblems.selectAll(":scope > use").call(d3.drag().on("drag", null)).attr("class", null); emblems.selectAll(":scope > use").call(d3.drag().on("drag", null)).attr("class", null);
} }

View file

@ -94,7 +94,7 @@ function showMapTooltip(point, e, i, g) {
tip(e.target.parentNode.dataset.name + ". Click to edit"); tip(e.target.parentNode.dataset.name + ". Click to edit");
return; return;
} }
if (group === "emblems") { if (group === "emblems" && e.target.tagName === "use") {
const parent = e.target.parentNode; const parent = e.target.parentNode;
const [g, type] = parent.id === "burgEmblems" ? [pack.burgs, "burg"] : const [g, type] = parent.id === "burgEmblems" ? [pack.burgs, "burg"] :
parent.id === "provinceEmblems" ? [pack.provinces, "province"] : parent.id === "provinceEmblems" ? [pack.provinces, "province"] :