feat: burg group editor - apply changes

This commit is contained in:
Azgaar 2024-10-09 00:33:22 +02:00
parent b6708bf698
commit b700bf0630
8 changed files with 102 additions and 29 deletions

21
main.js
View file

@ -151,10 +151,7 @@ let notes = [];
let rulers = new Rulers();
let customization = 0;
let biomesData = Biomes.getDefault();
let nameBases = Names.getNameBases(); // cultures-related data
// default options, based on Earth data
// global options; in v2.0 to be used for all UI settings
let options = {
pinNotes: false,
winds: [225, 45, 225, 315, 135, 315],
@ -163,21 +160,19 @@ let options = {
temperatureSouthPole: -15,
stateLabelsMode: "auto",
showBurgPreview: true,
villageMaxPopulation: 2000,
burgs: {
groups: Burgs.getDefaultGroups()
}
};
// create groups for each burg type
{
const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order);
for (const {name} of sortedGroups) {
burgIcons.append("g").attr("id", name);
burgLabels.append("g").attr("id", name);
}
}
// global style object; in v2.0 to be used for all map styles and render settings
let style = {
burgLabels: {},
burgIcons: {}
};
let biomesData = Biomes.getDefault();
let nameBases = Names.getNameBases(); // cultures-related data
let color = d3.scaleSequential(d3.interpolateSpectral); // default color scheme
const lineGen = d3.line().curve(d3.curveBasis); // d3 line generator with default curve interpolation

View file

@ -189,7 +189,7 @@ window.Burgs = (() => {
.sort((a, b) => a - b); // ascending
pack.burgs.forEach(burg => {
if (!burg.i || burg.removed || burg.lock) return;
if (!burg.i || burg.removed) return;
defineGroup(burg, populations);
});
@ -318,6 +318,12 @@ window.Burgs = (() => {
];
function defineGroup(burg, populations) {
if (burg.lock) {
// locked bugrgs: don't change group if it still exists
const group = options.burgs.groups.find(g => g.name === burg.group);
if (group) return;
}
for (const group of options.burgs.groups) {
if (!group.active) continue;
@ -404,5 +410,5 @@ window.Burgs = (() => {
return burgId;
}
return {generate, getDefaultGroups, specify, getType, add};
return {generate, getDefaultGroups, specify, defineGroup, getType, add};
})();

View file

@ -838,7 +838,6 @@ export function resolveVersionConflicts(mapVersion) {
if (isOlderThan("1.97.0")) {
// v1.97.00 changed MFCG link to an arbitrary preview URL
options.villageMaxPopulation = 2000;
options.showBurgPreview = options.showMFCGMap;
delete options.showMFCGMap;
@ -972,5 +971,7 @@ export function resolveVersionConflicts(mapVersion) {
options.burgs = {
groups: groups.map(name => ({name, active: true, preview: null}))
};
delete options.villageMaxPopulation;
}
}

View file

@ -2,8 +2,7 @@
function drawBurgIcons() {
TIME && console.time("drawBurgIcons");
icons.selectAll("circle, use").remove(); // cleanup
createIconGroups();
for (const {name} of options.burgs.groups) {
const burgsInGroup = pack.burgs.filter(b => b.group === name && !b.removed);
@ -49,3 +48,27 @@ function drawBurgIcon(burg) {
.attr("x", burg.x)
.attr("y", burg.y);
}
function createIconGroups() {
const defaultStyle = style.burgIcons.towns || Object.values(style.burgIcons)[0];
// save existing styles and remove all groups
document.querySelectorAll("g#burgIcons > g").forEach(group => {
const groupStyle = Object.keys(defaultStyle).reduce((acc, key) => {
acc[key] = group.getAttribute(key);
return acc;
}, {});
style.burgIcons[group.id] = groupStyle;
group.remove();
});
// create groups for each burg group and apply stored or default style
const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order);
for (const {name} of sortedGroups) {
const group = burgIcons.append("g").attr("id", name);
const styles = style.burgIcons[name] || defaultStyle;
Object.entries(styles).forEach(([key, value]) => {
group.attr(key, value);
});
}
}

View file

@ -2,8 +2,7 @@
function drawBurgLabels() {
TIME && console.time("drawBurgLabels");
burgLabels.selectAll("text").remove(); // cleanup
createLabelGroups();
for (const {name} of options.burgs.groups) {
const burgsInGroup = pack.burgs.filter(b => b.group === name && !b.removed);
@ -39,3 +38,27 @@ function drawBurgLabel(burg) {
.attr("dy", "-0.4em")
.text(burg.name);
}
function createLabelGroups() {
const defaultStyle = style.burgLabels.towns || Object.values(style.burgLabels)[0];
// save existing styles and remove all groups
document.querySelectorAll("g#burgLabels > g").forEach(group => {
const groupStyle = Object.keys(defaultStyle).reduce((acc, key) => {
acc[key] = group.getAttribute(key);
return acc;
}, {});
style.burgLabels[group.id] = groupStyle;
group.remove();
});
// create groups for each burg group and apply stored or default style
const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order);
for (const {name} of sortedGroups) {
const group = burgLabels.append("g").attr("id", name);
const styles = style.burgLabels[name] || defaultStyle;
Object.entries(styles).forEach(([key, value]) => {
group.attr(key, value);
});
}
}

View file

@ -211,6 +211,7 @@ function editBurgGroups() {
el.previousElementSibling.value = JSON.stringify(values);
el.innerHTML = Object.keys(values).length ? "some" : "any";
$(this).dialog("close");
},
Cancel: function () {
@ -305,6 +306,14 @@ function editBurgGroups() {
return group;
});
// put burgs to new groups
const validBurgs = pack.burgs.filter(b => b.i && !b.removed);
const populations = validBurgs.map(b => b.population).sort((a, b) => a - b);
validBurgs.forEach(burg => Burgs.defineGroup(burg, populations));
if (layerIsOn("toggleBurgIcons")) drawBurgIcons();
if (layerIsOn("toggleLabels")) drawBurgLabels();
$("#burgGroupsEditor").dialog("close");
}
}

View file

@ -240,13 +240,10 @@ function togglePort(burg) {
.attr("height", size);
}
// TODO: rework this function to use the new data structure
function getBurgLink(burg) {
if (burg.link) return burg.link;
const population = burg.population * populationRate * urbanization;
if (population >= options.villageMaxPopulation || burg.citadel || burg.walls || burg.temple || burg.shanty)
return createMfcgLink(burg);
if (burg.citadel || burg.walls || burg.temple || burg.shanty) return createMfcgLink(burg);
return createVillageGeneratorLink(burg);
}

View file

@ -71,13 +71,22 @@ async function fetchSystemPreset(preset) {
}
}
function applyStyle(style) {
for (const selector in style) {
function applyStyle(styleJSON) {
for (const selector in styleJSON) {
if (selector.startsWith("#burgLabels")) {
const group = selector.replace("#burgLabels > g#", "");
style.burgLabels[group] = styleJSON[selector];
}
if (selector.startsWith("#burgIcons")) {
const group = selector.replace("#burgIcons > g#", "");
style.burgIcons[group] = styleJSON[selector];
}
const el = document.querySelector(selector);
if (!el) continue;
for (const attribute in style[selector]) {
const value = style[selector][attribute];
for (const attribute in styleJSON[selector]) {
const value = styleJSON[selector][attribute];
if (value === "null" || value === null) {
el.removeAttribute(attribute);
@ -342,8 +351,18 @@ function addStylePreset() {
"stroke-dasharray",
"stroke-linecap"
];
const burgLabelsAttributes = [
"opacity",
"fill",
"text-shadow",
"letter-spacing",
"data-size",
"font-size",
"font-family"
];
options.burgs.groups.forEach(({name}) => {
attributes[`#burgIcons > g.${name}`] = burgIconsAttributes;
attributes[`#burgLabels > g#${name}`] = burgLabelsAttributes;
});
for (const selector in attributes) {