mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
refactor: ice editor dialog
This commit is contained in:
parent
0dd7468184
commit
3125366944
12 changed files with 75 additions and 46 deletions
|
|
@ -11,6 +11,7 @@ import {rn} from "utils/numberUtils";
|
||||||
import {rand} from "utils/probabilityUtils";
|
import {rand} from "utils/probabilityUtils";
|
||||||
import {parseTransform} from "utils/stringUtils";
|
import {parseTransform} from "utils/stringUtils";
|
||||||
import {convertTemperature, getHeight} from "utils/unitUtils";
|
import {convertTemperature, getHeight} from "utils/unitUtils";
|
||||||
|
import {restoreDefaultEvents} from "scripts/events";
|
||||||
|
|
||||||
let isLoaded = false;
|
let isLoaded = false;
|
||||||
|
|
||||||
|
|
@ -483,7 +484,8 @@ export function open({id} = {}) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
viewbox.on("click", clicked).style("cursor", "default");
|
restoreDefaultEvents();
|
||||||
|
|
||||||
if (layerIsOn("toggleCells") && toggler.dataset.forced) {
|
if (layerIsOn("toggleCells") && toggler.dataset.forced) {
|
||||||
toggleCells();
|
toggleCells();
|
||||||
toggler.dataset.forced = false;
|
toggler.dataset.forced = false;
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,37 @@
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
|
|
||||||
import {findGridCell, getGridPolygon} from "utils/graphUtils";
|
|
||||||
import {tip, clearMainTip} from "scripts/tooltips";
|
|
||||||
import {rn} from "utils/numberUtils";
|
|
||||||
import {ra} from "utils/probabilityUtils";
|
|
||||||
import {parseTransform} from "utils/stringUtils";
|
|
||||||
import {closeDialogs} from "dialogs/utils";
|
import {closeDialogs} from "dialogs/utils";
|
||||||
|
import {layerIsOn, toggleLayer} from "layers";
|
||||||
|
import {clearMainTip, tip} from "scripts/tooltips";
|
||||||
|
import {findGridCell, getGridPolygon} from "utils/graphUtils";
|
||||||
|
import {getInputNumber} from "utils/nodeUtils";
|
||||||
|
import {rn} from "utils/numberUtils";
|
||||||
|
import {rand} from "utils/probabilityUtils";
|
||||||
|
import {byId} from "utils/shorthands";
|
||||||
|
import {parseTransform} from "utils/stringUtils";
|
||||||
|
// @ts-expect-error js module
|
||||||
|
import {editStyle} from "modules/style";
|
||||||
|
// @ts-expect-error js module
|
||||||
|
import {restoreDefaultEvents} from "scripts/events";
|
||||||
|
// @ts-expect-error js module
|
||||||
|
import {unselect} from "modules/ui/editors";
|
||||||
|
|
||||||
let isLoaded = false;
|
let isLoaded = false;
|
||||||
|
|
||||||
export function editIce() {
|
export function open() {
|
||||||
if (customization) return;
|
|
||||||
closeDialogs(".stable");
|
closeDialogs(".stable");
|
||||||
if (!layerIsOn("toggleIce")) toggleIce();
|
if (!layerIsOn("toggleIce")) toggleLayer("toggleIce");
|
||||||
|
|
||||||
elSelected = d3.select(d3.event.target);
|
elSelected = d3.select(d3.event.target);
|
||||||
|
|
||||||
const type = elSelected.attr("type") ? "Glacier" : "Iceberg";
|
const type = elSelected.attr("type") ? "Glacier" : "Iceberg";
|
||||||
document.getElementById("iceRandomize").style.display = type === "Glacier" ? "none" : "inline-block";
|
if (byId("iceRandomize")) byId("iceRandomize")!.style.display = type === "Glacier" ? "none" : "inline-block";
|
||||||
document.getElementById("iceSize").style.display = type === "Glacier" ? "none" : "inline-block";
|
|
||||||
if (type === "Iceberg") document.getElementById("iceSize").value = +elSelected.attr("size");
|
const $iceSize = byId("iceSize") as HTMLInputElement;
|
||||||
|
if ($iceSize) {
|
||||||
|
$iceSize.style.display = type === "Glacier" ? "none" : "inline-block";
|
||||||
|
if (type === "Iceberg") $iceSize.value = elSelected.attr("size");
|
||||||
|
}
|
||||||
ice.selectAll("*").classed("draggable", true).call(d3.drag().on("drag", dragElement));
|
ice.selectAll("*").classed("draggable", true).call(d3.drag().on("drag", dragElement));
|
||||||
|
|
||||||
$("#iceEditor").dialog({
|
$("#iceEditor").dialog({
|
||||||
|
|
@ -32,29 +45,31 @@ export function editIce() {
|
||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
|
|
||||||
// add listeners
|
// add listeners
|
||||||
document.getElementById("iceEditStyle").addEventListener("click", () => editStyle("ice"));
|
byId("iceEditStyle")?.on("click", () => editStyle("ice"));
|
||||||
document.getElementById("iceRandomize").addEventListener("click", randomizeShape);
|
byId("iceRandomize")?.on("click", randomizeShape);
|
||||||
document.getElementById("iceSize").addEventListener("input", changeSize);
|
byId("iceSize")?.on("input", changeSize);
|
||||||
document.getElementById("iceNew").addEventListener("click", toggleAdd);
|
byId("iceNew")?.on("click", toggleAdd);
|
||||||
document.getElementById("iceRemove").addEventListener("click", removeIce);
|
byId("iceRemove")?.on("click", removeIce);
|
||||||
|
|
||||||
function randomizeShape() {
|
function randomizeShape() {
|
||||||
const c = grid.points[+elSelected.attr("cell")];
|
const c = grid.points[+elSelected.attr("cell")];
|
||||||
const s = +elSelected.attr("size");
|
const s = +elSelected.attr("size");
|
||||||
const i = ra(grid.cells.i),
|
const i = rand(0, grid.cells.i.length);
|
||||||
cn = grid.points[i];
|
|
||||||
|
const cn = grid.points[i];
|
||||||
const poly = getGridPolygon(i).map(p => [p[0] - cn[0], p[1] - cn[1]]);
|
const poly = getGridPolygon(i).map(p => [p[0] - cn[0], p[1] - cn[1]]);
|
||||||
const points = poly.map(p => [rn(c[0] + p[0] * s, 2), rn(c[1] + p[1] * s, 2)]);
|
const points = poly.map(p => [rn(c[0] + p[0] * s, 2), rn(c[1] + p[1] * s, 2)]);
|
||||||
elSelected.attr("points", points);
|
elSelected.attr("points", points);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeSize() {
|
function changeSize(this: HTMLInputElement) {
|
||||||
const c = grid.points[+elSelected.attr("cell")];
|
const c = grid.points[+elSelected.attr("cell")];
|
||||||
const s = +elSelected.attr("size");
|
const s = +elSelected.attr("size");
|
||||||
const flat = elSelected
|
const flat = elSelected
|
||||||
.attr("points")
|
.attr("points")
|
||||||
.split(",")
|
.split(",")
|
||||||
.map(el => +el);
|
.map((pointString: string) => +pointString);
|
||||||
|
|
||||||
const pairs = [];
|
const pairs = [];
|
||||||
while (flat.length) pairs.push(flat.splice(0, 2));
|
while (flat.length) pairs.push(flat.splice(0, 2));
|
||||||
const poly = pairs.map(p => [(p[0] - c[0]) / s, (p[1] - c[1]) / s]);
|
const poly = pairs.map(p => [(p[0] - c[0]) / s, (p[1] - c[1]) / s]);
|
||||||
|
|
@ -64,21 +79,21 @@ export function editIce() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleAdd() {
|
function toggleAdd() {
|
||||||
document.getElementById("iceNew").classList.toggle("pressed");
|
byId("iceNew")?.classList.toggle("pressed");
|
||||||
if (document.getElementById("iceNew").classList.contains("pressed")) {
|
if (byId("iceNew")?.classList.contains("pressed")) {
|
||||||
viewbox.style("cursor", "crosshair").on("click", addIcebergOnClick);
|
viewbox.style("cursor", "crosshair").on("click", addIcebergOnClick);
|
||||||
tip("Click on map to create an iceberg. Hold Shift to add multiple", true);
|
tip("Click on map to create an iceberg. Hold Shift to add multiple", true);
|
||||||
} else {
|
} else {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
viewbox.on("click", clicked).style("cursor", "default");
|
restoreDefaultEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addIcebergOnClick() {
|
function addIcebergOnClick(this: d3.ContainerElement) {
|
||||||
const [x, y] = d3.mouse(this);
|
const [x, y] = d3.mouse(this);
|
||||||
const i = findGridCell(x, y, grid);
|
const i = findGridCell(x, y, grid);
|
||||||
const c = grid.points[i];
|
const c = grid.points[i];
|
||||||
const s = +document.getElementById("iceSize").value;
|
const s = getInputNumber("iceSize");
|
||||||
|
|
||||||
const points = getGridPolygon(i).map(p => [(p[0] + (c[0] - p[0]) / s) | 0, (p[1] + (c[1] - p[1]) / s) | 0]);
|
const points = getGridPolygon(i).map(p => [(p[0] + (c[0] - p[0]) / s) | 0, (p[1] + (c[1] - p[1]) / s) | 0]);
|
||||||
const iceberg = ice.append("polygon").attr("points", points).attr("cell", i).attr("size", s);
|
const iceberg = ice.append("polygon").attr("points", points).attr("cell", i).attr("size", s);
|
||||||
|
|
@ -88,7 +103,7 @@ export function editIce() {
|
||||||
|
|
||||||
function removeIce() {
|
function removeIce() {
|
||||||
const type = elSelected.attr("type") ? "Glacier" : "Iceberg";
|
const type = elSelected.attr("type") ? "Glacier" : "Iceberg";
|
||||||
alertMessage.innerHTML = /* html */ `Are you sure you want to remove the ${type}?`;
|
byId("alertMessage")!.innerHTML = `Are you sure you want to remove the ${type}?`;
|
||||||
$("#alert").dialog({
|
$("#alert").dialog({
|
||||||
resizable: false,
|
resizable: false,
|
||||||
title: "Remove " + type,
|
title: "Remove " + type,
|
||||||
|
|
@ -105,14 +120,13 @@ export function editIce() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function dragElement() {
|
function dragElement(this: Element) {
|
||||||
const tr = parseTransform(this.getAttribute("transform"));
|
const tr = parseTransform(this.getAttribute("transform"));
|
||||||
const dx = +tr[0] - d3.event.x,
|
const dx = +tr[0] - d3.event.x;
|
||||||
dy = +tr[1] - d3.event.y;
|
const dy = +tr[1] - d3.event.y;
|
||||||
|
|
||||||
d3.event.on("drag", function () {
|
d3.event.on("drag", function (this: Element) {
|
||||||
const x = d3.event.x,
|
const {x, y} = d3.event;
|
||||||
y = d3.event.y;
|
|
||||||
this.setAttribute("transform", `translate(${dx + x},${dy + y})`);
|
this.setAttribute("transform", `translate(${dx + x},${dy + y})`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +134,7 @@ export function editIce() {
|
||||||
function closeEditor() {
|
function closeEditor() {
|
||||||
ice.selectAll("*").classed("draggable", false).call(d3.drag().on("drag", null));
|
ice.selectAll("*").classed("draggable", false).call(d3.drag().on("drag", null));
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
iceNew.classList.remove("pressed");
|
byId("iceNew")?.classList.remove("pressed");
|
||||||
unselect();
|
unselect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ const dialogsMap = {
|
||||||
heightmapEditor: "heightmap-editor",
|
heightmapEditor: "heightmap-editor",
|
||||||
heightmapSelection: "heightmap-selection",
|
heightmapSelection: "heightmap-selection",
|
||||||
hierarchyTree: "hierarchy-tree",
|
hierarchyTree: "hierarchy-tree",
|
||||||
|
iceEditor: "ice-editor",
|
||||||
religionsEditor: "religions-editor",
|
religionsEditor: "religions-editor",
|
||||||
statesEditor: "states-editor",
|
statesEditor: "states-editor",
|
||||||
unitsEditor: "units-editor"
|
unitsEditor: "units-editor"
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ export function editRegiment(selector) {
|
||||||
tip("Click on map to create new regiment or fleet", true);
|
tip("Click on map to create new regiment or fleet", true);
|
||||||
} else {
|
} else {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
viewbox.on("click", clicked).style("cursor", "default");
|
restoreDefaultEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,8 +240,8 @@ export function editRegiment(selector) {
|
||||||
armies.selectAll(":scope > g").classed("draggable", false);
|
armies.selectAll(":scope > g").classed("draggable", false);
|
||||||
} else {
|
} else {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
|
restoreDefaultEvents();
|
||||||
armies.selectAll(":scope > g").classed("draggable", true);
|
armies.selectAll(":scope > g").classed("draggable", true);
|
||||||
viewbox.on("click", clicked).style("cursor", "default");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,7 +313,7 @@ export function editRegiment(selector) {
|
||||||
} else {
|
} else {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
armies.selectAll(":scope > g").classed("draggable", true);
|
armies.selectAll(":scope > g").classed("draggable", true);
|
||||||
viewbox.on("click", clicked).style("cursor", "default");
|
restoreDefaultEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {rn} from "utils/numberUtils";
|
||||||
import {capitalize} from "utils/stringUtils";
|
import {capitalize} from "utils/stringUtils";
|
||||||
import {si} from "utils/unitUtils";
|
import {si} from "utils/unitUtils";
|
||||||
import {closeDialogs} from "dialogs/utils";
|
import {closeDialogs} from "dialogs/utils";
|
||||||
|
import {restoreDefaultEvents} from "scripts/events";
|
||||||
|
|
||||||
let isLoaded = false;
|
let isLoaded = false;
|
||||||
|
|
||||||
|
|
@ -170,7 +171,7 @@ export function overviewRegiments(state) {
|
||||||
if (regimentAdd.offsetParent) regimentAdd.classList.add("pressed");
|
if (regimentAdd.offsetParent) regimentAdd.classList.add("pressed");
|
||||||
} else {
|
} else {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
viewbox.on("click", clicked).style("cursor", "default");
|
restoreDefaultEvents();
|
||||||
addLines();
|
addLines();
|
||||||
if (regimentAdd.offsetParent) regimentAdd.classList.remove("pressed");
|
if (regimentAdd.offsetParent) regimentAdd.classList.remove("pressed");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import {rn} from "utils/numberUtils";
|
||||||
import {getNextId} from "utils/nodeUtils";
|
import {getNextId} from "utils/nodeUtils";
|
||||||
import {round} from "utils/stringUtils";
|
import {round} from "utils/stringUtils";
|
||||||
import {closeDialogs} from "dialogs/utils";
|
import {closeDialogs} from "dialogs/utils";
|
||||||
|
import {restoreDefaultEvents} from "../../scripts/events";
|
||||||
|
|
||||||
let isLoaded = false;
|
let isLoaded = false;
|
||||||
|
|
||||||
|
|
@ -278,7 +279,7 @@ export function editRoute(onClick) {
|
||||||
elSelected.on("click", null);
|
elSelected.on("click", null);
|
||||||
} else {
|
} else {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
viewbox.on("click", clicked).style("cursor", "default");
|
restoreDefaultEvents();
|
||||||
elSelected.on("click", addInterimControlPoint).attr("data-new", null);
|
elSelected.on("click", addInterimControlPoint).attr("data-new", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,11 @@ import {showMainTip, tip} from "./tooltips";
|
||||||
|
|
||||||
export function restoreDefaultEvents() {
|
export function restoreDefaultEvents() {
|
||||||
Zoom.setZoomBehavior();
|
Zoom.setZoomBehavior();
|
||||||
viewbox.style("cursor", "default").on(".drag", null).on("click", clicked).on("touchmove mousemove", onMouseMove);
|
viewbox
|
||||||
|
.style("cursor", "default")
|
||||||
|
.on(".drag", null)
|
||||||
|
.on("click", handleMapClick)
|
||||||
|
.on("touchmove mousemove", onMouseMove);
|
||||||
scaleBar.on("mousemove", () => tip("Click to open Units Editor")).on("click", () => openDialog("unitsEditor"));
|
scaleBar.on("mousemove", () => tip("Click to open Units Editor")).on("click", () => openDialog("unitsEditor"));
|
||||||
legend
|
legend
|
||||||
.on("mousemove", () => tip("Drag to change the position. Click to hide the legend"))
|
.on("mousemove", () => tip("Drag to change the position. Click to hide the legend"))
|
||||||
|
|
@ -21,7 +25,7 @@ export function restoreDefaultEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// on viewbox click event - run function based on target
|
// on viewbox click event - run function based on target
|
||||||
function clicked() {
|
function handleMapClick() {
|
||||||
const el = d3.event.target;
|
const el = d3.event.target;
|
||||||
if (!el || !el.parentElement || !el.parentElement.parentElement) return;
|
if (!el || !el.parentElement || !el.parentElement.parentElement) return;
|
||||||
const parent = el.parentElement;
|
const parent = el.parentElement;
|
||||||
|
|
@ -35,7 +39,7 @@ function clicked() {
|
||||||
else if (grand.id === "routes") editRoute();
|
else if (grand.id === "routes") editRoute();
|
||||||
else if (el.tagName === "tspan" && grand.parentNode.parentNode.id === "labels") editLabel();
|
else if (el.tagName === "tspan" && grand.parentNode.parentNode.id === "labels") editLabel();
|
||||||
else if (grand.id === "burgLabels" || grand.id === "burgIcons") openDialog("burgEditor", null, {id: +el.dataset.id});
|
else if (grand.id === "burgLabels" || grand.id === "burgIcons") openDialog("burgEditor", null, {id: +el.dataset.id});
|
||||||
else if (parent.id === "ice") editIce();
|
else if (parent.id === "ice") openDialog("iceEditor");
|
||||||
else if (parent.id === "terrain") editReliefIcon();
|
else if (parent.id === "terrain") editReliefIcon();
|
||||||
else if (grand.id === "markers" || great.id === "markers") editMarker();
|
else if (grand.id === "markers" || great.id === "markers") editMarker();
|
||||||
else if (grand.id === "coastline") openDialog("coastlineEditor", null, {node: d3.event.target});
|
else if (grand.id === "coastline") openDialog("coastlineEditor", null, {node: d3.event.target});
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {assignSpeakerBehavior} from "./speaker";
|
||||||
import {addResizeListener} from "modules/ui/options";
|
import {addResizeListener} from "modules/ui/options";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {addDragToUpload} from "modules/io/load";
|
import {addDragToUpload} from "modules/io/load";
|
||||||
import {addHotkeyListeners} from "modules/ui/hotkeys";
|
import {addHotkeyListeners} from "scripts/hotkeys";
|
||||||
|
|
||||||
export function addGlobalListeners() {
|
export function addGlobalListeners() {
|
||||||
if (PRODUCTION) {
|
if (PRODUCTION) {
|
||||||
|
|
|
||||||
8
src/types/grid.d.ts
vendored
8
src/types/grid.d.ts
vendored
|
|
@ -2,16 +2,22 @@ interface IGrid {
|
||||||
spacing: number;
|
spacing: number;
|
||||||
boundary: TPoints;
|
boundary: TPoints;
|
||||||
points: TPoints;
|
points: TPoints;
|
||||||
features: IFeature[];
|
vertices: {
|
||||||
|
p: TPoints;
|
||||||
|
v: number[][];
|
||||||
|
c: number[][];
|
||||||
|
};
|
||||||
cells: {
|
cells: {
|
||||||
i: IntArray;
|
i: IntArray;
|
||||||
b: IntArray;
|
b: IntArray;
|
||||||
c: number[][];
|
c: number[][];
|
||||||
|
v: number[][];
|
||||||
h: IntArray;
|
h: IntArray;
|
||||||
t: IntArray;
|
t: IntArray;
|
||||||
f: IntArray;
|
f: IntArray;
|
||||||
prec: IntArray;
|
prec: IntArray;
|
||||||
};
|
};
|
||||||
|
features: IFeature[];
|
||||||
}
|
}
|
||||||
interface IFeature {
|
interface IFeature {
|
||||||
i: number;
|
i: number;
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ export function findCell(x: number, y: number, radius = Infinity): number | unde
|
||||||
}
|
}
|
||||||
|
|
||||||
// get polygon points for initial cells knowing cell id
|
// get polygon points for initial cells knowing cell id
|
||||||
export function getGridPolygon(i: number) {
|
export function getGridPolygon(i: number): TPoints {
|
||||||
return grid.cells.v[i].map(v => grid.vertices.p[v]);
|
return grid.cells.v[i].map(v => grid.vertices.p[v]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ export function splitInTwo(str: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// transform string to array [translateX,translateY,rotateDeg,rotateX,rotateY,scale]
|
// transform string to array [translateX,translateY,rotateDeg,rotateX,rotateY,scale]
|
||||||
export function parseTransform(str: string) {
|
export function parseTransform(str: string | null) {
|
||||||
if (!str) return [0, 0, 0, 0, 0, 1];
|
if (!str) return [0, 0, 0, 0, 0, 1];
|
||||||
|
|
||||||
const a = str
|
const a = str
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue