mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
[Draft] Submap refactoring (#1153)
* refactor: submap - start * refactor: submap - continue * Merge branch 'master' of https://github.com/Azgaar/Fantasy-Map-Generator into submap-refactoring * refactor: submap - relocate burgs * refactor: submap - restore routes * refactor: submap - restore lake names * refactor: submap - UI update * refactor: submap - restore river and biome data * refactor: submap - simplify options * refactor: submap - restore rivers * refactor: submap - recalculateMapSize * refactor: submap - add middle points * refactor: submap - don't add middle points, unified findPath fn * chore: update version * feat: submap - relocate out of map regiments * feat: submap - fix route gen * feat: submap - allow custom number of cells * feat: submap - add checkbox submapRescaleBurgStyles * feat: submap - update version hash * chore: supporters update --------- Co-authored-by: Azgaar <azgaar.fmg@yandex.com>
This commit is contained in:
parent
23f36c3210
commit
66d22f26c0
18 changed files with 1043 additions and 745 deletions
201
modules/ui/transform-tool.js
Normal file
201
modules/ui/transform-tool.js
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
"use strict";
|
||||
|
||||
async function openTransformTool() {
|
||||
const width = Math.min(400, window.innerWidth * 0.5);
|
||||
const previewScale = width / graphWidth;
|
||||
const height = graphHeight * previewScale;
|
||||
|
||||
let mouseIsDown = false;
|
||||
let mouseX = 0;
|
||||
let mouseY = 0;
|
||||
|
||||
resetInputs();
|
||||
loadPreview();
|
||||
|
||||
$("#transformTool").dialog({
|
||||
title: "Transform map",
|
||||
resizable: false,
|
||||
position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Transform: function () {
|
||||
closeDialogs();
|
||||
transformMap();
|
||||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (modules.openTransformTool) return;
|
||||
modules.openTransformTool = true;
|
||||
|
||||
// add listeners
|
||||
byId("transformToolBody").on("input", handleInput);
|
||||
byId("transformPreview")
|
||||
.on("mousedown", handleMousedown)
|
||||
.on("mouseup", _ => (mouseIsDown = false))
|
||||
.on("mousemove", handleMousemove)
|
||||
.on("wheel", handleWheel);
|
||||
|
||||
async function loadPreview() {
|
||||
byId("transformPreview").style.width = width + "px";
|
||||
byId("transformPreview").style.height = height + "px";
|
||||
|
||||
const options = {noWater: true, fullMap: true, noLabels: true, noScaleBar: true, noVignette: true, noIce: true};
|
||||
const url = await getMapURL("png", options);
|
||||
const SCALE = 4;
|
||||
|
||||
const img = new Image();
|
||||
img.src = url;
|
||||
img.onload = function () {
|
||||
const $canvas = byId("transformPreviewCanvas");
|
||||
$canvas.style.width = width + "px";
|
||||
$canvas.style.height = height + "px";
|
||||
$canvas.width = width * SCALE;
|
||||
$canvas.height = height * SCALE;
|
||||
$canvas.getContext("2d").drawImage(img, 0, 0, width * SCALE, height * SCALE);
|
||||
};
|
||||
}
|
||||
|
||||
function resetInputs() {
|
||||
byId("transformAngleInput").value = 0;
|
||||
byId("transformAngleOutput").value = "0";
|
||||
byId("transformMirrorH").checked = false;
|
||||
byId("transformMirrorV").checked = false;
|
||||
byId("transformScaleInput").value = 0;
|
||||
byId("transformScaleResult").value = 1;
|
||||
byId("transformShiftX").value = 0;
|
||||
byId("transformShiftY").value = 0;
|
||||
handleInput();
|
||||
|
||||
updateCellsNumber(byId("pointsInput").value);
|
||||
byId("transformPointsInput").oninput = e => updateCellsNumber(e.target.value);
|
||||
|
||||
function updateCellsNumber(value) {
|
||||
byId("transformPointsInput").value = value;
|
||||
const cells = cellsDensityMap[value];
|
||||
byId("transformPointsInput").dataset.cells = cells;
|
||||
const output = byId("transformPointsFormatted");
|
||||
output.value = cells / 1000 + "K";
|
||||
output.style.color = getCellsDensityColor(cells);
|
||||
}
|
||||
}
|
||||
|
||||
function handleInput() {
|
||||
const angle = (+byId("transformAngleInput").value / 180) * Math.PI;
|
||||
const shiftX = +byId("transformShiftX").value;
|
||||
const shiftY = +byId("transformShiftY").value;
|
||||
const mirrorH = byId("transformMirrorH").checked;
|
||||
const mirrorV = byId("transformMirrorV").checked;
|
||||
|
||||
const EXP = 1.0965;
|
||||
const scale = rn(EXP ** +byId("transformScaleInput").value, 2); // [0.1, 10]x
|
||||
byId("transformScaleResult").value = scale;
|
||||
|
||||
byId("transformPreviewCanvas").style.transform = `
|
||||
translate(${shiftX * previewScale}px, ${shiftY * previewScale}px)
|
||||
scale(${mirrorH ? -scale : scale}, ${mirrorV ? -scale : scale})
|
||||
rotate(${angle}rad)
|
||||
`;
|
||||
}
|
||||
|
||||
function handleMousedown(e) {
|
||||
mouseIsDown = true;
|
||||
const shiftX = +byId("transformShiftX").value;
|
||||
const shiftY = +byId("transformShiftY").value;
|
||||
mouseX = shiftX - e.clientX / previewScale;
|
||||
mouseY = shiftY - e.clientY / previewScale;
|
||||
}
|
||||
|
||||
function handleMousemove(e) {
|
||||
if (!mouseIsDown) return;
|
||||
e.preventDefault();
|
||||
|
||||
byId("transformShiftX").value = Math.round(mouseX + e.clientX / previewScale);
|
||||
byId("transformShiftY").value = Math.round(mouseY + e.clientY / previewScale);
|
||||
handleInput();
|
||||
}
|
||||
|
||||
function handleWheel(e) {
|
||||
const $scaleInput = byId("transformScaleInput");
|
||||
$scaleInput.value = $scaleInput.valueAsNumber - Math.sign(e.deltaY);
|
||||
handleInput();
|
||||
}
|
||||
|
||||
function transformMap() {
|
||||
INFO && console.group("transformMap");
|
||||
|
||||
const transformPointsValue = byId("transformPointsInput").value;
|
||||
const globalPointsValue = byId("pointsInput").value;
|
||||
if (transformPointsValue !== globalPointsValue) changeCellsDensity(transformPointsValue);
|
||||
|
||||
const [projection, inverse] = getProjection();
|
||||
|
||||
resetZoom(0);
|
||||
undraw();
|
||||
Resample.process({projection, inverse, scale: 1});
|
||||
drawLayers();
|
||||
|
||||
INFO && console.groupEnd("transformMap");
|
||||
}
|
||||
|
||||
function getProjection() {
|
||||
const centerX = graphWidth / 2;
|
||||
const centerY = graphHeight / 2;
|
||||
const shiftX = +byId("transformShiftX").value;
|
||||
const shiftY = +byId("transformShiftY").value;
|
||||
const angle = (+byId("transformAngleInput").value / 180) * Math.PI;
|
||||
const cos = Math.cos(angle);
|
||||
const sin = Math.sin(angle);
|
||||
const scale = +byId("transformScaleResult").value;
|
||||
const mirrorH = byId("transformMirrorH").checked;
|
||||
const mirrorV = byId("transformMirrorV").checked;
|
||||
|
||||
function project(x, y) {
|
||||
// center the point
|
||||
x -= centerX;
|
||||
y -= centerY;
|
||||
|
||||
// apply scale
|
||||
if (scale !== 1) {
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
}
|
||||
|
||||
// apply rotation
|
||||
if (angle) [x, y] = [x * cos - y * sin, x * sin + y * cos];
|
||||
|
||||
// apply mirroring
|
||||
if (mirrorH) x = -x;
|
||||
if (mirrorV) y = -y;
|
||||
|
||||
// uncenter the point and apply shift
|
||||
return [x + centerX + shiftX, y + centerY + shiftY];
|
||||
}
|
||||
|
||||
function inverse(x, y) {
|
||||
// undo shift and center the point
|
||||
x -= centerX + shiftX;
|
||||
y -= centerY + shiftY;
|
||||
|
||||
// undo mirroring
|
||||
if (mirrorV) y = -y;
|
||||
if (mirrorH) x = -x;
|
||||
|
||||
// undo rotation
|
||||
if (angle !== 0) [x, y] = [x * cos + y * sin, -x * sin + y * cos];
|
||||
|
||||
// undo scale
|
||||
if (scale !== 1) {
|
||||
x /= scale;
|
||||
y /= scale;
|
||||
}
|
||||
|
||||
// uncenter the point
|
||||
return [x + centerX, y + centerY];
|
||||
}
|
||||
|
||||
return [project, inverse];
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue