mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-23 12:31:24 +01:00
153 lines
6.5 KiB
JavaScript
153 lines
6.5 KiB
JavaScript
function editWorld() {
|
|
if (customization) return;
|
|
$('#worldConfigurator').dialog({
|
|
title: 'Configure World',
|
|
resizable: false,
|
|
width: '42em',
|
|
buttons: {
|
|
'Whole World': () => applyWorldPreset(100, 50),
|
|
Northern: () => applyWorldPreset(33, 25),
|
|
Tropical: () => applyWorldPreset(33, 50),
|
|
Southern: () => applyWorldPreset(33, 75),
|
|
'Restore Winds': restoreDefaultWinds
|
|
},
|
|
open: function () {
|
|
const buttons = $(this).dialog('widget').find('.ui-dialog-buttonset > button');
|
|
buttons[0].addEventListener('mousemove', () => tip('Click to set map size to cover the whole World'));
|
|
buttons[1].addEventListener('mousemove', () => tip('Click to set map size to cover the Northern latitudes'));
|
|
buttons[2].addEventListener('mousemove', () => tip('Click to set map size to cover the Tropical latitudes'));
|
|
buttons[3].addEventListener('mousemove', () => tip('Click to set map size to cover the Southern latitudes'));
|
|
buttons[4].addEventListener('mousemove', () => tip('Click to restore default wind directions'));
|
|
},
|
|
close: function () {
|
|
$(this).dialog('destroy');
|
|
}
|
|
});
|
|
|
|
const globe = d3.select('#globe');
|
|
const clr = d3.scaleSequential(d3.interpolateSpectral);
|
|
const tMax = 30,
|
|
tMin = -25; // temperature extremes
|
|
const projection = d3.geoOrthographic().translate([100, 100]).scale(100);
|
|
const path = d3.geoPath(projection);
|
|
|
|
updateGlobeTemperature();
|
|
updateGlobePosition();
|
|
|
|
if (modules.editWorld) return;
|
|
modules.editWorld = true;
|
|
|
|
document.getElementById('worldControls').addEventListener('input', (e) => updateWorld(e.target));
|
|
globe.select('#globeWindArrows').on('click', changeWind);
|
|
globe.select('#globeGraticule').attr('d', round(path(d3.geoGraticule()()))); // globe graticule
|
|
updateWindDirections();
|
|
|
|
function updateWorld(el) {
|
|
if (el) {
|
|
document.getElementById(el.dataset.stored + 'Input').value = el.value;
|
|
document.getElementById(el.dataset.stored + 'Output').value = el.value;
|
|
if (el.dataset.stored) lock(el.dataset.stored);
|
|
}
|
|
|
|
updateGlobeTemperature();
|
|
updateGlobePosition();
|
|
calculateTemperatures();
|
|
generatePrecipitation();
|
|
const heights = new Uint8Array(pack.cells.h);
|
|
Rivers.generate();
|
|
Lakes.defineGroup();
|
|
Rivers.specify();
|
|
pack.cells.h = new Float32Array(heights);
|
|
defineBiomes();
|
|
|
|
if (layerIsOn('toggleTemp')) drawTemp();
|
|
if (layerIsOn('togglePrec')) drawPrec();
|
|
if (layerIsOn('toggleBiomes')) drawBiomes();
|
|
if (layerIsOn('toggleCoordinates')) drawCoordinates();
|
|
if (layerIsOn('toggleRivers')) drawRivers();
|
|
if (document.getElementById('canvas3d')) setTimeout(ThreeD.update(), 500);
|
|
}
|
|
|
|
function updateGlobePosition() {
|
|
const size = +document.getElementById('mapSizeOutput').value;
|
|
const eqD = ((graphHeight / 2) * 100) / size;
|
|
|
|
calculateMapCoordinates();
|
|
const mc = mapCoordinates; // shortcut
|
|
const scale = +distanceScaleInput.value,
|
|
unit = distanceUnitInput.value;
|
|
const meridian = toKilometer(eqD * 2 * scale);
|
|
document.getElementById('mapSize').innerHTML = `${graphWidth}x${graphHeight}`;
|
|
document.getElementById('mapSizeFriendly').innerHTML = `${rn(graphWidth * scale)}x${rn(graphHeight * scale)} ${unit}`;
|
|
document.getElementById('meridianLength').innerHTML = rn(eqD * 2);
|
|
document.getElementById('meridianLengthFriendly').innerHTML = `${rn(eqD * 2 * scale)} ${unit}`;
|
|
document.getElementById('meridianLengthEarth').innerHTML = meridian ? ' = ' + rn(meridian / 200) + '%🌏' : '';
|
|
document.getElementById('mapCoordinates').innerHTML = `${lat(mc.latN)} ${Math.abs(rn(mc.lonW))}°W; ${lat(mc.latS)} ${rn(mc.lonE)}°E`;
|
|
|
|
function toKilometer(v) {
|
|
if (unit === 'km') return v;
|
|
else if (unit === 'mi') return v * 1.60934;
|
|
else if (unit === 'lg') return v * 5.556;
|
|
else if (unit === 'vr') return v * 1.0668;
|
|
return 0; // 0 if distanceUnitInput is a custom unit
|
|
}
|
|
|
|
function lat(lat) {
|
|
return lat > 0 ? Math.abs(rn(lat)) + '°N' : Math.abs(rn(lat)) + '°S';
|
|
} // parse latitude value
|
|
const area = d3.geoGraticule().extent([
|
|
[mc.lonW, mc.latN],
|
|
[mc.lonE, mc.latS]
|
|
]);
|
|
globe.select('#globeArea').attr('d', round(path(area.outline()))); // map area
|
|
}
|
|
|
|
function updateGlobeTemperature() {
|
|
const tEq = +document.getElementById('temperatureEquatorOutput').value;
|
|
document.getElementById('temperatureEquatorF').innerHTML = rn((tEq * 9) / 5 + 32);
|
|
const tPole = +document.getElementById('temperaturePoleOutput').value;
|
|
document.getElementById('temperaturePoleF').innerHTML = rn((tPole * 9) / 5 + 32);
|
|
globe.selectAll('.tempGradient90').attr('stop-color', clr(1 - (tPole - tMin) / (tMax - tMin)));
|
|
globe.selectAll('.tempGradient60').attr('stop-color', clr(1 - (tEq - ((tEq - tPole) * 2) / 3 - tMin) / (tMax - tMin)));
|
|
globe.selectAll('.tempGradient30').attr('stop-color', clr(1 - (tEq - ((tEq - tPole) * 1) / 3 - tMin) / (tMax - tMin)));
|
|
globe.select('.tempGradient0').attr('stop-color', clr(1 - (tEq - tMin) / (tMax - tMin)));
|
|
}
|
|
|
|
function updateWindDirections() {
|
|
globe
|
|
.select('#globeWindArrows')
|
|
.selectAll('path')
|
|
.each(function (d, i) {
|
|
const tr = parseTransform(this.getAttribute('transform'));
|
|
this.setAttribute('transform', `rotate(${options.winds[i]} ${tr[1]} ${tr[2]})`);
|
|
});
|
|
}
|
|
|
|
function changeWind() {
|
|
const arrow = d3.event.target.nextElementSibling;
|
|
const tier = +arrow.dataset.tier;
|
|
options.winds[tier] = (options.winds[tier] + 45) % 360;
|
|
const tr = parseTransform(arrow.getAttribute('transform'));
|
|
arrow.setAttribute('transform', `rotate(${options.winds[tier]} ${tr[1]} ${tr[2]})`);
|
|
localStorage.setItem('winds', options.winds);
|
|
const mapTiers = d3.range(mapCoordinates.latN, mapCoordinates.latS, -30).map((c) => ((90 - c) / 30) | 0);
|
|
if (mapTiers.includes(tier)) updateWorld();
|
|
}
|
|
|
|
function restoreDefaultWinds() {
|
|
const defaultWinds = [225, 45, 225, 315, 135, 315];
|
|
const mapTiers = d3.range(mapCoordinates.latN, mapCoordinates.latS, -30).map((c) => ((90 - c) / 30) | 0);
|
|
const update = mapTiers.some((t) => options.winds[t] != defaultWinds[t]);
|
|
options.winds = defaultWinds;
|
|
updateWindDirections();
|
|
if (update) updateWorld();
|
|
}
|
|
|
|
function applyWorldPreset(size, lat) {
|
|
document.getElementById('mapSizeInput').value = document.getElementById('mapSizeOutput').value = size;
|
|
document.getElementById('latitudeInput').value = document.getElementById('latitudeOutput').value = lat;
|
|
lock('mapSize');
|
|
lock('latitude');
|
|
updateWorld();
|
|
}
|
|
}
|