From b700bf06308cc13784b8e3f08747f88d4932f354 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Wed, 9 Oct 2024 00:33:22 +0200 Subject: [PATCH] feat: burg group editor - apply changes --- main.js | 21 ++++++++------------- modules/burgs-generator.js | 10 ++++++++-- modules/dynamic/auto-update.js | 3 ++- modules/renderers/draw-burg-icons.js | 27 +++++++++++++++++++++++++-- modules/renderers/draw-burg-labels.js | 27 +++++++++++++++++++++++++-- modules/ui/burg-group-editor.js | 9 +++++++++ modules/ui/editors.js | 7 ++----- modules/ui/style-presets.js | 27 +++++++++++++++++++++++---- 8 files changed, 102 insertions(+), 29 deletions(-) diff --git a/main.js b/main.js index af49ecd3..9cd2583e 100644 --- a/main.js +++ b/main.js @@ -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 diff --git a/modules/burgs-generator.js b/modules/burgs-generator.js index f27fe286..a44f0af0 100644 --- a/modules/burgs-generator.js +++ b/modules/burgs-generator.js @@ -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}; })(); diff --git a/modules/dynamic/auto-update.js b/modules/dynamic/auto-update.js index cb4ca6d9..c06b7d12 100644 --- a/modules/dynamic/auto-update.js +++ b/modules/dynamic/auto-update.js @@ -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; } } diff --git a/modules/renderers/draw-burg-icons.js b/modules/renderers/draw-burg-icons.js index fc9c4a70..ad98b5bd 100644 --- a/modules/renderers/draw-burg-icons.js +++ b/modules/renderers/draw-burg-icons.js @@ -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); + }); + } +} diff --git a/modules/renderers/draw-burg-labels.js b/modules/renderers/draw-burg-labels.js index 4f5b004f..6f4438bc 100644 --- a/modules/renderers/draw-burg-labels.js +++ b/modules/renderers/draw-burg-labels.js @@ -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); + }); + } +} diff --git a/modules/ui/burg-group-editor.js b/modules/ui/burg-group-editor.js index 01252256..771c614b 100644 --- a/modules/ui/burg-group-editor.js +++ b/modules/ui/burg-group-editor.js @@ -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"); } } diff --git a/modules/ui/editors.js b/modules/ui/editors.js index 1fcdffe2..3d8ba2a7 100644 --- a/modules/ui/editors.js +++ b/modules/ui/editors.js @@ -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); } diff --git a/modules/ui/style-presets.js b/modules/ui/style-presets.js index 08c1f118..9ec256df 100644 --- a/modules/ui/style-presets.js +++ b/modules/ui/style-presets.js @@ -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) {