v1.5.12 - emblems adding, save/load

This commit is contained in:
Azgaar 2021-02-09 00:02:21 +03:00
parent dc3dbe9881
commit a5b2f23cee
12 changed files with 1379 additions and 743 deletions

View file

@ -52,6 +52,11 @@ function editBurg(id) {
function updateBurgValues() {
const id = +elSelected.attr("data-id");
const b = pack.burgs[id];
const province = pack.cells.province[b.cell];
const provinceName = province ? pack.provinces[province].fullName + ", " : "";
const stateName = pack.states[b.state].fullName || pack.states[b.state].name;
document.getElementById("burgProvinceAndState").innerHTML = provinceName + stateName;
document.getElementById("burgName").value = b.name;
document.getElementById("burgPopulation").value = rn(b.population * populationRate.value * urbanization.value);
document.getElementById("burgEditAnchorStyle").style.display = +b.port ? "inline-block" : "none";
@ -62,6 +67,11 @@ function editBurg(id) {
const cultures = pack.cultures.filter(c => !c.removed);
cultures.forEach(c => cultureSelect.options.add(new Option(c.name, c.i, false, c.i === b.culture)));
const temperature = grid.cells.temp[pack.cells.g[b.cell]];
document.getElementById("burgTemperature").innerHTML = convertTemperature(temperature);
document.getElementById("burgTemperatureLikeIn").innerHTML = getTemperatureLikeness(temperature);
document.getElementById("burgElevation").innerHTML = getHeight(pack.cells.h[b.cell]);
// toggle features
if (b.capital) document.getElementById("burgCapital").classList.remove("inactive");
else document.getElementById("burgCapital").classList.add("inactive");
@ -93,6 +103,18 @@ function editBurg(id) {
document.getElementById("burgEmblem").setAttribute("href", "#" + coaID);
}
// in °C, array from -1 °C; source: https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature
function getTemperatureLikeness(temperature) {
if (temperature < -5) return "Yakutsk";
const cities = [
"Snag (Yukon)", "Yellowknife (Canada)", "Okhotsk (Russia)", "Fairbanks (Alaska)", "Nuuk (Greenland)", "Murmansk", // -5 - 0
"Arkhangelsk", "Anchorage", "Tromsø", "Reykjavik", "Riga", "Stockholm", "Halifax", "Prague", "Copenhagen9", "London", // 1 - 10
"Antwerp", "Paris", "Milan", "Batumi", "Rome", "Dubrovnik", "Lisbon", "Barcelona", "Marrakesh", "Alexandria", // 11 - 20
"Tegucigalpa", "Guangzhou", "Rio de Janeiro", "Dakar", "Miami", "Jakarta", "Mogadishu", "Bangkok", "Aden", "Khartoum"]; // 21 - 30
if (temperature > 30) return "Mecca";
return cities[temperature+5] || null;
}
function dragBurgLabel() {
const tr = parseTransform(this.getAttribute("transform"));
const dx = +tr[0] - d3.event.x, dy = +tr[1] - d3.event.y;
@ -313,7 +335,8 @@ function editBurg(id) {
if (!seed && burg.MFCGlink) {openURL(burg.MFCGlink); return;}
const cells = pack.cells;
const name = elSelected.text();
const size = Math.max(Math.min(rn(burg.population), 65), 6);
const size = Math.max(Math.min(rn(burg.population), 100), 6); // to be removed once change on MFDC is done
const population = rn(burg.population * populationRate.value * urbanization.value);
const s = burg.MFCG || defSeed;
const cell = burg.cell;
@ -338,7 +361,7 @@ function editBurg(id) {
}
const site = "http://fantasycities.watabou.ru/?random=0&continuous=0";
const url = `${site}&name=${name}&size=${size}&seed=${s}&hub=${hub}&river=${river}&coast=${coast}&citadel=${citadel}&plaza=${plaza}&temple=${temple}&walls=${walls}&shantytown=${shanty}${sea}`;
const url = `${site}&name=${name}&population=${population}&size=${size}&seed=${s}&hub=${hub}&river=${river}&coast=${coast}&citadel=${citadel}&plaza=${plaza}&temple=${temple}&walls=${walls}&shantytown=${shanty}${sea}`;
openURL(url);
}
}

View file

@ -125,7 +125,12 @@ function addBurg(point) {
const temple = pack.states[state].form === "Theocracy";
const population = Math.max((cells.s[cell] + cells.road[cell]) / 3 + i / 1000 + cell % 100 / 1000, .1);
pack.burgs.push({name, cell, x, y, state, i, culture, feature, capital: 0, port: 0, temple, population});
// generate emblem
const coa = COA.generate(pack.states[state].coa, .25);
coa.shield = COA.getShield(culture, state);
COArenderer.add("burg", i, coa, x, y);
pack.burgs.push({name, cell, x, y, state, i, culture, feature, capital: 0, port: 0, temple, population, coa});
cells.burg[cell] = i;
const townSize = burgIcons.select("#towns").attr("size") || 0.5;

View file

@ -8,6 +8,7 @@ function editEmblem(type, id, el) {
const emblemStates = document.getElementById("emblemStates");
const emblemProvinces = document.getElementById("emblemProvinces");
const emblemBurgs = document.getElementById("emblemBurgs");
const emblemShapeSelector = document.getElementById("emblemShapeSelector");
updateElementSelectors(type, id, el);
@ -21,9 +22,14 @@ function editEmblem(type, id, el) {
emblemStates.oninput = selectState;
emblemProvinces.oninput = selectProvince;
emblemBurgs.oninput = selectBurg;
document.getElementById("emblemShapeSelector").oninput = changeShape;
emblemShapeSelector.oninput = changeShape;
document.getElementById("emblemsRegenerate").onclick = regenerate;
document.getElementById("emblemsArmoria").onclick = openInArmoria;
document.getElementById("emblemsUpload").onclick = toggleUpload;
document.getElementById("emblemsUploadImage").onclick = () => emblemImageToLoad.click();
document.getElementById("emblemsUploadSVG").onclick = () => emblemSVGToLoad.click();
document.getElementById("emblemImageToLoad").onchange = () => upload("image");
document.getElementById("emblemSVGToLoad").onchange = () => upload("svg");
document.getElementById("emblemsDownload").onclick = toggleDownload;
document.getElementById("emblemsDownloadSVG").onclick = () => download("svg");
document.getElementById("emblemsDownloadPNG").onclick = () => download("png");
@ -88,10 +94,15 @@ function editEmblem(type, id, el) {
function updateEmblemData(type, id, el) {
if (!el.coa) return;
document.getElementById("emblemImage").setAttribute("href", "#" + id);
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;
if (el.coa === "custom") emblemShapeSelector.disabled = true;
else {
emblemShapeSelector.disabled = false;
emblemShapeSelector.value = el.coa.shield;
}
}
function selectState() {
@ -149,27 +160,75 @@ function editEmblem(type, id, el) {
function regenerate() {
let parent = null;
if (type === "province") parent = pack.states[el.state].coa;
if (type === "province") parent = pack.states[el.state];
else if (type === "burg") {
const province = pack.cells.province[el.cell];
parent = province ? pack.provinces[province].coa : pack.states[el.state].coa;
parent = province ? pack.provinces[province] : pack.states[el.state];
}
const shield = el.coa.shield;
el.coa = COA.generate(parent);
const shield = el.coa.shield || COA.getShield(el.culture || parent?.culture || 0, el.state);
el.coa = COA.generate(parent ? parent.coa : null);
el.coa.shield = shield;
emblemShapeSelector.disabled = false;
emblemShapeSelector.value = el.coa.shield;
document.getElementById(id).remove();
const coaEl = document.getElementById(id);
if (coaEl) coaEl.remove();
COArenderer.trigger(id, el.coa);
}
function openInArmoria() {
const json = JSON.stringify(el.coa).replaceAll("#", "%23");
const coa = el.coa && el.coa !== "custom" ? el.coa : {t1: "sable"};
const json = JSON.stringify(coa).replaceAll("#", "%23");
const url = `http://azgaar.github.io/Armoria/?coa=${json}`;
openURL(url);
}
function toggleUpload() {
document.getElementById("emblemDownloadControl").classList.add("hidden");
const buttons = document.getElementById("emblemUploadControl");
buttons.classList.toggle("hidden");
}
function upload(type) {
const input = type === "image" ? document.getElementById("emblemImageToLoad") : document.getElementById("emblemSVGToLoad");
const file = input.files[0];
input.value = "";
if (file.size > 500000) {
tip(`File is too big, please optimize file size up to 500kB and re-upload. Recommended size is 200x200 px and up to 100kB`, true, "error", 5000);
return;
}
const reader = new FileReader();
reader.onload = function(readerEvent) {
const result = readerEvent.target.result;
const defs = document.getElementById("defs-emblems");
if (type === "image") {
const svg = `<svg id="${id}" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><image x="0" y="0" width="200" height="200" href="${result}"/></svg>`;
defs.insertAdjacentHTML("beforeend", svg);
} else {
defs.insertAdjacentHTML("beforeend", result);
const newEmblem = defs.lastChild; // new coa
newEmblem.id = id;
newEmblem.setAttribute("width", 200);
newEmblem.setAttribute("height", 200);
}
const coa = document.getElementById(id);
if (coa) coa.remove(); // remove old emblem
el.coa = "custom";
emblemShapeSelector.disabled = true;
};
if (type === "image") reader.readAsDataURL(file); else reader.readAsText(file);
}
function toggleDownload() {
document.getElementById("emblemUploadControl").classList.add("hidden");
const buttons = document.getElementById("emblemDownloadControl");
buttons.classList.toggle("hidden");
}
@ -225,16 +284,9 @@ function editEmblem(type, id, el) {
const clone = svg.cloneNode(true); // clone svg
const d = clone.getElementsByTagName("defs")[0];
clone.removeAttribute("id");
clone.setAttribute("width", size);
clone.setAttribute("height", size);
d.insertAdjacentHTML("beforeend", document.getElementById(coa.shield).outerHTML); // copy shield to defs
clone.querySelectorAll("[fill^=url]").forEach(el => {
const id = el.getAttribute("fill").match(/\#([^)]+)\)/)[1];
d.insertAdjacentHTML("beforeend", document.getElementById(id).outerHTML);
});
return (new XMLSerializer()).serializeToString(clone);
}

View file

@ -239,10 +239,15 @@ function editProvinces() {
const name = provinces[p].name;
const color = getRandomColor();
const coa = provinces[p].coa;
const coaEl = document.getElementById("provinceCOA"+p);
if (coaEl) coaEl.id = "stateCOA"+newState;
emblems.select(`#provinceEmblems > use[data-i='${p}']`).remove();
// update cells
cells.i.filter(i => cells.province[i] === p).forEach(i => {
cells.province[i] = 0;
cells.state[i] = newState;
cells.province[i] = 0;
cells.state[i] = newState;
});
// update diplomacy and reverse relations
@ -264,7 +269,7 @@ function editProvinces() {
states[0].diplomacy.push([`Independance declaration`, `${name} declared its independance from ${states[oldState].name}`]);
// create new state
states.push({i:newState, name, diplomacy, provinces:[], color, expansionism:.5, capital:burg, type:"Generic", center, culture, military:[], alert:1});
states.push({i:newState, name, diplomacy, provinces:[], color, expansionism:.5, capital:burg, type:"Generic", center, culture, military:[], alert:1, coa});
BurgsAndStates.collectStatistics();
BurgsAndStates.defineStateForms([newState]);
@ -276,7 +281,10 @@ function editProvinces() {
// remove old province
unfog("focusProvince"+p);
if (states[oldState].provinces.includes(p)) states[oldState].provinces.splice(states[oldState].provinces.indexOf(p), 1);
provinces[p].removed = true;
provinces[p] = {i:p, removed: true};
// draw emblem
COArenderer.add("state", newState, coa, pack.states[newState].pole[0], pack.states[newState].pole[1]);
closeDialogs();
editStates();
@ -767,7 +775,15 @@ function editProvinces() {
const fullName = name + " " + formName;
const stateColor = pack.states[state].color, rndColor = getRandomColor();
const color = stateColor[0] === "#" ? d3.color(d3.interpolate(stateColor, rndColor)(.2)).hex() : rndColor;
provinces.push({i:province, state, center, burg, name, formName, fullName, color});
// generate emblem
const kinship = burg ? .8 : .4;
const parent = burg ? pack.burgs[burg].coa : pack.states[state].coa;
const coa = COA.generate(parent, kinship);
coa.shield = COA.getShield(c, state);
COArenderer.add("province", province, coa, point[0], point[1]);
provinces.push({i:province, state, center, burg, name, formName, fullName, color, coa});
cells.province[center] = province;
cells.c[center].forEach(c => {

View file

@ -842,6 +842,10 @@ function editStates() {
const name = Names.getState(basename, culture);
const color = getRandomColor();
// generate emblem
const coa = COA.generate(burgs[burg].coa, .4);
coa.shield = COA.getShield(culture, null);
// update diplomacy and reverse relations
const diplomacy = states.map(s => {
if (!s.i) return "x";
@ -869,7 +873,9 @@ function editStates() {
const affectedProvinces = [cells.province[center]];
cells.state[center] = newState;
cells.province[center] = 0;
cells.c[center].forEach(c => {
const cellsToCheck = [...new Set(cells.c[center].map(c => cells.c[c].map(c => cells.c[c])).flat(2))];
cellsToCheck.forEach(c => {
if (cells.h[c] < 20) return;
if (cells.burg[c]) return;
affectedStates.push(cells.state[c]);
@ -877,7 +883,8 @@ function editStates() {
cells.state[c] = newState;
cells.province[c] = 0;
});
states.push({i:newState, name, diplomacy, provinces:[], color, expansionism:.5, capital:burg, type:"Generic", center, culture, military:[], alert:1});
states.push({i:newState, name, diplomacy, provinces:[], color, expansionism:.5, capital:burg, type:"Generic", center, culture, military:[], alert:1, coa});
BurgsAndStates.collectStatistics();
BurgsAndStates.defineStateForms([newState]);
adjustProvinces([...new Set(affectedProvinces)]);
@ -886,6 +893,7 @@ function editStates() {
if (!layerIsOn("toggleStates")) toggleStates(); else drawStates();
if (!layerIsOn("toggleBorders")) toggleBorders(); else drawBorders();
BurgsAndStates.drawStateLabels([...new Set(affectedStates)]);
COArenderer.add("state", newState, coa, states[newState].pole[0], states[newState].pole[1]);
statesEditorAddLines();
}