diff --git a/index.html b/index.html index e4f782ed..76fccef2 100644 --- a/index.html +++ b/index.html @@ -8108,5 +8108,6 @@ + diff --git a/main.js b/main.js index f5e0b85a..bd51c1f6 100644 --- a/main.js +++ b/main.js @@ -80,7 +80,7 @@ let labels = viewbox.append("g").attr("id", "labels"); let icons = viewbox.append("g").attr("id", "icons"); let burgIcons = icons.append("g").attr("id", "burgIcons"); let anchors = icons.append("g").attr("id", "anchors"); -let armies = viewbox.append("g").attr("id", "armies").style("display", "none"); +let armies = viewbox.append("g").attr("id", "armies"); let markers = viewbox.append("g").attr("id", "markers"); let fogging = viewbox .append("g") diff --git a/modules/dynamic/auto-update.js b/modules/dynamic/auto-update.js index f7d78376..b6f947ea 100644 --- a/modules/dynamic/auto-update.js +++ b/modules/dynamic/auto-update.js @@ -944,5 +944,8 @@ export function resolveVersionConflicts(mapVersion) { // v1.103.00 separated pole of inaccessibility detection from layer rendering BurgsAndStates.getPoles(); Provinces.getPoles(); + + // v1.103.00 removed regiments from initial render + viewbox.select("#armies").style("display", null); } } diff --git a/modules/military-generator.js b/modules/military-generator.js index e5aacb4d..61224d69 100644 --- a/modules/military-generator.js +++ b/modules/military-generator.js @@ -2,7 +2,7 @@ window.Military = (function () { const generate = function () { - TIME && console.time("generateMilitaryForces"); + TIME && console.time("generateMilitary"); const {cells, states} = pack; const {p} = cells; const valid = states.filter(s => s.i && !s.removed); // valid states @@ -252,8 +252,6 @@ window.Military = (function () { delete s.temp; // do not store temp data }); - redraw(); - function createRegiments(nodes, s) { if (!nodes.length) return []; @@ -312,19 +310,9 @@ window.Military = (function () { return regiments; } - TIME && console.timeEnd("generateMilitaryForces"); + TIME && console.timeEnd("generateMilitary"); }; - function redraw() { - const validStates = pack.states.filter(s => s.i && !s.removed); - armies.selectAll("g > g").each(function () { - const index = notes.findIndex(n => n.id === this.id); - if (index != -1) notes.splice(index, 1); - }); - armies.selectAll("g").remove(); - validStates.forEach(s => drawRegiments(s.military, s.i)); - } - const getDefaultOptions = function () { return [ {icon: "⚔️", name: "infantry", rural: 0.25, urban: 0.2, crew: 1, power: 1, type: "melee", separate: 0}, @@ -335,122 +323,6 @@ window.Military = (function () { ]; }; - const drawRegiments = function (regiments, s) { - const size = +armies.attr("box-size"); - const w = d => (d.n ? size * 4 : size * 6); - const h = size * 2; - const x = d => rn(d.x - w(d) / 2, 2); - const y = d => rn(d.y - size, 2); - - const baseColor = pack.states[s].color[0] === "#" ? pack.states[s].color : "#999"; - const darkerColor = d3.color(baseColor).darker().hex(); - const army = armies - .append("g") - .attr("id", "army" + s) - .attr("fill", baseColor) - .attr("color", darkerColor); - - const g = army - .selectAll("g") - .data(regiments) - .enter() - .append("g") - .attr("id", d => "regiment" + s + "-" + d.i) - .attr("data-name", d => d.name) - .attr("data-state", s) - .attr("data-id", d => d.i) - .attr("transform", d => (d.angle ? `rotate(${d.angle})` : null)) - .attr("transform-origin", d => `${d.x}px ${d.y}px`); - g.append("rect") - .attr("x", d => x(d)) - .attr("y", d => y(d)) - .attr("width", d => w(d)) - .attr("height", h); - g.append("text") - .attr("x", d => d.x) - .attr("y", d => d.y) - .text(d => getTotal(d)); - g.append("rect") - .attr("fill", "currentColor") - .attr("x", d => x(d) - h) - .attr("y", d => y(d)) - .attr("width", h) - .attr("height", h); - g.append("text") - .attr("class", "regimentIcon") - .attr("x", d => x(d) - size) - .attr("y", d => d.y) - .text(d => d.icon); - }; - - const drawRegiment = function (reg, stateId) { - const size = +armies.attr("box-size"); - const w = reg.n ? size * 4 : size * 6; - const h = size * 2; - const x1 = rn(reg.x - w / 2, 2); - const y1 = rn(reg.y - size, 2); - - let army = armies.select("g#army" + stateId); - if (!army.size()) { - const baseColor = pack.states[stateId].color[0] === "#" ? pack.states[stateId].color : "#999"; - const darkerColor = d3.color(baseColor).darker().hex(); - army = armies - .append("g") - .attr("id", "army" + stateId) - .attr("fill", baseColor) - .attr("color", darkerColor); - } - - const g = army - .append("g") - .attr("id", "regiment" + stateId + "-" + reg.i) - .attr("data-name", reg.name) - .attr("data-state", stateId) - .attr("data-id", reg.i) - .attr("transform", `rotate(${reg.angle || 0})`) - .attr("transform-origin", `${reg.x}px ${reg.y}px`); - g.append("rect").attr("x", x1).attr("y", y1).attr("width", w).attr("height", h); - g.append("text").attr("x", reg.x).attr("y", reg.y).text(getTotal(reg)); - g.append("rect") - .attr("fill", "currentColor") - .attr("x", x1 - h) - .attr("y", y1) - .attr("width", h) - .attr("height", h); - g.append("text") - .attr("class", "regimentIcon") - .attr("x", x1 - size) - .attr("y", reg.y) - .text(reg.icon); - }; - - // move one regiment to another - const moveRegiment = function (reg, x, y) { - const el = armies.select("g#army" + reg.state).select("g#regiment" + reg.state + "-" + reg.i); - if (!el.size()) return; - - const duration = Math.hypot(reg.x - x, reg.y - y) * 8; - reg.x = x; - reg.y = y; - const size = +armies.attr("box-size"); - const w = reg.n ? size * 4 : size * 6; - const h = size * 2; - const x1 = x => rn(x - w / 2, 2); - const y1 = y => rn(y - size, 2); - - const move = d3.transition().duration(duration).ease(d3.easeSinInOut); - el.select("rect").transition(move).attr("x", x1(x)).attr("y", y1(y)); - el.select("text").transition(move).attr("x", x).attr("y", y); - el.selectAll("rect:nth-of-type(2)") - .transition(move) - .attr("x", x1(x) - h) - .attr("y", y1(y)); - el.select(".regimentIcon") - .transition(move) - .attr("x", x1(x) - size) - .attr("y", y); - }; - // utilize si function to make regiment total text fit regiment box const getTotal = reg => (reg.a > (reg.n ? 999 : 99999) ? si(reg.a) : reg.a); @@ -513,13 +385,9 @@ window.Military = (function () { return { generate, - redraw, getDefaultOptions, getName, generateNote, - drawRegiments, - drawRegiment, - moveRegiment, getTotal, getEmblem }; diff --git a/modules/renderers/draw-military.js b/modules/renderers/draw-military.js new file mode 100644 index 00000000..2a56acaa --- /dev/null +++ b/modules/renderers/draw-military.js @@ -0,0 +1,126 @@ +"use strict"; + +function drawMilitary() { + TIME && console.time("drawMilitary"); + + armies.selectAll("g").remove(); + pack.states.filter(s => s.i && !s.removed).forEach(s => drawRegiments(s.military, s.i)); + + TIME && console.timeEnd("drawMilitary"); +} + +const drawRegiments = function (regiments, s) { + const size = +armies.attr("box-size"); + const w = d => (d.n ? size * 4 : size * 6); + const h = size * 2; + const x = d => rn(d.x - w(d) / 2, 2); + const y = d => rn(d.y - size, 2); + + const baseColor = pack.states[s].color[0] === "#" ? pack.states[s].color : "#999"; + const darkerColor = d3.color(baseColor).darker().hex(); + const army = armies + .append("g") + .attr("id", "army" + s) + .attr("fill", baseColor) + .attr("color", darkerColor); + + const g = army + .selectAll("g") + .data(regiments) + .enter() + .append("g") + .attr("id", d => "regiment" + s + "-" + d.i) + .attr("data-name", d => d.name) + .attr("data-state", s) + .attr("data-id", d => d.i) + .attr("transform", d => (d.angle ? `rotate(${d.angle})` : null)) + .attr("transform-origin", d => `${d.x}px ${d.y}px`); + g.append("rect") + .attr("x", d => x(d)) + .attr("y", d => y(d)) + .attr("width", d => w(d)) + .attr("height", h); + g.append("text") + .attr("x", d => d.x) + .attr("y", d => d.y) + .text(d => Military.getTotal(d)); + g.append("rect") + .attr("fill", "currentColor") + .attr("x", d => x(d) - h) + .attr("y", d => y(d)) + .attr("width", h) + .attr("height", h); + g.append("text") + .attr("class", "regimentIcon") + .attr("x", d => x(d) - size) + .attr("y", d => d.y) + .text(d => d.icon); +}; + +const drawRegiment = function (reg, stateId) { + const size = +armies.attr("box-size"); + const w = reg.n ? size * 4 : size * 6; + const h = size * 2; + const x1 = rn(reg.x - w / 2, 2); + const y1 = rn(reg.y - size, 2); + + let army = armies.select("g#army" + stateId); + if (!army.size()) { + const baseColor = pack.states[stateId].color[0] === "#" ? pack.states[stateId].color : "#999"; + const darkerColor = d3.color(baseColor).darker().hex(); + army = armies + .append("g") + .attr("id", "army" + stateId) + .attr("fill", baseColor) + .attr("color", darkerColor); + } + + const g = army + .append("g") + .attr("id", "regiment" + stateId + "-" + reg.i) + .attr("data-name", reg.name) + .attr("data-state", stateId) + .attr("data-id", reg.i) + .attr("transform", `rotate(${reg.angle || 0})`) + .attr("transform-origin", `${reg.x}px ${reg.y}px`); + g.append("rect").attr("x", x1).attr("y", y1).attr("width", w).attr("height", h); + g.append("text").attr("x", reg.x).attr("y", reg.y).text(getTotal(reg)); + g.append("rect") + .attr("fill", "currentColor") + .attr("x", x1 - h) + .attr("y", y1) + .attr("width", h) + .attr("height", h); + g.append("text") + .attr("class", "regimentIcon") + .attr("x", x1 - size) + .attr("y", reg.y) + .text(reg.icon); +}; + +// move one regiment to another +const moveRegiment = function (reg, x, y) { + const el = armies.select("g#army" + reg.state).select("g#regiment" + reg.state + "-" + reg.i); + if (!el.size()) return; + + const duration = Math.hypot(reg.x - x, reg.y - y) * 8; + reg.x = x; + reg.y = y; + const size = +armies.attr("box-size"); + const w = reg.n ? size * 4 : size * 6; + const h = size * 2; + const x1 = x => rn(x - w / 2, 2); + const y1 = y => rn(y - size, 2); + + const move = d3.transition().duration(duration).ease(d3.easeSinInOut); + el.select("rect").transition(move).attr("x", x1(x)).attr("y", y1(y)); + el.select("text").transition(move).attr("x", x).attr("y", y); + el.selectAll("rect:nth-of-type(2)") + .transition(move) + .attr("x", x1(x) - h) + .attr("y", y1(y)); + el.select(".regimentIcon") + .transition(move) + .attr("x", x1(x) - size) + .attr("y", y); +}; diff --git a/modules/submap.js b/modules/submap.js index d40e225a..2ade0058 100644 --- a/modules/submap.js +++ b/modules/submap.js @@ -53,7 +53,7 @@ window.Submap = (function () { } }; - stage("Resampling heightmap, temperature and precipitation."); + stage("Resampling heightmap, temperature and precipitation"); // resample heightmap from old WorldState const n = grid.points.length; grid.cells.h = new Uint8Array(n); // heightmap @@ -87,7 +87,7 @@ window.Submap = (function () { } if (options.depressRivers) { - stage("Generating riverbeds."); + stage("Generating riverbeds"); const rbeds = new Uint16Array(grid.cells.i.length); // and erode riverbeds @@ -96,7 +96,7 @@ window.Submap = (function () { if (oldpc < 0) return; // ignore out-of-map marker (-1) const oldc = parentMap.pack.cells.g[oldpc]; const targetCells = forwardGridMap[oldc]; - if (!targetCells) throw "TargetCell shouldn't be empty."; + if (!targetCells) throw "TargetCell shouldn't be empty"; targetCells.forEach(c => { if (grid.cells.h[c] < 20) return; rbeds[c] = 1; @@ -110,7 +110,7 @@ window.Submap = (function () { }); } - stage("Detect features, ocean and generating lakes."); + stage("Detect features, ocean and generating lakes"); markFeatures(); markupGridOcean(); @@ -125,11 +125,11 @@ window.Submap = (function () { calculateMapCoordinates(); // calculateTemperatures(); // generatePrecipitation(); - stage("Cell cleanup."); + stage("Cell cleanup"); reGraph(); // remove misclassified cells - stage("Define coastline."); + stage("Define coastline"); drawCoastline(); /****************************************************/ @@ -147,7 +147,7 @@ window.Submap = (function () { cells.religion = new Uint16Array(pn); cells.province = new Uint16Array(pn); - stage("Resampling culture, state and religion map."); + stage("Resampling culture, state and religion map"); for (const [id, gridCellId] of cells.g.entries()) { const oldGridId = reverseGridMap[gridCellId]; if (oldGridId === undefined) { @@ -206,13 +206,13 @@ window.Submap = (function () { forwardMap[oldid].push(id); } - stage("Regenerating river network."); + stage("Regenerating river network"); Rivers.generate(); Lakes.defineGroup(); // biome calculation based on (resampled) grid.cells.temp and prec // it's safe to recalculate. - stage("Regenerating Biome."); + stage("Regenerating Biome"); Biomes.define(); // recalculate suitability and population // TODO: normalize according to the base-map @@ -233,11 +233,11 @@ window.Submap = (function () { c.center = newCenters.length ? newCenters[0] : pack.cells.culture.findIndex(x => x === i); }); - stage("Porting and locking burgs."); + stage("Porting and locking burgs"); copyBurgs(parentMap, projection, options); // transfer states, mark states without land as removed. - stage("Porting states."); + stage("Porting states"); const validStates = new Set(pack.cells.state); pack.states = parentMap.pack.states; // keep valid states and neighbors only @@ -253,7 +253,7 @@ window.Submap = (function () { }); // transfer provinces, mark provinces without land as removed. - stage("Porting provinces."); + stage("Porting provinces"); const validProvinces = new Set(pack.cells.province); pack.provinces = parentMap.pack.provinces; // mark uneccesary provinces @@ -269,7 +269,7 @@ window.Submap = (function () { BurgsAndStates.drawBurgs(); - stage("Regenerating routes network."); + stage("Regenerating routes network"); regenerateRoutes(); drawStateLabels(); @@ -277,7 +277,7 @@ window.Submap = (function () { Rivers.specify(); Lakes.generateName(); - stage("Porting military."); + stage("Porting military"); for (const s of pack.states) { if (!s.military) continue; for (const m of s.military) { @@ -288,9 +288,9 @@ window.Submap = (function () { } s.military = s.military.filter(m => m.cell).map((m, i) => ({...m, i})); } - Military.redraw(); + drawMilitary(); - stage("Copying markers."); + stage("Copying markers"); for (const m of pack.markers) { const [x, y] = projection(m.x, m.y); if (!inMap(x, y)) { @@ -304,14 +304,14 @@ window.Submap = (function () { } if (layerIsOn("toggleMarkers")) drawMarkers(); - stage("Redraw emblems."); + stage("Redraw emblems"); drawEmblems(); - stage("Regenerating Zones."); + stage("Regenerating Zones"); Zones.generate(); Names.getMapName(); - stage("Restoring Notes."); + stage("Restoring Notes"); notes = parentMap.notes; - stage("Submap done."); + stage("Submap done"); WARN && console.warn(`TOTAL: ${rn((performance.now() - timeStart) / 1000, 2)}s`); showStatistics(); diff --git a/modules/ui/battle-screen.js b/modules/ui/battle-screen.js index 12ad7bdd..8c595a80 100644 --- a/modules/ui/battle-screen.js +++ b/modules/ui/battle-screen.js @@ -277,7 +277,7 @@ class Battle { const shift = side === "attackers" ? attackers.length * -8 : (defenders.length - 1) * 8; regiment.px = regiment.x; regiment.py = regiment.y; - Military.moveRegiment(regiment, defenders[0].x, defenders[0].y + shift); + moveRegiment(regiment, defenders[0].x, defenders[0].y + shift); }); } @@ -909,7 +909,7 @@ class Battle { cancelResults() { // move regiments back to initial positions - this.attackers.regiments.concat(this.defenders.regiments).forEach(r => Military.moveRegiment(r, r.px, r.py)); + this.attackers.regiments.concat(this.defenders.regiments).forEach(r => moveRegiment(r, r.px, r.py)); $("#battleScreen").dialog("close"); this.cleanData(); } diff --git a/modules/ui/layers.js b/modules/ui/layers.js index 4894cc54..3380efb1 100644 --- a/modules/ui/layers.js +++ b/modules/ui/layers.js @@ -185,6 +185,7 @@ function restoreLayers() { if (layerIsOn("toggleBorders")) drawBorders(); if (layerIsOn("toggleStates")) drawStates(); if (layerIsOn("toggleRivers")) drawRivers(); + if (layerIsOn("toggleMilitary")) drawMilitary(); } function toggleHeight(event) { @@ -824,11 +825,11 @@ function drawRoutes() { function toggleMilitary(event) { if (!layerIsOn("toggleMilitary")) { turnButtonOn("toggleMilitary"); - $("#armies").fadeIn(); + drawMilitary(); if (event && isCtrlClick(event)) editStyle("armies"); } else { if (event && isCtrlClick(event)) return editStyle("armies"); - $("#armies").fadeOut(); + armies.selectAll("g").remove(); turnButtonOff("toggleMilitary"); } } diff --git a/modules/ui/regiment-editor.js b/modules/ui/regiment-editor.js index 5c38a07a..fb2f4da4 100644 --- a/modules/ui/regiment-editor.js +++ b/modules/ui/regiment-editor.js @@ -246,7 +246,7 @@ function editRegiment(selector) { reg.name = Military.getName(reg, military); military.push(reg); Military.generateNote(reg, pack.states[state]); // add legend - Military.drawRegiment(reg, state); + drawRegiment(reg, state); if (regimentsOverviewRefresh.offsetParent) regimentsOverviewRefresh.click(); toggleAdd(); } @@ -296,7 +296,7 @@ function editRegiment(selector) { (defender.px = defender.x), (defender.py = defender.y); // move attacker to defender - Military.moveRegiment(attacker, defender.x, defender.y - 8); + moveRegiment(attacker, defender.x, defender.y - 8); // draw battle icon const attack = d3 diff --git a/modules/ui/regiments-overview.js b/modules/ui/regiments-overview.js index 28f40d18..fee7c480 100644 --- a/modules/ui/regiments-overview.js +++ b/modules/ui/regiments-overview.js @@ -179,7 +179,7 @@ function overviewRegiments(state) { reg.name = Military.getName(reg, military); military.push(reg); Military.generateNote(reg, pack.states[state]); // add legend - Military.drawRegiment(reg, state); + drawRegiment(reg, state); toggleAdd(); } diff --git a/modules/ui/style.js b/modules/ui/style.js index 3df838eb..83edd239 100644 --- a/modules/ui/style.js +++ b/modules/ui/style.js @@ -953,7 +953,7 @@ styleArmiesSize.on("input", e => { armies.selectAll("g").remove(); // clear armies layer pack.states.forEach(s => { if (!s.i || s.removed || !s.military.length) return; - Military.drawRegiments(s.military, s.i); + drawRegiments(s.military, s.i); }); }); diff --git a/modules/ui/tools.js b/modules/ui/tools.js index 91addfaa..5ee4081b 100644 --- a/modules/ui/tools.js +++ b/modules/ui/tools.js @@ -506,8 +506,8 @@ function regenerateEmblems() { function regenerateReligions() { Religions.generate(); - if (!layerIsOn("toggleReligions")) toggleReligions(); - else drawReligions(); + if (layerIsOn("toggleReligions")) drawReligions(); + else toggleReligions(); refreshAllEditors(); } @@ -523,7 +523,9 @@ function regenerateCultures() { function regenerateMilitary() { Military.generate(); - if (!layerIsOn("toggleMilitary")) toggleMilitary(); + if (layerIsOn("toggleMilitary")) drawMilitary(); + else toggleMilitary(); + if (byId("militaryOverviewRefresh").offsetParent) militaryOverviewRefresh.click(); }