mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
v1.0.16
This commit is contained in:
parent
c0a634bec1
commit
5a1b747da8
11 changed files with 182 additions and 51 deletions
|
|
@ -200,6 +200,13 @@ i.icon-lock {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#religionInfo {
|
||||||
|
text-align: center;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
#burgLabels {
|
#burgLabels {
|
||||||
dominant-baseline: alphabetic;
|
dominant-baseline: alphabetic;
|
||||||
text-anchor: middle;
|
text-anchor: middle;
|
||||||
|
|
|
||||||
|
|
@ -1163,8 +1163,7 @@
|
||||||
<tr data-tip="Set grid cells spacing (size)">
|
<tr data-tip="Set grid cells spacing (size)">
|
||||||
<td>Size</td>
|
<td>Size</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="styleGridSize" type="range" min=2 max=50 step=.1 value=10 style="width:42%">
|
<input id="styleGridSize" type="number" min=2 max=50 step=.001 value=10 >
|
||||||
<output id="styleGridSizeOutput" data-tip="Grid cells spacing in pixels">10</output>
|
|
||||||
<output id="styleGridSizeFriendly" data-tip="Distance between two adjacent cells in map scale">(52 mi)</output>
|
<output id="styleGridSizeFriendly" data-tip="Distance between two adjacent cells in map scale">(52 mi)</output>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -1599,7 +1598,7 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr data-tip="Define a number of towns to be placed (if suitable area is enougth)">
|
<tr data-tip="Define a number of towns to be placed (if enough suitable land exists)">
|
||||||
<td>
|
<td>
|
||||||
<i data-locked=0 id="lock_manors" class="icon-lock-open"></i>
|
<i data-locked=0 id="lock_manors" class="icon-lock-open"></i>
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -2780,7 +2779,8 @@
|
||||||
<button id="religionsEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
|
<button id="religionsEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
|
||||||
<button id="religionsLegend" data-tip="Toggle Legend box" class="icon-list-bullet"></button>
|
<button id="religionsLegend" data-tip="Toggle Legend box" class="icon-list-bullet"></button>
|
||||||
<button id="religionsPercentage" data-tip="Toggle percentage / absolute values display mode" class="icon-percent"></button>
|
<button id="religionsPercentage" data-tip="Toggle percentage / absolute values display mode" class="icon-percent"></button>
|
||||||
<button id="religionsExtinct" data-tip="Show/hide extinct religions (religions without believers)" class="icon-adjust"></button>
|
<button id="religionsHeirarchy" data-tip="Show religions hierarchy tree" class="icon-fork"></button>
|
||||||
|
<button id="religionsExtinct" data-tip="Show/hide extinct religions (religions without cells)" class="icon-adjust"></button>
|
||||||
|
|
||||||
<button id="religionsManually" data-tip="Manually re-assign religions" class="icon-brush"></button>
|
<button id="religionsManually" data-tip="Manually re-assign religions" class="icon-brush"></button>
|
||||||
<div id="religionsManuallyButtons" style="display: none">
|
<div id="religionsManuallyButtons" style="display: none">
|
||||||
|
|
|
||||||
1
libs/jquery-ui.css
vendored
1
libs/jquery-ui.css
vendored
|
|
@ -362,6 +362,7 @@ body .ui-dialog {
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: .5em 1em;
|
padding: .5em 1em;
|
||||||
background: none;
|
background: none;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
.ui-dialog .ui-dialog-buttonpane {
|
.ui-dialog .ui-dialog-buttonpane {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
|
||||||
2
main.js
2
main.js
|
|
@ -397,7 +397,7 @@ function applyDefaultStyle() {
|
||||||
|
|
||||||
coastline.attr("opacity", .5).attr("stroke", "#1f3846").attr("stroke-width", .7).attr("filter", "url(#dropShadow)");
|
coastline.attr("opacity", .5).attr("stroke", "#1f3846").attr("stroke-width", .7).attr("filter", "url(#dropShadow)");
|
||||||
styleCoastlineAuto.checked = true;
|
styleCoastlineAuto.checked = true;
|
||||||
relig.attr("opacity", .6).attr("stroke", "#777777").attr("stroke-width", .2).attr("filter", null).attr("fill-rule", "evenodd");
|
relig.attr("opacity", .7).attr("stroke", "#404040").attr("stroke-width", .7).attr("filter", null).attr("fill-rule", "evenodd");
|
||||||
cults.attr("opacity", .6).attr("stroke", "#777777").attr("stroke-width", .5).attr("filter", null).attr("fill-rule", "evenodd");
|
cults.attr("opacity", .6).attr("stroke", "#777777").attr("stroke-width", .5).attr("filter", null).attr("fill-rule", "evenodd");
|
||||||
icons.selectAll("g").attr("opacity", null).attr("fill", "#ffffff").attr("stroke", "#3e3e4b").attr("filter", null).attr("mask", null);
|
icons.selectAll("g").attr("opacity", null).attr("fill", "#ffffff").attr("stroke", "#3e3e4b").attr("filter", null).attr("mask", null);
|
||||||
landmass.attr("opacity", 1).attr("fill", "#eef6fb").attr("filter", null);
|
landmass.attr("opacity", 1).attr("fill", "#eef6fb").attr("filter", null);
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,8 @@
|
||||||
const form = rw(forms.Folk);
|
const form = rw(forms.Folk);
|
||||||
const name = c.name + " " + rw(types[form]);
|
const name = c.name + " " + rw(types[form]);
|
||||||
const deity = form === "Animism" ? null : getDeityName(c.i);
|
const deity = form === "Animism" ? null : getDeityName(c.i);
|
||||||
const color = getRandomColor(); // `url(#hatch${rand(8,13)})`;
|
const color = getMixedColor(c.color, .1, 0); // `url(#hatch${rand(8,13)})`;
|
||||||
religions.push({i: c.i, name, color, culture: c.i, type:"Folk", form, deity});
|
religions.push({i: c.i, name, color, culture: c.i, type:"Folk", form, deity, center: c.center, origin:0});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (religionsInput.value == 0 || pack.cultures.length < 2) return;
|
if (religionsInput.value == 0 || pack.cultures.length < 2) return;
|
||||||
|
|
@ -101,10 +101,11 @@
|
||||||
// add "Old" to name of the folk religion on this culture
|
// add "Old" to name of the folk religion on this culture
|
||||||
const folk = religions.find(r => expansion === "culture" && r.culture === culture && r.type === "Folk");
|
const folk = religions.find(r => expansion === "culture" && r.culture === culture && r.type === "Folk");
|
||||||
if (folk && folk.name.slice(0,3) !== "Old") folk.name = "Old " + folk.name;
|
if (folk && folk.name.slice(0,3) !== "Old") folk.name = "Old " + folk.name;
|
||||||
|
const origin = religions.find(r => r.culture === culture && r.type === "Folk").i || 0;
|
||||||
|
|
||||||
const expansionism = rand(3, 8);
|
const expansionism = rand(3, 8);
|
||||||
const color = getRandomColor(); // `url(#hatch${rand(0,5)})`;
|
const color = getMixedColor(religions[origin].color, .3, 0); // `url(#hatch${rand(0,5)})`;
|
||||||
religions.push({i: religions.length, name, color, culture, type:"Organized", form, deity, expansion, expansionism, center});
|
religions.push({i: religions.length, name, color, culture, type:"Organized", form, deity, expansion, expansionism, center, origin});
|
||||||
religionsTree.add([x, y]);
|
religionsTree.add([x, y]);
|
||||||
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "blue");
|
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "blue");
|
||||||
}
|
}
|
||||||
|
|
@ -120,11 +121,12 @@
|
||||||
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
|
if (religionsTree.find(x, y, s) !== undefined) continue; // to close to existing religion
|
||||||
|
|
||||||
const culture = cells.culture[center];
|
const culture = cells.culture[center];
|
||||||
|
const origin = religions.find(r => r.culture === culture && r.type === "Folk").i || 0;
|
||||||
const deity = getDeityName(culture);
|
const deity = getDeityName(culture);
|
||||||
const name = getCultName(form, center);
|
const name = getCultName(form, center);
|
||||||
const expansionism = gauss(1.1, .5, 0, 5);
|
const expansionism = gauss(1.1, .5, 0, 5);
|
||||||
const color = getRandomColor(); // "url(#hatch7)";
|
const color = getMixedColor(cultures[culture].color, .5, 0); // "url(#hatch7)";
|
||||||
religions.push({i: religions.length, name, color, culture, type:"Cult", form, deity, expansion:"global", expansionism, center});
|
religions.push({i: religions.length, name, color, culture, type:"Cult", form, deity, expansion:"global", expansionism, center, origin});
|
||||||
religionsTree.add([x, y]);
|
religionsTree.add([x, y]);
|
||||||
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red");
|
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "red");
|
||||||
}
|
}
|
||||||
|
|
@ -145,14 +147,15 @@
|
||||||
const culture = cells.culture[center];
|
const culture = cells.culture[center];
|
||||||
const name = getCultName("Heresy", center);
|
const name = getCultName("Heresy", center);
|
||||||
const expansionism = gauss(1.2, .5, 0, 5);
|
const expansionism = gauss(1.2, .5, 0, 5);
|
||||||
const color = getRandomColor(); // "url(#hatch6)";
|
const color = getMixedColor(r.color, .4, .2); // "url(#hatch6)";
|
||||||
religions.push({i: religions.length, name, color, culture, type:"Heresy", form:"Heresy", deity: r.deity, expansion:"global", expansionism, center});
|
religions.push({i: religions.length, name, color, culture, type:"Heresy", form:r.form, deity: r.deity, expansion:"global", expansionism, center, origin:r.i});
|
||||||
religionsTree.add([x, y]);
|
religionsTree.add([x, y]);
|
||||||
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green");
|
//debug.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).attr("fill", "green");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expandHeresies();
|
expandHeresies();
|
||||||
|
checkCenters();
|
||||||
|
|
||||||
console.timeEnd('generateReligions');
|
console.timeEnd('generateReligions');
|
||||||
}
|
}
|
||||||
|
|
@ -162,22 +165,23 @@
|
||||||
const r = cells.religion[center];
|
const r = cells.religion[center];
|
||||||
const i = religions.length;
|
const i = religions.length;
|
||||||
const culture = cells.culture[center];
|
const culture = cells.culture[center];
|
||||||
const color = getRandomColor();
|
const color = getMixedColor(religions[r].color, .3, 0);
|
||||||
|
|
||||||
const type = religions[r].type === "Organized" ? rw({Organized:4, Cult:1, Heresy:2}) : rw({Organized:5, Cult:2});
|
const type = religions[r].type === "Organized" ? rw({Organized:4, Cult:1, Heresy:2}) : rw({Organized:5, Cult:2});
|
||||||
const form = rw(forms[type]);
|
const form = rw(forms[type]);
|
||||||
const deity = form === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture);
|
const deity = type === "Heresy" ? religions[r].deity : form === "Non-theism" ? null : getDeityName(culture);
|
||||||
|
|
||||||
let name, expansion;
|
let name, expansion;
|
||||||
if (type === "Organized") [name, expansion] = getReligionName(form, deity, center)
|
if (type === "Organized") [name, expansion] = getReligionName(form, deity, center)
|
||||||
else {name = getCultName(form, center); expansion = "global";}
|
else {name = getCultName(form, center); expansion = "global";}
|
||||||
|
const formName = type === "Heresy" ? religions[r].form : form;
|
||||||
religions.push({i, name, color, culture, type, form, deity, expansion, expansionism:0, center, area: 0, rural: 0, urban: 0});
|
const code = getCode(name);
|
||||||
|
religions.push({i, name, color, culture, type, form:formName, deity, expansion, expansionism:0, center, cells:0, area:0, rural:0, urban:0, origin:r, code});
|
||||||
|
cells.religion[center] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// growth algorithm to assign cells to religions
|
// growth algorithm to assign cells to religions
|
||||||
const expandReligions = function() {
|
const expandReligions = function() {
|
||||||
console.time("expandReligions");
|
|
||||||
const cells = pack.cells, religions = pack.religions;
|
const cells = pack.cells, religions = pack.religions;
|
||||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||||
const cost = [];
|
const cost = [];
|
||||||
|
|
@ -215,17 +219,15 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.timeEnd("expandReligions");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// growth algorithm to assign cells to heresies
|
// growth algorithm to assign cells to heresies
|
||||||
const expandHeresies = function() {
|
const expandHeresies = function() {
|
||||||
console.time("expandHeresies");
|
|
||||||
const cells = pack.cells, religions = pack.religions;
|
const cells = pack.cells, religions = pack.religions;
|
||||||
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
|
||||||
const cost = [];
|
const cost = [];
|
||||||
|
|
||||||
religions.filter(r => r.form === "Heresy").forEach(r => {
|
religions.filter(r => r.type === "Heresy").forEach(r => {
|
||||||
const b = cells.religion[r.center]; // "base" religion id
|
const b = cells.religion[r.center]; // "base" religion id
|
||||||
cells.religion[r.center] = r.i; // heresy id
|
cells.religion[r.center] = r.i; // heresy id
|
||||||
queue.queue({e:r.center, p:0, r:r.i, b});
|
queue.queue({e:r.center, p:0, r:r.i, b});
|
||||||
|
|
@ -253,8 +255,31 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//debug.selectAll(".text").data(cost).enter().append("text").attr("x", (d, e) => cells.p[e][0]-1).attr("y", (d, e) => cells.p[e][1]-1).text(d => d ? rn(d) : "").attr("font-size", 2);
|
}
|
||||||
console.timeEnd("expandHeresies");
|
|
||||||
|
function checkCenters() {
|
||||||
|
const cells = pack.cells, religions = pack.religions;
|
||||||
|
|
||||||
|
religions.filter(r => r.i).forEach(r => {
|
||||||
|
r.code = getCode(r.name);
|
||||||
|
|
||||||
|
// move religion center if it's not within religion area after expansion
|
||||||
|
if (cells.religion[r.center] === r.i) return; // in area
|
||||||
|
const religCells = cells.i.filter(i => cells.religion[i] === r.i);
|
||||||
|
if (!religCells.length) return; // extinct religion
|
||||||
|
r.center = religCells.sort((a,b) => b.pop - a.pop)[0];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign a unique two-letters code (abbreviation)
|
||||||
|
function getCode(rawName) {
|
||||||
|
const name = rawName.replace("Old ", ""); // remove Old prefix
|
||||||
|
const words = name.split(" "), letters = words.join("");
|
||||||
|
let code = words.length === 2 ? words[0][0]+words[1][0] : letters.slice(0,2);
|
||||||
|
for (let i=1; i < letters.length-1 && pack.religions.some(r => r.code === code); i++) {
|
||||||
|
code = letters[0] + letters[i].toUpperCase();
|
||||||
|
}
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get supreme deity name
|
// get supreme deity name
|
||||||
|
|
|
||||||
|
|
@ -671,6 +671,12 @@ function parseLoadedData(data) {
|
||||||
|
|
||||||
// labels should be toggled via style attribute, so remove display attribute
|
// labels should be toggled via style attribute, so remove display attribute
|
||||||
labels.attr("display", null);
|
labels.attr("display", null);
|
||||||
|
|
||||||
|
// v 1.0 added religions heirarchy tree
|
||||||
|
pack.religions.forEach(r => {
|
||||||
|
r.origin = 0;
|
||||||
|
r.code = r.name.slice(0, 2);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -231,9 +231,12 @@ document.addEventListener("keydown", function(event) {
|
||||||
const active = document.activeElement.tagName;
|
const active = document.activeElement.tagName;
|
||||||
if (active === "INPUT" || active === "SELECT" || active === "TEXTAREA") return; // don't trigger if user inputs a text
|
if (active === "INPUT" || active === "SELECT" || active === "TEXTAREA") return; // don't trigger if user inputs a text
|
||||||
if (active === "DIV" && document.activeElement.contentEditable === "true") return; // don't trigger if user inputs a text
|
if (active === "DIV" && document.activeElement.contentEditable === "true") return; // don't trigger if user inputs a text
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
const key = event.keyCode, ctrl = event.ctrlKey, shift = event.shiftKey, meta = event.metaKey;
|
const key = event.keyCode, ctrl = event.ctrlKey, shift = event.shiftKey, meta = event.metaKey;
|
||||||
if (key === 27) {closeDialogs(); hideOptions();} // Escape to close all dialogs
|
if (key === 27) {closeDialogs(); hideOptions();} // Escape to close all dialogs
|
||||||
else if (key === 9) {toggleOptions(event); event.preventDefault();} // Tab to toggle options
|
else if (key === 9) toggleOptions(event); // Tab to toggle options
|
||||||
|
|
||||||
else if (key === 113) regeneratePrompt(); // "F2" for new map
|
else if (key === 113) regeneratePrompt(); // "F2" for new map
|
||||||
else if (key === 46) removeElementOnKey(); // "Delete" to remove the selected element
|
else if (key === 46) removeElementOnKey(); // "Delete" to remove the selected element
|
||||||
|
|
|
||||||
|
|
@ -343,17 +343,18 @@ styleClippingInput.addEventListener("change", function() {
|
||||||
|
|
||||||
styleGridType.addEventListener("change", function() {
|
styleGridType.addEventListener("change", function() {
|
||||||
if (layerIsOn("toggleGrid")) drawGrid();
|
if (layerIsOn("toggleGrid")) drawGrid();
|
||||||
|
calculateFriendlyGridSize();
|
||||||
});
|
});
|
||||||
|
|
||||||
styleGridSize.addEventListener("input", function() {
|
styleGridSize.addEventListener("input", function() {
|
||||||
if (layerIsOn("toggleGrid")) drawGrid();
|
if (layerIsOn("toggleGrid")) drawGrid();
|
||||||
styleGridSizeOutput.value = this.value;
|
|
||||||
calculateFriendlyGridSize();
|
calculateFriendlyGridSize();
|
||||||
});
|
});
|
||||||
|
|
||||||
function calculateFriendlyGridSize() {
|
function calculateFriendlyGridSize() {
|
||||||
const size = styleGridSize.value * Math.cos(30 * Math.PI / 180) * 2;;
|
const square = styleGridType.value === "square";
|
||||||
const friendly = "(" + rn(size * distanceScaleInput.value) + " " + distanceUnitInput.value + ")";
|
const size = square ? styleGridSize.value : styleGridSize.value * Math.cos(30 * Math.PI / 180) * 2;
|
||||||
|
const friendly = `${rn(size * distanceScaleInput.value, 2)} ${distanceUnitInput.value}`;
|
||||||
styleGridSizeFriendly.value = friendly;
|
styleGridSizeFriendly.value = friendly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ function editReligions() {
|
||||||
|
|
||||||
const body = document.getElementById("religionsBody");
|
const body = document.getElementById("religionsBody");
|
||||||
const animate = d3.transition().duration(1500).ease(d3.easeSinIn);
|
const animate = d3.transition().duration(1500).ease(d3.easeSinIn);
|
||||||
drawReligionCenters();
|
|
||||||
refreshReligionsEditor();
|
refreshReligionsEditor();
|
||||||
|
drawReligionCenters();
|
||||||
|
|
||||||
if (modules.editReligions) return;
|
if (modules.editReligions) return;
|
||||||
modules.editReligions = true;
|
modules.editReligions = true;
|
||||||
|
|
@ -25,6 +25,7 @@ function editReligions() {
|
||||||
document.getElementById("religionsEditorRefresh").addEventListener("click", refreshReligionsEditor);
|
document.getElementById("religionsEditorRefresh").addEventListener("click", refreshReligionsEditor);
|
||||||
document.getElementById("religionsLegend").addEventListener("click", toggleLegend);
|
document.getElementById("religionsLegend").addEventListener("click", toggleLegend);
|
||||||
document.getElementById("religionsPercentage").addEventListener("click", togglePercentageMode);
|
document.getElementById("religionsPercentage").addEventListener("click", togglePercentageMode);
|
||||||
|
document.getElementById("religionsHeirarchy").addEventListener("click", showHierarchy);
|
||||||
document.getElementById("religionsExtinct").addEventListener("click", toggleExtinct);
|
document.getElementById("religionsExtinct").addEventListener("click", toggleExtinct);
|
||||||
document.getElementById("religionsManually").addEventListener("click", enterReligionsManualAssignent);
|
document.getElementById("religionsManually").addEventListener("click", enterReligionsManualAssignent);
|
||||||
document.getElementById("religionsManuallyApply").addEventListener("click", applyReligionsManualAssignent);
|
document.getElementById("religionsManuallyApply").addEventListener("click", applyReligionsManualAssignent);
|
||||||
|
|
@ -39,11 +40,12 @@ function editReligions() {
|
||||||
|
|
||||||
function religionsCollectStatistics() {
|
function religionsCollectStatistics() {
|
||||||
const cells = pack.cells, religions = pack.religions;
|
const cells = pack.cells, religions = pack.religions;
|
||||||
religions.forEach(r => r.area = r.rural = r.urban = 0);
|
religions.forEach(r => r.cells = r.area = r.rural = r.urban = 0);
|
||||||
|
|
||||||
for (const i of cells.i) {
|
for (const i of cells.i) {
|
||||||
if (cells.h[i] < 20) continue;
|
if (cells.h[i] < 20) continue;
|
||||||
const r = cells.religion[i];
|
const r = cells.religion[i];
|
||||||
|
religions[r].cells += 1;
|
||||||
religions[r].area += cells.area[i];
|
religions[r].area += cells.area[i];
|
||||||
religions[r].rural += cells.pop[i];
|
religions[r].rural += cells.pop[i];
|
||||||
if (cells.burg[i]) religions[r].urban += pack.burgs[cells.burg[i]].population;
|
if (cells.burg[i]) religions[r].urban += pack.burgs[cells.burg[i]].population;
|
||||||
|
|
@ -62,7 +64,7 @@ function editReligions() {
|
||||||
const rural = r.rural * populationRate.value;
|
const rural = r.rural * populationRate.value;
|
||||||
const urban = r.urban * populationRate.value * urbanization.value;
|
const urban = r.urban * populationRate.value * urbanization.value;
|
||||||
const population = rn(rural + urban);
|
const population = rn(rural + urban);
|
||||||
if (r.i && !population && body.dataset.extinct !== "show") continue; // hide extinct religions
|
if (r.i && !r.cells && body.dataset.extinct !== "show") continue; // hide extinct religions
|
||||||
const populationTip = `Believers: ${si(population)}; Rural areas: ${si(rural)}; Urban areas: ${si(urban)}`;
|
const populationTip = `Believers: ${si(population)}; Rural areas: ${si(rural)}; Urban areas: ${si(urban)}`;
|
||||||
totalArea += area;
|
totalArea += area;
|
||||||
totalPopulation += population;
|
totalPopulation += population;
|
||||||
|
|
@ -136,18 +138,38 @@ function editReligions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function religionHighlightOn(event) {
|
function religionHighlightOn(event) {
|
||||||
|
const religion = +event.target.dataset.id;
|
||||||
|
const info = document.getElementById("religionInfo");
|
||||||
|
if (info) {
|
||||||
|
d3.select("#religionHierarchy").select("g[data-id='"+religion+"'] > path")
|
||||||
|
.attr("stroke", "#c13119").attr("stroke-width", 2);
|
||||||
|
const r = pack.religions[religion];
|
||||||
|
const type = r.name.includes(r.type) ? ""
|
||||||
|
: r.type === "Folk" || r.type === "Organized"
|
||||||
|
? ". " + r.type + " religion" : ". " + r.type;
|
||||||
|
const form = r.form === r.type || r.name.includes(r.form) ? "" : ". " + r.form;
|
||||||
|
const rural = r.rural * populationRate.value;
|
||||||
|
const urban = r.urban * populationRate.value * urbanization.value;
|
||||||
|
const population = rural + urban > 0 ? ". " + si(rn(rural + urban)) + " believers" : ". Extinct";
|
||||||
|
info.innerHTML = `${r.name}${type}${form}${population}`;
|
||||||
|
}
|
||||||
|
|
||||||
if (!layerIsOn("toggleReligions")) return;
|
if (!layerIsOn("toggleReligions")) return;
|
||||||
if (customization) return;
|
if (customization) return;
|
||||||
const religion = +event.target.dataset.id;
|
|
||||||
relig.select("#religion"+religion).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#c13119");
|
relig.select("#religion"+religion).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#c13119");
|
||||||
debug.select("#cultureCenter"+religion).raise().transition(animate).attr("r", 8).attr("stroke", "#c13119");
|
debug.select("#religionsCenter"+religion).raise().transition(animate).attr("r", 8).attr("stroke-width", 2).attr("stroke", "#c13119");
|
||||||
}
|
}
|
||||||
|
|
||||||
function religionHighlightOff(event) {
|
function religionHighlightOff(event) {
|
||||||
if (!layerIsOn("toggleReligions")) return;
|
|
||||||
const religion = +event.target.dataset.id;
|
const religion = +event.target.dataset.id;
|
||||||
|
const info = document.getElementById("religionInfo");
|
||||||
|
if (info) {
|
||||||
|
d3.select("#religionHierarchy").select("g[data-id='"+religion+"'] > path")
|
||||||
|
.attr("stroke", "#333333").attr("stroke-width", 1);
|
||||||
|
info.innerHTML = "‍";
|
||||||
|
}
|
||||||
relig.select("#religion"+religion).transition().attr("stroke-width", null).attr("stroke", null);
|
relig.select("#religion"+religion).transition().attr("stroke-width", null).attr("stroke", null);
|
||||||
debug.select("#cultureCenter"+religion).transition().attr("r", 6).attr("stroke", null);
|
debug.select("#religionsCenter"+religion).transition().attr("r", 4).attr("stroke-width", 1.2).attr("stroke", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function religionChangeColor() {
|
function religionChangeColor() {
|
||||||
|
|
@ -159,7 +181,7 @@ function editReligions() {
|
||||||
el.setAttribute("fill", fill);
|
el.setAttribute("fill", fill);
|
||||||
pack.religions[religion].color = fill;
|
pack.religions[religion].color = fill;
|
||||||
relig.select("#religion"+religion).attr("fill", fill);
|
relig.select("#religion"+religion).attr("fill", fill);
|
||||||
debug.select("#cultureCenter"+religion).attr("fill", fill);
|
debug.select("#religionsCenter"+religion).attr("fill", fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
openPicker(currentFill, callback);
|
openPicker(currentFill, callback);
|
||||||
|
|
@ -202,28 +224,37 @@ function editReligions() {
|
||||||
if (customization) return;
|
if (customization) return;
|
||||||
const religion = +this.parentNode.dataset.id;
|
const religion = +this.parentNode.dataset.id;
|
||||||
relig.select("#religion"+religion).remove();
|
relig.select("#religion"+religion).remove();
|
||||||
debug.select("#cultureCenter"+religion).remove();
|
debug.select("#religionsCenter"+religion).remove();
|
||||||
|
|
||||||
pack.cells.religion.forEach((r, i) => {if(r === religion) pack.cells.religion[i] = 0;});
|
pack.cells.religion.forEach((r, i) => {if(r === religion) pack.cells.religion[i] = 0;});
|
||||||
pack.religions[religion].removed = true;
|
pack.religions[religion].removed = true;
|
||||||
|
const origin = pack.religions[religion].origin;
|
||||||
|
pack.religions.forEach(r => {if(r.origin === religion) r.origin = origin;});
|
||||||
|
|
||||||
refreshReligionsEditor();
|
refreshReligionsEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawReligionCenters() {
|
function drawReligionCenters() {
|
||||||
const tooltip = "Drag to move the religion center (it won't affect religions distribution)";
|
|
||||||
debug.select("#religionCenters").remove();
|
debug.select("#religionCenters").remove();
|
||||||
const religionCenters = debug.append("g").attr("id", "religionCenters")
|
const religionCenters = debug.append("g").attr("id", "religionCenters")
|
||||||
.attr("stroke-width", 2).attr("stroke", "#444444").style("cursor", "move");
|
.attr("stroke-width", 1.2).attr("stroke", "#444444").style("cursor", "move");
|
||||||
|
|
||||||
const data = pack.religions.filter(r => r.center && !r.removed);
|
const data = pack.religions.filter(r => r.i && r.center && r.cells && !r.removed);
|
||||||
religionCenters.selectAll("circle").data(data).enter().append("circle")
|
religionCenters.selectAll("circle").data(data).enter().append("circle")
|
||||||
.attr("id", d => "cultureCenter"+d.i).attr("data-id", d => d.i)
|
.attr("id", d => "religionsCenter"+d.i).attr("data-id", d => d.i)
|
||||||
.attr("r", 6).attr("fill", d => pack.religions[d.i].color)
|
.attr("r", 4).attr("fill", d => d.color)
|
||||||
.attr("cx", d => pack.cells.p[d.center][0]).attr("cy", d => pack.cells.p[d.center][1])
|
.attr("cx", d => pack.cells.p[d.center][0]).attr("cy", d => pack.cells.p[d.center][1])
|
||||||
.on("mouseenter", d => {tip(tooltip, true); body.querySelector(`div[data-id='${d.i}']`).classList.add("selected"); religionHighlightOn(event);})
|
.on("mouseenter", d => {
|
||||||
.on("mouseleave", d => {tip('', true); body.querySelector(`div[data-id='${d.i}']`).classList.remove("selected"); religionHighlightOff(event);})
|
tip(d.name+ ". Drag to move the religion center", true);
|
||||||
.call(d3.drag().on("start", religionCenterDrag));
|
const el = body.querySelector(`div[data-id='${d.i}']`);
|
||||||
|
if (el) el.classList.add("selected");
|
||||||
|
religionHighlightOn(event);
|
||||||
|
}).on("mouseleave", d => {
|
||||||
|
tip('', true);
|
||||||
|
const el = body.querySelector(`div[data-id='${d.i}']`)
|
||||||
|
if (el) el.classList.remove("selected");
|
||||||
|
religionHighlightOff(event);
|
||||||
|
}).call(d3.drag().on("start", religionCenterDrag));
|
||||||
}
|
}
|
||||||
|
|
||||||
function religionCenterDrag() {
|
function religionCenterDrag() {
|
||||||
|
|
@ -259,6 +290,61 @@ function editReligions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showHierarchy() {
|
||||||
|
// build hierarchy tree
|
||||||
|
const religions = pack.religions.filter(r => !r.removed);
|
||||||
|
const root = d3.stratify().id(d => d.i).parentId(d => d.origin)(religions);
|
||||||
|
const treeWidth = root.leaves().length;
|
||||||
|
const treeHeight = root.height;
|
||||||
|
const width = treeWidth * 40, height = treeHeight * 60;
|
||||||
|
|
||||||
|
const margin = {top: 10, right: 10, bottom: -5, left: 10};
|
||||||
|
const w = width - margin.left - margin.right;
|
||||||
|
const h = height + 30 - margin.top - margin.bottom;
|
||||||
|
const treeLayout = d3.tree().size([w, h]);
|
||||||
|
|
||||||
|
treeLayout(root);
|
||||||
|
|
||||||
|
// prepare svg
|
||||||
|
alertMessage.innerHTML = "<div id='religionInfo'>‍</div>";
|
||||||
|
const svg = d3.select("#alertMessage").insert("svg", "#religionInfo").attr("id", "religionHierarchy")
|
||||||
|
.attr("width", width).attr("height", height).style("text-anchor", "middle");
|
||||||
|
const graph = svg.append("g").attr("transform", `translate(10, -45)`);
|
||||||
|
const links = graph.append("g").attr("fill", "none").attr("stroke", "#aaaaaa");
|
||||||
|
const nodes = graph.append("g");
|
||||||
|
|
||||||
|
// render tree
|
||||||
|
links.selectAll('path').data(root.links()).enter()
|
||||||
|
.append('path').attr("d", d => {return "M" + d.source.x + "," + d.source.y
|
||||||
|
+ "C" + d.source.x + "," + (d.source.y * 3 + d.target.y) / 4
|
||||||
|
+ " " + d.target.x + "," + (d.source.y * 2 + d.target.y) / 3
|
||||||
|
+ " " + d.target.x + "," + d.target.y;});
|
||||||
|
|
||||||
|
const node = nodes.selectAll('g').data(root.descendants()).enter()
|
||||||
|
.append('g').attr("data-id", d => d.data.i)
|
||||||
|
.attr("transform", d => `translate(${d.x}, ${d.y})`)
|
||||||
|
.on("mouseenter", () => religionHighlightOn(event))
|
||||||
|
.on("mouseleave", () => religionHighlightOff(event));
|
||||||
|
|
||||||
|
node.append("path").attr("d", d => {
|
||||||
|
if (d.data.type === "Folk") return "M11.3,0A11.3,11.3,0,1,1,-11.3,0A11.3,11.3,0,1,1,11.3,0"; else // circle
|
||||||
|
if (d.data.type === "Heresy") return "M0,-14L14,0L0,14L-14,0Z"; else // diamond
|
||||||
|
if (d.data.type === "Cult") return "M-6.5,-11.26l13,0l6.5,11.26l-6.5,11.26l-13,0l-6.5,-11.26Z"; else // hex
|
||||||
|
if (!d.data.i) return "M5,0A5,5,0,1,1,-5,0A5,5,0,1,1,5,0"; else // small circle
|
||||||
|
return "M-11,-11h22v22h-22Z"; // square
|
||||||
|
}).attr("stroke", "#333333")
|
||||||
|
.attr("fill", d => d.data.i ? d.data.color : "#ffffff")
|
||||||
|
.attr("stroke-dasharray", d => d.data.cells ? "null" : "1");
|
||||||
|
|
||||||
|
node.append("text").attr("dy", ".35em").style("pointer-events", "none")
|
||||||
|
.text(d => d.data.i ? d.data.code : '');
|
||||||
|
|
||||||
|
$("#alert").dialog({
|
||||||
|
title: "Religions tree", width: fitContent(), resizable: false,
|
||||||
|
position: {my: "left center", at: "left+10 center", of: "svg"}, buttons: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function toggleExtinct() {
|
function toggleExtinct() {
|
||||||
body.dataset.extinct = body.dataset.extinct !== "show" ? "show" : "hide";
|
body.dataset.extinct = body.dataset.extinct !== "show" ? "show" : "hide";
|
||||||
religionsEditorAddLines();
|
religionsEditorAddLines();
|
||||||
|
|
@ -354,6 +440,7 @@ function editReligions() {
|
||||||
if (changed.size()) {
|
if (changed.size()) {
|
||||||
drawReligions();
|
drawReligions();
|
||||||
refreshReligionsEditor();
|
refreshReligionsEditor();
|
||||||
|
drawReligionCenters();
|
||||||
}
|
}
|
||||||
exitReligionsManualAssignment();
|
exitReligionsManualAssignment();
|
||||||
}
|
}
|
||||||
|
|
@ -402,10 +489,11 @@ function editReligions() {
|
||||||
if (occupied) {tip("This cell is already a religion center. Please select a different cell", false, "error"); return;}
|
if (occupied) {tip("This cell is already a religion center. Please select a different cell", false, "error"); return;}
|
||||||
|
|
||||||
if (d3.event.shiftKey === false) exitAddReligionMode();
|
if (d3.event.shiftKey === false) exitAddReligionMode();
|
||||||
|
|
||||||
Religions.add(center);
|
Religions.add(center);
|
||||||
|
|
||||||
|
drawReligions();
|
||||||
|
refreshReligionsEditor();
|
||||||
drawReligionCenters();
|
drawReligionCenters();
|
||||||
religionsEditorAddLines();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadReligionsData() {
|
function downloadReligionsData() {
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ function getRandomColor() {
|
||||||
|
|
||||||
// mix a color with a random color
|
// mix a color with a random color
|
||||||
function getMixedColor(color, mix = .2, bright = .3) {
|
function getMixedColor(color, mix = .2, bright = .3) {
|
||||||
const c = color[0] === "#" ? color : getRandomColor(); // if provided color is not hex (e.g. harching), generate random one
|
const c = color && color[0] === "#" ? color : getRandomColor(); // if provided color is not hex (e.g. harching), generate random one
|
||||||
return d3.color(d3.interpolate(c, getRandomColor())(mix)).brighter(bright).hex();
|
return d3.color(d3.interpolate(c, getRandomColor())(mix)).brighter(bright).hex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue