v1.5.02 - COA rendering + editor basic UI

This commit is contained in:
Azgaar 2021-01-28 01:40:11 +03:00
parent b86d985607
commit 9f1012603d
9 changed files with 1663 additions and 53 deletions

View file

@ -158,14 +158,14 @@
head: {e: 1},
headWreathed: {e: 1}
};
const lines = {
straight: 50, wavy: 8, engrailed: 4, invecked: 3, rayonne: 3, embattled: 1, raguly: 1, urdy: 1, dancetty: 1, indented: 2,
dentilly: 1, bevilled: 1, angled: 1, flechy: 1, barby: 1, enclavy: 1, escartely: 1, arched: 2, archedReversed: 1, nowy: 1, nowyReversed: 1,
embattledGhibellin: 1, embattledNotched: 1, embattledGrady: 1, dovetailedIndented: 1, dovetailed: 1,
potenty: 1, potentyDexter: 1, potentySinister: 1, nebuly: 2, seaWaves: 1, dragonTeeth: 1, firTrees: 1
};
const divisions = {
variants: { perPale: 5, perFess: 5, perBend: 2, perBendSinister: 1, perChevron: 1, perChevronReversed: 1, perCross: 5, perPile: 1, perSaltire: 1, gyronny: 1, chevronny: 1 },
perPale: lines,
@ -177,7 +177,7 @@
perCross: { straight: 20, wavy: 5, engrailed: 4, invecked: 3, rayonne: 1, embattled: 1, raguly: 1, urdy: 1, indented: 2, dentilly: 1, bevilled: 1, angled: 1, embattledGhibellin: 1, embattledGrady: 1, dovetailedIndented: 1, dovetailed: 1, potenty: 1, potentyDexter: 1, potentySinister: 1, nebuly: 1 },
perPile: lines
};
const ordinaries = {
lined: {
pale: 7, fess: 5, bend: 3, bendSinister: 2, chief: 5, bar: 2, gemelle: 1, fessCotissed: 1, fessDoubleCotissed: 1,
@ -194,6 +194,14 @@
TIME && console.time("generateCOA");
let usedPattern = null, usedTinctures = [];
// TODO
// seafaring
// stringify coa on save and load
// regenerateAll
// generate on new item creation
// shields for cultures
// old versions auti migration
const t1 = parent && P(.25) ? parent.t1 : getTincture("field");
const coa = {t1};
@ -285,7 +293,7 @@
division === "perBend" ? ["l", "m"] :
["j", "o"]; // perBendSinister
coa.charges[0].p = p1;
const charge = selectCharge(charges.single);
const t = getTincture("charge", usedTinctures, coa.division.t);
coa.charges.push({charge, t, p: p2});
@ -293,28 +301,28 @@
else if (["perCross", "perSaltire"].includes(division) && P(.5)) { // place 4 charges in division standard positions
const [p1, p2, p3, p4] = division === "perCross" ? ["j", "l", "m", "o"] : ["b", "d", "f", "h"];
coa.charges[0].p = p1;
const c2 = selectCharge(charges.single);
const t2 = getTincture("charge", [], coa.division.t);
const c3 = selectCharge(charges.single);
const t3 = getTincture("charge", [], coa.division.t);
const c4 = selectCharge(charges.single);
const t4 = getTincture("charge", [], coa.t1);
coa.charges.push({charge: c2, t: t2, p: p2}, {charge: c3, t: t3, p: p3}, {charge: c4, t: t4, p: p4});
}
else if (allowCounter && p.length > 1) coa.charges[0].divided = "counter"; // counterchanged, 40%
}
coa.charges.forEach(c => defineChargeAttributes(c));
function defineChargeAttributes(c) {
// define size
c.size = (c.size || 1) * getSize(c.p, ordinary, division);
// clean-up position
c.p = [...new Set(c.p)].join("");
// define orientation
if (P(.02) && charges.sinister.includes(c.charge)) c.sinister = 1;
if (P(.02) && charges.reversed.includes(c.charge)) c.reversed = 1;
@ -329,21 +337,21 @@
// select tincture: element type (field, division, charge), used field tinctures, field type to follow RoT
function getTincture(element, fields = [], RoT) {
const base = RoT ? RoT.includes("-") ? RoT.split("-")[1] : RoT : null;
let type = rw(tinctures[element]); // metals, colours, stains, patterns
if (RoT && type !== "patterns") type = getType(base) === "metals" ? "colours" : "metals"; // follow RoT
if (type === "metals" && fields.includes("or") && fields.includes("argent")) type = "colours"; // exclude metals overuse
let tincture = rw(tinctures[type]);
while (tincture === base || fields.includes(tincture)) {tincture = rw(tinctures[type]);} // follow RoT
if (type !== "patterns" && element !== "charge") usedTinctures.push(tincture); // add field tincture
if (type === "patterns") {
usedPattern = tincture;
tincture = definePattern(tincture, element);
}
return tincture;
}
@ -361,7 +369,7 @@
else if (P(.05)) size = "-smaller";
else if (P(.035)) size = "-big";
else if (P(.001)) size = "-smallest";
// apply standard tinctures
if (P(.5) && ["vair", "vairInPale", "vairEnPointe"].includes(pattern)) {t1 = "azure"; t2 = "argent";}
else if (P(.8) && pattern === "ermine") {t1 = "argent"; t2 = "sable";}
@ -381,24 +389,24 @@
else if (P(.15)) {t1 = "gules"; t2 = "argent";}
}
else if (pattern === "semy") pattern += "_of_" + selectCharge(charges.semy);
if (!t1 || !t2) {
const startWithMetal = P(.7);
t1 = startWithMetal ? rw(tinctures.metals) : rw(tinctures.colours);
t2 = startWithMetal ? rw(tinctures.colours) : rw(tinctures.metals);
}
// division should not be the same tincture as base field
if (element === "division") {
if (usedTinctures.includes(t1)) t1 = replaceTincture(t1);
if (usedTinctures.includes(t2)) t2 = replaceTincture(t2);
}
usedTinctures.push(t1, t2);
return `${pattern}-${t1}-${t2}${size}`;
}
function replaceTincture(t, n) {
const type = getType(t);
while (!n || n === t) {n = rw(tinctures[type]);}

887
modules/coa-renderer.js Normal file
View file

@ -0,0 +1,887 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.COArenderer = factory());
}(this, (function () {'use strict';
const colors = {
argent: "#fafafa",
or: "#ffe066",
gules: "#d7374a",
sable: "#333333",
azure: "#377cd7",
vert: "#26c061",
purpure: "#522d5b",
murrey: "#85185b",
sanguine: "#b63a3a",
tenné: "#cc7f19"
}
const shieldPositions = {
// shield-specific position: [x, y] (relative to center)
heater: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-32.25, 37.5], h: [0, 50], i: [32.25, 37.5],
y: [-50, -50], z: [0, 62.5],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-30, 30], n: [0, 42.5], o: [30, 30],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.2, -66.6], B: [-22, -66.6], C: [22, -66.6], D: [66.2, -66.6],
K: [-66.2, -20], E: [66.2, -20],
J: [-55.5, 26], F: [55.5, 26],
I: [-33, 62], G: [33, 62],
H: [0, 89.5]
},
spanish: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-43.75, 50], h: [0, 50], i: [43.75, 50],
y: [-50, -50], z: [0, 50],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 37.5], o: [37.5, 37.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.2, -66.6], B: [-22, -66.6], C: [22, -66.6], D: [66.2, -66.6],
K: [-66.4, -20], E: [66.4, -20],
J: [-66.4, 26], F: [66.4, 26],
I: [-49, 70], G: [49, 70],
H: [0, 92]
},
french: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-43.75, 50], h: [0, 50], i: [43.75, 50],
y: [-50, -50], z: [0, 65],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 37.5], o: [37.5, 37.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.2, -66.6], B: [-22, -66.6], C: [22, -66.6], D: [66.2, -66.6],
K: [-66.4, -20], E: [66.4, -20],
J: [-66.4, 26], F: [66.4, 26],
I: [-65.4, 70], G: [65.4, 70],
H: [0, 89]
},
horsehead: {
a: [-43.75, -47.5], b: [0, -50], c: [43.75, -47.5],
d: [-35, 0], e: [0, 0], f: [35, 0],
h: [0, 50],
y: [-50, -50], z: [0, 55],
j: [-35, -35], k: [0, -40], l: [35, -35],
m: [-30, 30], n: [0, 40], o: [30, 30],
p: [-27.5, 0], q: [27.5, 0],
A: [-71, -52], B: [-24, -73], C: [24, -73], D: [71, -52],
K: [-62, -16], E: [62, -16],
J: [-39, 20], F: [39, 20],
I: [-33.5, 60], G: [33.5, 60],
H: [0, 91.5]
},
horsehead2: {
a: [-37.5, -47.5], b: [0, -50], c: [37.5, -47.5],
d: [-35, 0], e: [0, 0], f: [35, 0],
g: [-35, -47.5], h: [0, 50], i: [35, -47.5],
y: [-50, -50], z: [0, 55],
j: [-30, -30], k: [0, -40], l: [30, -30],
m: [-30, 30], n: [0, 40], o: [30, 30],
p: [-27.5, 0], q: [27.5, 0],
A: [-49, -39], B: [-22, -70], C: [22, -70], D: [49, -39],
K: [-51, -2], E: [51, -2],
J: [-38.5, 31], F: [38.5, 31],
I: [-35, 67], G: [35, 67],
H: [0, 85]
},
polish: {
a: [-35, -50], b: [0, -50], c: [35, -50],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-37.5, 50], h: [0, 50], i: [37.5, 50],
y: [-50, -50], z: [0, 65],
j: [-27.5, -27.5], k: [0, -45], l: [27.5, -27.5],
m: [-27.5, 27.5], n: [0, 45], o: [27.5, 27.5],
p: [-32.5, 0], q: [32.5, 0],
A: [-48, -52], B: [-23, -80], C: [23, -80], D: [48, -52],
K: [-47, -10], E: [47, -10],
J: [-62, 32], F: [62, 32],
I: [-37, 68], G: [37, 68],
H: [0, 86]
},
hessen: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-43.75, 50], h: [0, 50], i: [43.75, 50],
y: [-50, -50], z: [0, 52.5],
j: [-40, -40], k: [0, -40], l: [40, -40],
m: [-40, 40], n: [0, 40], o: [40, 40],
p: [-40, 0], q: [40, 0],
A: [-69, -64], B: [-22, -76], C: [22, -76], D: [69, -64],
K: [-66.4, -20], E: [66.4, -20],
J: [-62, 26], F: [62, 26],
I: [-46, 70], G: [46, 70],
H: [0, 91.5]
},
swiss: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-32, 37.5], h: [0, 50], i: [32, 37.5],
y: [-50, -50], z: [0, 62.5],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-32, 32.5], n: [0, 42.5], o: [32, 32.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.2, -66.6], B: [-22, -66], C: [22, -66], D: [66.2, -66.6],
K: [-63, -20], E: [63, -20],
J: [-50, 26], F: [50, 26],
I: [-29, 62], G: [29, 62],
H: [0, 89.5]
},
boeotian: {
a: [-37.5, -47.5], b: [0, -47.5], c: [37.5, -47.5],
d: [-25, 0], e: [0, 0], f: [25, 0],
g: [-37.5, 47.5], h: [0, 47.5], i: [37.5, 47.5],
y: [-48, -48], z: [0, 60],
j: [-32.5, -37.5], k: [0, -45], l: [32.5, -37.5],
m: [-32.5, 37.5], n: [0, 45], o: [32.5, 37.5],
p: [-20, 0], q: [20, 0],
A: [-45, -55], B: [-20, -77], C: [20, -77], D: [45, -55],
K: [-59, -25], E: [59, -25],
J: [-58, 27], F: [58, 27],
I: [-39, 63], G: [39, 63],
H: [0, 81]
},
roman: {
a: [-40, -52.5], b: [0, -52.5], c: [40, -52.5],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-40, 52.5], h: [0, 52.5], i: [40, 52.5],
y: [-42.5, -52.5], z: [0, 65],
j: [-30, -37.5], k: [0, -37.5], l: [30, -37.5],
m: [-30, 37.5], n: [0, 37.5], o: [30, 37.5],
p: [-30, 0], q: [30, 0],
A: [-51.5, -65], B: [-17, -75], C: [17, -75], D: [51.5, -65],
K: [-51.5, -21], E: [51.5, -21],
J: [-51.5, 21], F: [51.5, 21],
I: [-51.5, 65], G: [51.5, 65],
H: [-17, 75], L: [17, 75]
},
kite: {
b: [0, -65], e: [0, -15], h: [0, 35],
z: [0, 35], k: [0, -50], n: [0, 20],
p: [-20, -15], q: [20, -15],
A: [-38, -52], B: [-29, -78], C: [29, -78], D: [38, -52],
K: [-33, -20], E: [33, -20],
J: [-25, 11], F: [25, 11],
I: [-15, 42], G: [15, 42],
H: [0, 73], L: [0, -91]
},
oldFrench: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-37.5, 50], h: [0, 50], i: [37.5, 50],
y: [-50, -50], z: [0, 62.5],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 45], o: [37.5, 37.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.2, -66.6], B: [-22, -66.6], C: [22, -66.6], D: [66.2, -66.6],
K: [-66.2, -20], E: [66.2, -20],
J: [-64, 26], F: [64, 26],
I: [-45, 62], G: [45, 62],
H: [0, 91],
},
renaissance: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-41.5, 0], e: [0, 0], f: [41.5, 0],
g: [-43.75, 50], h: [0, 50], i: [43.75, 50],
y: [-50, -50], z: [0, 62.5],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 37.5], o: [37.5, 37.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-61, -55], B: [-23, -67], C: [23, -67], D: [61, -55],
K: [-55, -11], E: [55, -11],
J: [-65, 31], F: [65, 31],
I: [-45, 76], G: [45, 76],
H: [0, 87]
},
baroque: {
a: [-43.75, -45], b: [0, -45], c: [43.75, -45],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-43.75, 50], h: [0, 50], i: [43.75, 50],
y: [-50, -50], z: [0, 60],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 37.5], o: [37.5, 37.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-65, -54.5], B: [-22, -65], C: [22, -65], D: [65, -54.5],
K: [-58.5, -15], E: [58.5, -15],
J: [-65, 31], F: [66, 31],
I: [-35, 73], G: [35, 73],
H: [0, 89]
},
targe: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-43.75, 50], h: [0, 50], i: [43.75, 50],
y: [-50, -50], z: [0, 50],
j: [-40, -40], k: [0, -40], l: [40, -40],
m: [-40, 40], n: [0, 40], o: [40, 40],
p: [-32.5, 0], q: [32.5, 0],
A: [-66.2, -60], B: [-22, -77], C: [22, -86], D: [60, -66.6],
K: [-28, -20], E: [57, -20],
J: [-61, 26], F: [61, 26],
I: [-49, 63], G: [49, 59],
H: [0, 80]
},
targe2: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-43.75, 50], h: [0, 50], i: [43.75, 50],
y: [-50, -50], z: [0, 60],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 37.5], o: [37.5, 37.5],
p: [-32.5, 0], q: [32.5, 0],
A: [-55, -59], B: [-15, -59], C: [24, -79], D: [51, -58],
K: [-40, -14], E: [51, -14],
J: [-64, 26], F: [62, 26],
I: [-46, 66], G: [48, 67],
H: [0, 83]
},
pavise: {
a: [-40, -52.5], b: [0, -52.5], c: [40, -52.5],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-40, 52.5], h: [0, 52.5], i: [40, 52.5],
y: [-42.5, -52.5], z: [0, 60],
j: [-30, -35], k: [0, -37.5], l: [30, -35],
m: [-30, 35], n: [0, 37.5], o: [30, 35],
p: [-30, 0], q: [30, 0],
A: [-57, -55], B: [-22, -74], C: [22, -74], D: [57, -55],
K: [-54, -11], E: [54, -11],
J: [-50, 36], F: [50, 36],
I: [-46, 81], G: [46, 81],
H: [0, 81]
},
wedged: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.75, 0], e: [0, 0], f: [43.75, 0],
g: [-32.25, 37.5], h: [0, 50], i: [32.25, 37.5],
y: [-50, -50], z: [0, 62.5],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-32.5, 32.5], n: [0, 42.5], o: [32.5, 32.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66, -53], B: [-22, -72.5], C: [22, -72.5], D: [66, -53],
K: [-62.6, -13], E: [62.6, -13],
J: [-50, 26], F: [50, 26],
I: [-27, 62], G: [27, 62],
H: [0, 87]
},
flag: {
a: [-60, -40], b: [0, -40], c: [60, -40],
d: [-60, 0], e: [0, 0], f: [60, 0],
g: [-60, 40], h: [0, 40], i: [60, 40],
y: [-60, -42.5], z: [0, 40],
j: [-45, -30], k: [0, -30], l: [45, -30],
m: [-45, 30], n: [0, 30], o: [45, 30],
p: [-45, 0], q: [45, 0],
A: [-81, -51], B: [-27, -51], C: [27, -51], D: [81, -51],
K: [-81, -17], E: [81, -17],
J: [-81, 17], F: [81, 17],
I: [-81, 51], G: [81, 51],
H: [-27, 51], L: [27, 51]
},
pennon: {
a: [-75, -40],
d: [-75, 0], e: [-25, 0], f: [25, 0],
g: [-75, 40],
y: [-70, -42.5],
j: [-60, -30],
m: [-60, 30],
p: [-60, 0], q: [5, 0],
A: [-81, -48], B: [-43, -36], C: [-4.5, -24], D: [33, -12],
E: [72, 0],
F: [33, 12], G: [-4.5, 24], H: [-43, 36], I: [-81, 48],
J: [-81, 17], K: [-81, -17]
},
guidon: {
a: [-60, -40], b: [0, -40], c: [60, -40],
d: [-60, 0], e: [0, 0],
g: [-60, 40], h: [0, 40], i: [60, 40],
y: [-60, -42.5], z: [0, 40],
j: [-45, -30], k: [0, -30], l: [45, -30],
m: [-45, 30], n: [0, 30], o: [45, 30],
p: [-45, 0],
A: [-81, -51], B: [-27, -51], C: [27, -51], D: [78, -51],
K: [-81, -17], E: [40.5, -17],
J: [-81, 17], F: [40.5, 17],
I: [-81, 51], G: [78, 51],
H: [-27, 51], L: [27, 51]
},
banner: {
a: [-50, -50], b: [0, -50], c: [50, -50],
d: [-50, 0], e: [0, 0], f: [50, 0],
g: [-50, 40], h: [0, 40], i: [50, 40],
y: [-50, -50], z: [0, 40],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 27.5], n: [0, 27.5], o: [37.5, 27.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.5, -66.5], B: [-22, -66.5], C: [22, -66.5], D: [66.5, -66.5],
K: [-66.5, -20], E: [66.5, -20],
J: [-66.5, 26], F: [66.5, 26],
I: [-66.5, 66.5], G: [66.5, 66.5],
H: [-25, 75], L: [25, 75]
},
dovetail: {
a: [-49.75, -50], b: [0, -50], c: [49.75, -50],
d: [-49.75, 0], e: [0, 0], f: [49.75, 0],
g: [-49.75, 50], i: [49.75, 50],
y: [-50, -50], z: [0, 40],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 32.5], o: [37.5, 37.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.5, -66.5], B: [-22, -66.5], C: [22, -66.5], D: [66.5, -66.5],
K: [-66.5, -16.5], E: [66.5, -16.5],
J: [-66.5, 34.5], F: [66.5, 34.5],
I: [-66.5, 84.5], G: [66.5, 84.5],
H: [-25, 64], L: [25, 64]
},
gonfalon: {
a: [-49.75, -50], b: [0, -50], c: [49.75, -50],
d: [-49.75, 0], e: [0, 0], f: [49.75, 0],
g: [-49.75, 50], h: [0, 50], i: [49.75, 50],
y: [-50, -50], z: [0, 50],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 37.5], o: [37.5, 37.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.5, -66.5], B: [-22, -66.5], C: [22, -66.5], D: [66.5, -66.5],
K: [-66.5, -20], E: [66.5, -20],
J: [-66.5, 26], F: [66.5, 26],
I: [-40, 63], G: [40, 63],
H: [0, 88]
},
pennant: {
a: [-45, -50], b: [0, -50], c: [45, -50],
e: [0, 0], h: [0, 50],
y: [-50, -50], z: [0, 50],
j: [-32.5, -37.5], k: [0, -37.5], l: [32.5, -37.5],
n: [0, 37.5],
A: [-60, -76], B: [-22, -76], C: [22, -76], D: [60, -76],
K: [-46, -38], E: [46, -38],
J: [-31, 0], F: [31, 0],
I: [-16, 38], G: [16, 38],
H: [0, 76]
},
round: {
a: [-40, -47.5], b: [0, -47.5], c: [40, -47.5],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-32.5, 47.5], h: [0, 47.5], i: [32.5, 47.5],
y: [-48, -48], z: [0, 57.5],
j: [-35.5, -35.5], k: [0, -37.5], l: [35.5, -35.5],
m: [-35.5, 35.5], n: [0, 37.5], o: [35.5, 35.5],
p: [-36.5, 0], q: [36.5, 0],
A: [-59, -48], B: [-23, -73], C: [23, -73], D: [59, -48],
K: [-76, -10], E: [76, -10],
J: [-70, 31], F: [70, 31],
I: [-42, 64], G: [42, 64],
H: [0, 77]
},
oval: {
a: [-37.5, -50], b: [0, -50], c: [37.5, -50],
d: [-43, 0], e: [0, 0], f: [43, 0],
g: [-37.5, 50], h: [0, 50], i: [37.5, 50],
y: [-48, -48], z: [0, 60],
j: [-35.5, -37.5], k: [0, -37.5], l: [35.5, -37.5],
m: [-35.5, 37.5], n: [0, 50], o: [35.5, 37.5],
p: [-36.5, 0], q: [36.5, 0],
A: [-48, -48], B: [-23, -78], C: [23, -78], D: [48, -48],
K: [-59, -10], E: [59, -10],
J: [-55, 31], F: [55, 31],
I: [-36, 68], G: [36, 68],
H: [0, 85]
},
vesicaPiscis: {
a: [-32, -37], b: [0, -50], c: [32, -37],
d: [-32, 0], e: [0, 0], f: [32, 0],
g: [-32, 37], h: [0, 50], i: [32, 37],
y: [-50, -50], z: [0, 62],
j: [-27.5, -27.5], k: [0, -37], l: [27.5, -27.5],
m: [-27.5, 27.5], n: [0, 42], o: [27.5, 27.5],
p: [-27.5, 0], q: [27.5, 0],
A: [-45, -32], B: [-29, -63], C: [29, -63], D: [45, -32],
K: [-50, 0], E: [50, 0],
J: [-45, 32], F: [45, 32],
I: [-29, 63], G: [29, 63],
H: [0, 89], L: [0, -89]
},
square: {
a: [-49.75, -50], b: [0, -50], c: [49.75, -50],
d: [-49.75, 0], e: [0, 0], f: [49.75, 0],
g: [-49.75, 50], h: [0, 50], i: [49.75, 50],
y: [-50, -50], z: [0, 50],
j: [-37.5, -37.5], k: [0, -37.5], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 37.5], o: [37.5, 37.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-66.5, -66.5], B: [-22, -66.5], C: [22, -66.5], D: [66.5, -66.5],
K: [-66.5, -20], E: [66.5, -20],
J: [-66.5, 26], F: [66.5, 26],
I: [-66.5, 66.5], G: [66.5, 66.5],
H: [-22, 66.5], L: [22, 66.5]
},
diamond: {
a: [-32, -37], b: [0, -50], c: [32, -37],
d: [-43, 0], e: [0, 0], f: [43, 0],
g: [-32, 37], h: [0, 50], i: [32, 37],
y: [-50, -50], z: [0, 62],
j: [-27.5, -27.5], k: [0, -37], l: [27.5, -27.5],
m: [-27.5, 27.5], n: [0, 42], o: [27.5, 27.5],
p: [-37, 0], q: [37, 0],
A: [-43, -28], B: [-22, -56], C: [22, -56], D: [43, -28],
K: [-63, 0], E: [63, 0],
J: [-42, 28], F: [42, 28],
I: [-22, 56], G: [22, 56],
H: [0, 83], L: [0, -82]
},
no: {
a: [-66.5, -66.5], b: [0, -66.5], c: [66.5, -66.5],
d: [-66.5, 0], e: [0, 0], f: [66.5, 0],
g: [-66.5, 66.5], h: [0, 66.5], i: [66.5, 66.5],
y: [-50, -50], z: [0, 75],
j: [-50, -50], k: [0, -50], l: [50, -50],
m: [-50, 50], n: [0, 50], o: [50, 50],
p: [-50, 0], q: [50, 0],
A: [-91.5, -91.5], B: [-30.5, -91.5], C: [30.5, -91.5], D: [91.5, -91.5],
K: [-91.5, -30.5], E: [91.5, -30.5],
J: [-91.5, 30.5], F: [91.5, 30.5],
I: [-91.5, 91.5], G: [91.5, 91.5],
H: [-30.5, 91.5], L: [30.5, 91.5]
},
fantasy1: {
a: [-45, -45], b: [0, -50], c: [45, -45],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-36, 42.5], h: [0, 50], i: [36, 42.5],
y: [-50, -50], z: [0, 60],
j: [-37, -37], k: [0, -40], l: [37, -37],
m: [-32, 32], n: [0, 40], o: [32, 32],
p: [-28.5, 0], q: [28.5, 0],
A: [-66, -55], B: [-22, -67], C: [22, -67], D: [66, -55],
K: [-53, -20], E: [53, -20],
J: [-46, 26], F: [46, 26],
I: [-29, 62], G: [29, 62],
H: [0, 84]
},
fantasy2: {
a: [-45, -45], b: [0, -45], c: [45, -45],
d: [-35, 0], e: [0, 0], f: [35, 0],
g: [-36, 42.5], h: [0, 45], i: [36, 42.5],
y: [-50, -50], z: [0, 55],
j: [-32.5, -32.5], k: [0, -40], l: [32.5, -32.5],
m: [-30, 30], n: [0, 40], o: [30, 30],
p: [-27.5, 0], q: [27.5, 0],
A: [-58, -35], B: [-44, -67], C: [44, -67], D: [58, -35],
K: [-39, -5], E: [39, -5],
J: [-57, 26], F: [57, 26],
I: [-32, 58], G: [32, 58],
H: [0, 83], L: [0, -72]
},
fantasy3: {
a: [-40, -45], b: [0, -50], c: [40, -45],
d: [-35, 0], e: [0, 0], f: [35, 0],
g: [-36, 42.5], h: [0, 50], i: [36, 42.5],
y: [-50, -50], z: [0, 55],
j: [-32.5, -32.5], k: [0, -40], l: [32.5, -32.5],
m: [-30, 30], n: [0, 40], o: [30, 30],
p: [-27.5, 0], q: [27.5, 0],
A: [-56, -42], B: [-22, -72], C: [22, -72], D: [56, -42],
K: [-37, -11], E: [37, -11],
J: [-60, 20], F: [60, 20],
I: [-34, 56], G: [34, 56],
H: [0, 83]
},
fantasy4: {
a: [-50, -45], b: [0, -50], c: [50, -45],
d: [-45, 0], e: [0, 0], f: [45, 0],
g: [-40, 45], h: [0, 50], i: [40, 45],
y: [-50, -50], z: [0, 62.5],
j: [-37.5, -37.5], k: [0, -45], l: [37.5, -37.5],
m: [-37.5, 37.5], n: [0, 45], o: [37.5, 37.5],
p: [-35, 0], q: [35, 0],
A: [-75, -56], B: [-36, -61], C: [36, -61], D: [75, -56],
K: [-67, -12], E: [67, -12],
J: [-63, 32], F: [63, 32],
I: [-42, 75], G: [42, 75],
H: [0, 91.5], L: [0, -79]
},
fantasy5: {
a: [-45, -50], b: [0, -50], c: [45, -50],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-30, 45], h: [0, 50], i: [30, 45],
y: [-50, -50], z: [0, 60],
j: [-37, -37], k: [0, -40], l: [37, -37],
m: [-32, 32], n: [0, 40], o: [32, 32],
p: [-28.5, 0], q: [28.5, 0],
A: [-61, -67], B: [-22, -76], C: [22, -76], D: [61, -67],
K: [-58, -25], E: [58, -25],
J: [-48, 20], F: [48, 20],
I: [-28.5, 60], G: [28.5, 60],
H: [0, 89]
},
noldor: {
b: [0, -65], e: [0, -15], h: [0, 35],
z: [0, 35], k: [0, -50], n: [0, 30],
p: [-20, -15], q: [20, -15],
A: [-34, -47], B: [-20, -68], C: [20, -68], D: [34, -47],
K: [-18, -20], E: [18, -20],
J: [-26, 11], F: [26, 11],
I: [-14, 43], G: [14, 43],
H: [0, 74], L: [0, -85]
},
gondor: {
a: [-32.5, -50], b: [0, -50], c: [32.5, -50],
d: [-32.5, 0], e: [0, 0], f: [32.5, 0],
g: [-32.5, 50], h: [0, 50], i: [32.5, 50],
y: [-42.5, -52.5], z: [0, 65],
j: [-25, -37.5], k: [0, -37.5], l: [25, -37.5],
m: [-25, 30], n: [0, 37.5], o: [25, 30],
p: [-25, 0], q: [25, 0],
A: [-42, -52], B: [-17, -75], C: [17, -75], D: [42, -52],
K: [-42, -15], E: [42, -15],
J: [-42, 22], F: [42, 22],
I: [-26, 60], G: [26, 60],
H: [0, 87]
},
easterling: {
a: [-40, -47.5], b: [0, -47.5], c: [40, -47.5],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-40, 47.5], h: [0, 47.5], i: [40, 47.5],
y: [-42.5, -52.5], z: [0, 65],
j: [-30, -37.5], k: [0, -37.5], l: [30, -37.5],
m: [-30, 37.5], n: [0, 37.5], o: [30, 37.5],
p: [-30, 0], q: [30, 0],
A: [-52, -72], B: [0, -65], D: [52, -72],
K: [-52, -24], E: [52, -24],
J: [-52, 24], F: [52, 24],
I: [-52, 72], G: [52, 72],
H: [0, 65]
},
erebor: {
a: [-40, -40], b: [0, -55], c: [40, -40],
d: [-40, 0], e: [0, 0], f: [40, 0],
g: [-40, 40], h: [0, 55], i: [40, 40],
y: [-50, -50], z: [0, 50],
j: [-35, -35], k: [0, -45], l: [35, -35],
m: [-35, 35], n: [0, 45], o: [35, 35],
p: [-37.5, 0], q: [37.5, 0],
A: [-47, -46], B: [-22, -81], C: [22, -81], D: [47, -46],
K: [-66.5, 0], E: [66.5, 0],
J: [-47, 46], F: [47, 46],
I: [-22, 81], G: [22, 81]
},
ironHills: {
a: [-43.75, -50], b: [0, -50], c: [43.75, -50],
d: [-43.25, 0], e: [0, 0], f: [43.25, 0],
g: [-42.5, 42.5], h: [0, 50], i: [42.5, 42.5],
y: [-50, -50], z: [0, 62.5],
j: [-32.5, -32.5], k: [0, -40], l: [32.5, -32.5],
m: [-32.5, 32.5], n: [0, 40], o: [32.5, 32.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-61, -67], B: [-22, -74], C: [22, -74], D: [61, -67],
K: [-59, -20], E: [59, -20],
J: [-57, 26], F: [57, 26],
I: [-33, 64], G: [33, 64],
H: [0, 88]
},
urukHai: {
a: [-40, -45], b: [0, -45], c: [40, -45],
d: [-36, 0], e: [0, 0], f: [36, 0],
g: [-32.25, 40], h: [0, 40], i: [32.25, 40],
y: [-50, -50], z: [0, 40],
j: [-32.5, -32.5], k: [0, -37.5], l: [32.5, -32.5],
m: [-27.5, 27.5], n: [0, 32.5], o: [27.5, 27.5],
p: [-37.5, 0], q: [37.5, 0],
A: [-31, -79], B: [-1, -90], C: [31, -74], D: [61, -57],
K: [-55, -19], E: [53, -19],
J: [-45, 19], F: [45, 19],
I: [-33, 57], G: [35, 57],
H: [0, 57], L: [-39, -50]
},
moriaOrc: {
a: [-37.5, -37.5], b: [0, -37.5], c: [37.5, -37.5],
d: [-37.5, 0], e: [0, 0], f: [37.5, 0],
g: [-37.5, 37.5], h: [0, 37.5], i: [37.5, 37.5],
y: [-50, -50], z: [0, 40],
j: [-30, -30], k: [0, -30], l: [30, -30],
m: [-30, 30], n: [0, 30], o: [30, 30],
p: [-30, 0], q: [30, 0],
A: [-48, -48], B: [-16, -50], C: [16, -46], D: [39, -61],
K: [-52, -19], E: [52, -26],
J: [-42, 9], F: [52, 9],
I: [-31, 40], G: [40, 43],
H: [4, 47]
}
};
const shieldSize = {
horsehead: .9, horsehead2: .9, polish: .85, swiss: .95,
boeotian: .75, roman: .95, kite: .65, targe2: .9, pavise: .9, wedged: .95,
flag: .7, pennon: .5, guidon: .65, banner: .8, dovetail: .8, pennant: .6,
oval: .95, vesicaPiscis: .8, diamond: .8, no: 1.2,
fantasy1: .8, fantasy2: .7, fantasy3: .7, fantasy5: .9,
noldor: .5, gondor: .75, easterling: .8, erebor: .9, urukHai: .8, moriaOrc: .7
}
const shieldBox = {
heater: "0 10 200 200",
spanish: "0 10 200 200",
french: "0 10 200 200",
horsehead: "0 10 200 200",
horsehead2: "0 10 200 200",
polish: "0 0 200 200",
hessen: "0 5 200 200",
swiss: "0 10 200 200",
boeotian: "0 0 200 200",
roman: "0 0 200 200",
kite: "0 0 200 200",
oldFrench: "0 10 200 200",
renaissance: "0 5 200 200",
baroque: "0 10 200 200",
targe: "0 0 200 200",
targe2: "0 0 200 200",
pavise: "0 0 200 200",
wedged: "0 10 200 200",
flag: "0 0 200 200",
pennon: "2.5 0 200 200",
guidon: "2.5 0 200 200",
banner: "0 10 200 200",
dovetail: "0 10 200 200",
gonfalon: "0 10 200 200",
pennant: "0 0 200 200",
round: "0 0 200 200",
oval: "0 0 200 200",
vesicaPiscis: "0 0 200 200",
square: "0 0 200 200",
diamond: "0 0 200 200",
no: "0 0 200 200",
fantasy1: "0 0 200 200",
fantasy2: "0 5 200 200",
fantasy3: "0 5 200 200",
fantasy4: "0 5 200 200",
fantasy5: "0 0 200 200",
noldor: "0 0 200 200",
gondor: "0 5 200 200",
easterling: "0 0 200 200",
erebor: "0 0 200 200",
ironHills: "0 5 200 200",
urukHai: "0 0 200 200",
moriaOrc: "0 0 200 200"
}
async function draw(id, coa) {
const {division, ordinaries = [], charges = []} = coa;
const ordinariesRegular = ordinaries.filter(o => !o.above);
const ordinariesAboveCharges = ordinaries.filter(o => o.above);
const shieldPath = document.getElementById(coa.shield).querySelector("path").getAttribute("d");
const tDiv = division ? division.t.includes("-") ? division.t.split("-")[1] : division.t : null;
const positions = shieldPositions[coa.shield];
const sizeModifier = shieldSize[coa.shield] || 1;
const viewBox = shieldBox[coa.shield] || "0 0 200 200";
const coaDefs = document.getElementById("coaDefs");
const chargesGroup = coaDefs.querySelector("#charges");
let svg = `
<svg id="${id}" xmlns="http://www.w3.org/2000/svg" width=200 height=200 viewBox="${viewBox}">
<defs>
${division ? `<clipPath id="divisionClip_${id}">${getTemplate(division.division, division.line)}</clipPath>` : ''}
</defs>
<g clip-path="url(#${coa.shield})">
<rect x=0 y=0 width=200 height=200 fill="${clr(coa.t1)}"/>
${templateDivision()}
${templateAboveAll()}
</g>
<path d="${shieldPath}" fill="url(#backlight)" stroke="#333"/>
</svg>
`;
// insert coa svg to coaDefs
coaDefs.querySelector("#coas").insertAdjacentHTML("beforeend", svg);
// fetch charges
if (charges.length) {
const defs = document.getElementById(id).querySelector("defs");
const uniqueCharges = [...new Set(charges.map(charge => charge.charge))];
uniqueCharges.forEach(charge => fetchCharge(charge, defs));
}
function templateDivision() {
if (!division) return "";
let svg = "";
// In field part
for (const ordinary of ordinariesRegular) {
if (ordinary.divided === "field") svg += templateOrdinary(ordinary, ordinary.t); else
if (ordinary.divided === "counter") svg += templateOrdinary(ordinary, tDiv);
}
for (const charge of charges) {
if (charge.divided === "field") svg += templateCharge(charge, charge.t); else
if (charge.divided === "counter") svg += templateCharge(charge, tDiv);
}
for (const ordinary of ordinariesAboveCharges) {
if (ordinary.divided === "field") svg += templateOrdinary(ordinary, ordinary.t); else
if (ordinary.divided === "counter") svg += templateOrdinary(ordinary, tDiv);
}
// In division part
svg += `
<g clip-path="url(#divisionClip_${id})">
<rect x=0 y=0 width=200 height=200 fill="${clr(division.t)}"/>
`;
for (const ordinary of ordinariesRegular) {
if (ordinary.divided === "division") svg += templateOrdinary(ordinary, ordinary.t); else
if (ordinary.divided === "counter") svg += templateOrdinary(ordinary, coa.t1);
}
for (const charge of charges) {
if (charge.divided === "division") svg += templateCharge(charge, charge.t); else
if (charge.divided === "counter") svg += templateCharge(charge, coa.t1);
}
for (const ordinary of ordinariesAboveCharges) {
if (ordinary.divided === "division") svg += templateOrdinary(ordinary, ordinary.t); else
if (ordinary.divided === "counter") svg += templateOrdinary(ordinary, coa.t1);
}
return svg += `</g>`
}
function templateAboveAll() {
let svg = "";
ordinariesRegular.filter(o => !o.divided).forEach(ordinary => {
svg += templateOrdinary(ordinary, ordinary.t);
});
charges.filter(o => !o.divided || !division).forEach(charge => {
svg += templateCharge(charge, charge.t);
});
ordinariesAboveCharges.filter(o => !o.divided).forEach(ordinary => {
svg += templateOrdinary(ordinary, ordinary.t);
})
return svg;
}
function templateOrdinary(ordinary, tincture) {
const fill = clr(tincture);
let svg = `<g fill="${fill}" stroke="none">`;
if (ordinary.ordinary === "bordure") svg += `<path d="${shieldPath}" fill="none" stroke="${fill}" stroke-width="16.7%"/>`;
else if (ordinary.ordinary === "orle") svg += `<path d="${shieldPath}" fill="none" stroke="${fill}" stroke-width="5%" transform="scale(.85)" transform-origin="center">`;
else svg += getTemplate(ordinary.ordinary, ordinary.line);
return svg + `</g>`;
}
function templateCharge(charge, tincture) {
const fill = clr(tincture);
const chargePositions = [...new Set(charge.p)].filter(position => positions[position]);
let svg = "";
svg += `<g fill="${fill}" stroke="#000">`;
for (const p of chargePositions) {
const transform = getElTransform(charge, p);
svg += `<use href="#${charge.charge}_${id}" transform="${transform}" transform-origin="center"></use>`;
}
return svg + `</g>`;
function getElTransform(c, p) {
const [x, y] = positions[p];
const s = (c.size || 1) * sizeModifier;
const scale = c.sinister || c.reversed ? `${c.sinister ? "-" : ""}${s}, ${c.reversed ? "-" : ""}${s}` : s;
return `translate(${x} ${y}) scale(${scale})`;
}
}
// get color or link to pattern
function clr(tincture) {
if (colors[tincture]) return colors[tincture];
const pattern = document.getElementById(tincture);
if (!pattern) renderPattern(tincture);
return "url(#"+tincture+")";
}
function renderPattern(tincture) {
const [pattern, t1, t2, size] = tincture.split("-");
const semy = pattern.slice(0, 4) === "semy";
const template = document.getElementById(semy ? "semy" : pattern);
let html = template.innerHTML.replace(/{id}/, tincture);
const width = template.querySelector("pattern").getAttribute("width");
const height = template.querySelector("pattern").getAttribute("height");
if (t1) html = html.replace(/{c1}/g, clr(t1));
if (t2) html = html.replace(/{c2}/g, clr(t2));
document.getElementById("patterns").insertAdjacentHTML("beforeend", html);
if (semy) {
const charge = pattern.split("_of_")[1];
const el = document.getElementById(tincture);
fetch("https://azgaar.github.io/Armoria/charges/"+charge+".svg").then(res => {
if (res.ok) return res.text();
else throw new Error('Cannot fetch charge');
}).then(text => {
const html = document.createElement("html");
html.innerHTML = text;
el.innerHTML = el.innerHTML.replace(/<charge>/g, html.querySelector("g").outerHTML);
});
}
if (size) {
let mod = 1;
if (size === "small") mod = .5;
if (size === "smaller") mod = .25;
if (size === "smallest") mod = .125;
if (size === "big") mod = 2;
const el = document.getElementById(tincture);
el.setAttribute("width", width * mod);
el.setAttribute("height", height * mod);
}
}
function getTemplate(templateId, lineId) {
if (!lineId) return document.getElementById(templateId)?.innerHTML;
const template = document.getElementById(templateId);
const line = document.getElementById(lineId) ? document.getElementById(lineId) : document.getElementById("straight");
return template.innerHTML.replace(/{line}/g, line.getAttribute("d")).replace(/dpath/g, "d");
}
function fetchCharge(charge, defs) {
if (charge === "inescutcheon") {
const g = `<g id="inescutcheon_${id}"><path transform="scale(.33)" transform-origin="center" d="${shieldPath}"/></g>`;
defs.insertAdjacentHTML("beforeend", g);
return;
}
fetch("https://azgaar.github.io/Armoria/charges/"+charge+".svg").then(res => {
if (res.ok) return res.text();
else throw new Error('Cannot fetch charge');
}).then(text => {
const el = document.createElement("html");
el.innerHTML = text;
const g = el.querySelector("g");
g.id = charge + "_" + id;
defs.insertAdjacentHTML("beforeend", g.outerHTML);
});
}
}
// async render coa if it does not exist
const trigger = function(id, coa) {
if (!document.getElementById(id)) draw(id, coa);
}
return {trigger};
})));

View file

@ -423,7 +423,7 @@ async function quickSave() {
if (customization) {tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error"); return;}
const blob = await getMapData();
if (blob) ldb.set("lastMap", blob); // auto-save map
tip("Map is saved to browser memory", true, "success", 2000);
tip("Map is saved to browser memory. Please also save as .map file to secure progress", true, "success", 2000);
}
function quickLoad() {

108
modules/ui/coa-editor.js Normal file
View file

@ -0,0 +1,108 @@
"use strict";
function editEmblem(type, id, el) {
if (customization) return;
const emblemStates = document.getElementById("emblemStates");
const emblemProvinces = document.getElementById("emblemProvinces");
const emblemBurgs = document.getElementById("emblemBurgs");
const {states, provinces, burgs, cells} = pack;
updateElementSelectors(type, id, el);
$("#emblemEditor").dialog({
title: "Edit Emblem", resizable: true, width: "auto",
position: {my: "left top", at: "left+10 top+10", of: "svg", collision: "fit"}
});
if (modules.editEmblem) return;
modules.editEmblem = true;
// add listeners
emblemStates.addEventListener("input", selectState);
emblemProvinces.addEventListener("input", selectProvince);
emblemBurgs.addEventListener("input", selectBurg);
function updateElementSelectors(type, id, el) {
let state = 0, province = 0, burg = 0;
// set active type
emblemStates.parentElement.className = type === "state" ? "active" : "";
emblemProvinces.parentElement.className = type === "province" ? "active" : "";
emblemBurgs.parentElement.className = type === "burg" ? "active" : "";
// define selected values
if (type === "state") state = el.i;
else if (type === "province") {province = el.i; state = states[el.state].i;}
else {burg = el.i; province = provinces[cells.province[el.cell]].i; state = provinces[province].state;}
// update option list and select actual values
emblemStates.options.length = 0;
const neutralBurgs = burgs.filter(burg => burg.i && !burg.removed && !burg.state);
if (neutralBurgs.length) emblemProvinces.options.add(new Option(states[0].name, 0, false, !state));
const stateList = states.filter(state => state.i && !state.removed);
stateList.forEach(s => emblemStates.options.add(new Option(s.name, s.i, false, s.i === state)));
emblemProvinces.options.length = 0;
emblemProvinces.options.add(new Option("", 0, false, !province));
const provinceList = provinces.filter(province => !province.removed && province.state === state);
provinceList.forEach(p => emblemProvinces.options.add(new Option(p.name, p.i, false, p.i === province)));
emblemBurgs.options.length = 0;
emblemBurgs.options.add(new Option("", 0, false, !burg));
const burgList = burgs.filter(burg => !burg.removed && province ? cells.province[burg.cell] === province : burg.state === state);
burgList.forEach(b => emblemBurgs.options.add(new Option(b.name, b.i, false, b.i === burg)));
emblemBurgs.options[0].disabled = true;
COArenderer.trigger(id, el.coa);
updateEmblemData(type, id, el);
}
function updateEmblemData(type, id, el) {
if (!el.coa) return;
document.getElementById("emblemImage").setAttribute("href", "#" + id);
document.getElementById("emblemArmiger").innerText = el.fullName || el.name;
}
function selectState() {
const state = +this.value;
if (state) {
type = "state";
el = states[state];
id = "stateCOA"+ state;
} else {
// select neutral burg if state is changed to Neutrals
const neutralBurgs = burgs.filter(burg => burg.i && !burg.removed && !burg.state);
if (!neutralBurgs.length) return;
type = "burg";
el = neutralBurgs[0];
id = "burgCOA"+ neutralBurgs[0].i;
}
updateElementSelectors(type, id, el);
}
function selectProvince() {
const province = +this.value;
if (province) {
type = "province";
el = provinces[province];
id = "provinceCOA"+ province;
} else {
// select state if province is changed to null value
const state = +emblemStates.value;
type = "state";
el = states[state];
id = "stateCOA"+ state;
}
updateElementSelectors(type, id, el);
}
function selectBurg() {
const burg = +this.value;
type = "burg";
el = burgs[burg];
id = "burgCOA"+ burg;
updateElementSelectors(type, id, el);
}
}

View file

@ -339,6 +339,7 @@ function showInfo() {
const Reddit = link("https://www.reddit.com/r/FantasyMapGenerator", "Reddit")
const Patreon = link("https://www.patreon.com/azgaar", "Patreon");
const Trello = link("https://trello.com/b/7x832DG4/fantasy-map-generator", "Trello");
const Armoria = link("https://azgaar.github.io/Armoria", "Armoria");
const QuickStart = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Quick-Start-Tutorial", "Quick start tutorial");
const QAA = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Q&A", "Q&A page");
@ -353,9 +354,11 @@ function showInfo() {
<p>The best way to get help is to contact the community on ${Discord} and ${Reddit}.
Before asking questions, please check out the ${QuickStart} and the ${QAA}.</p>
<p>You can track the development process on ${Trello}.</p>
<p>Track the development process on ${Trello}.</p>
Links:
<p>Check out our new project: ${Armoria}, heraldry generator and editor.</p>
<b>Links:</b>
<ul style="columns:2">
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator", "GitHub repository")}</li>
<li>${link("https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/LICENSE", "License")}</li>

View file

@ -42,7 +42,7 @@ function editStates() {
const el = ev.target, cl = el.classList, line = el.parentNode, state = +line.dataset.id;
if (cl.contains("fillRect")) stateChangeFill(el); else
if (cl.contains("name")) editStateName(state); else
if (cl.contains("emblemIcon")) editCOA(state); else
if (cl.contains("coaIcon")) editEmblem("state", "stateCOA"+state, pack.states[state]); else
if (cl.contains("icon-star-empty")) stateCapitalZoomIn(state); else
if (cl.contains("culturePopulation")) changePopulation(state); else
if (cl.contains("icon-pin")) toggleFog(state, cl); else
@ -83,7 +83,6 @@ function editStates() {
totalPopulation += population;
totalBurgs += s.burgs;
const focused = defs.select("#fog #focusState"+s.i).size();
const COAsize = Math.round(15 * +uiSizeInput.value);
if (!s.i) {
// Neutral line
@ -91,7 +90,7 @@ function editStates() {
data-population=${population} data-burgs=${s.burgs} data-color="" data-form="" data-capital="" data-culture="" data-type="" data-expansionism="">
<svg width="9" height="9" class="placeholder"></svg>
<input data-tip="Neutral lands name. Click to change" class="stateName name pointer italic" value="${s.name}" readonly>
<embed class="emblemIcon placeholder hide" type="image/svg+xml" width=${COAsize} height=${COAsize} >
<svg class="coaIcon placeholder hide"></svg>
<input class="stateForm placeholder" value="none">
<span class="icon-star-empty placeholder hide"></span>
<input class="stateCapital placeholder hide">
@ -110,13 +109,14 @@ function editStates() {
</div>`;
continue;
}
const capital = pack.burgs[s.capital].name;
const coaURL = `http://azgaar.github.io/Armoria/?view=1&size=${COAsize}&noedit&coa=${COA.toString(s.coa)}`;
COArenderer.trigger("stateCOA"+s.i, s.coa);
lines += `<div class="states" data-id=${s.i} data-name="${s.name}" data-form="${s.formName}" data-capital="${capital}" data-color="${s.color}" data-cells=${s.cells}
data-area=${area} data-population=${population} data-burgs=${s.burgs} data-culture=${pack.cultures[s.culture].name} data-type=${s.type} data-expansionism=${s.expansionism}>
<svg data-tip="State fill style. Click to change" width=".9em" height=".9em" style="margin-bottom:-1px"><rect x="0" y="0" width="100%" height="100%" fill="${s.color}" class="fillRect pointer"></svg>
<input data-tip="State name. Click to change" class="stateName name pointer" value="${s.name}" readonly>
<embed data-tip="Click to show state COA" class="emblemIcon hide" type="image/svg+xml" width=${COAsize} height=${COAsize} src='${coaURL}'>
<svg data-tip="Click to edit state emblem" class="coaIcon hide" viewBox="0 0 200 200"><use href="#stateCOA${s.i}"></use></svg>
<input data-tip="State form name. Click to change" class="stateForm name pointer" value="${s.formName}" readonly>
<span data-tip="State capital. Click to zoom into view" class="icon-star-empty pointer hide"></span>
<input data-tip="Capital name. Click and type to rename" class="stateCapital hide" value="${capital}" autocorrect="off" spellcheck="false"/>
@ -315,19 +315,6 @@ function editStates() {
document.querySelector("#burgLabel"+capital).textContent = value;
}
function editCOA(state) {
const coa = COA.toString(pack.states[state].coa);
const url = "http://azgaar.github.io/Armoria/?view=1&size=200&noedit&coa=" + coa;
$("#emblemsEditor").dialog({
title: "Emblems Editor", resizable: false, width: fitContent(), close: closeStatesEditor,
position: {my: "left top", at: "left+10 top+10", of: "svg", collision: "fit"}
});
const embed = document.getElementById("emblemsEmbed");
embed.setAttribute("src", url);
}
function changePopulation(state) {
const s = pack.states[state];
if (!s.cells) {tip("State does not have any cells, cannot change population", false, "error"); return;}