mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
v 0.8.0b
This commit is contained in:
parent
707913f630
commit
680044ddd6
65 changed files with 14257 additions and 13020 deletions
247
modules/ui/relief-editor.js
Normal file
247
modules/ui/relief-editor.js
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
"use strict";
|
||||
function editReliefIcon() {
|
||||
if (customization) return;
|
||||
closeDialogs(".stable");
|
||||
if (!layerIsOn("toggleRelief")) toggleRelief();
|
||||
|
||||
terrain.selectAll("use").call(d3.drag().on("drag", dragReliefIcon)).classed("draggable", true);
|
||||
elSelected = d3.select(d3.event.target);
|
||||
|
||||
restoreEditMode();
|
||||
updateReliefIconSelected();
|
||||
updateReliefSizeInput();
|
||||
|
||||
$("#reliefEditor").dialog({
|
||||
title: "Edit Relief Icons", resizable: false,
|
||||
position: {my: "center top+40", at: "top", of: d3.event, collision: "fit"},
|
||||
close: closeReliefEditor
|
||||
});
|
||||
|
||||
if (modules.editReliefIcon) return;
|
||||
modules.editReliefIcon = true;
|
||||
|
||||
// add listeners
|
||||
document.getElementById("reliefIndividual").addEventListener("click", enterIndividualMode);
|
||||
document.getElementById("reliefBulkAdd").addEventListener("click", enterBulkAddMode);
|
||||
document.getElementById("reliefBulkRemove").addEventListener("click", enterBulkRemoveMode);
|
||||
|
||||
document.getElementById("reliefSize").addEventListener("input", changeIconSize);
|
||||
document.getElementById("reliefSizeNumber").addEventListener("input", changeIconSize);
|
||||
reliefIconsDiv.querySelectorAll("button").forEach(el => el.addEventListener("click", changeIcon));
|
||||
|
||||
document.getElementById("reliefCopy").addEventListener("click", copyIcon);
|
||||
document.getElementById("reliefMoveFront").addEventListener("click", () => elSelected.raise());
|
||||
document.getElementById("reliefMoveBack").addEventListener("click", () => elSelected.lower());
|
||||
document.getElementById("reliefRemove").addEventListener("click", removeIcon);
|
||||
|
||||
function dragReliefIcon() {
|
||||
const dx = +this.getAttribute("x") - d3.event.x;
|
||||
const dy = +this.getAttribute("y") - d3.event.y;
|
||||
|
||||
d3.event.on("drag", function() {
|
||||
const x = d3.event.x, y = d3.event.y;
|
||||
this.setAttribute("x", dx+x);
|
||||
this.setAttribute("y", dy+y);
|
||||
});
|
||||
}
|
||||
|
||||
function restoreEditMode() {
|
||||
if (!reliefTools.querySelector("button.pressed")) enterIndividualMode(); else
|
||||
if (reliefBulkAdd.classList.contains("pressed")) enterBulkAddMode(); else
|
||||
if (reliefBulkRemove.classList.contains("pressed")) enterBulkRemoveMode();
|
||||
}
|
||||
|
||||
function updateReliefIconSelected() {
|
||||
const type = elSelected.attr("data-type");
|
||||
reliefIconsDiv.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed"));
|
||||
reliefIconsDiv.querySelector("button[data-type='"+type+"']").classList.add("pressed");
|
||||
}
|
||||
|
||||
function updateReliefSizeInput() {
|
||||
const size = +elSelected.attr("data-size");
|
||||
reliefSize.value = reliefSizeNumber.value = rn(size);
|
||||
}
|
||||
|
||||
function enterIndividualMode() {
|
||||
reliefTools.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed"));
|
||||
reliefIndividual.classList.add("pressed");
|
||||
|
||||
reliefSizeDiv.style.display = "block";
|
||||
reliefRadiusDiv.style.display = "none";
|
||||
reliefSpacingDiv.style.display = "none";
|
||||
reliefIconsSeletionAny.style.display = "none";
|
||||
|
||||
updateReliefSizeInput();
|
||||
restoreDefaultEvents();
|
||||
clearMainTip();
|
||||
}
|
||||
|
||||
function enterBulkAddMode() {
|
||||
reliefTools.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed"));
|
||||
reliefBulkAdd.classList.add("pressed");
|
||||
|
||||
reliefSizeDiv.style.display = "block";
|
||||
reliefRadiusDiv.style.display = "block";
|
||||
reliefSpacingDiv.style.display = "block";
|
||||
reliefIconsSeletionAny.style.display = "none";
|
||||
|
||||
const pressedType = reliefIconsDiv.querySelector("button.pressed");
|
||||
if (pressedType.id === "reliefIconsSeletionAny") { // in "any" is pressed, select first type
|
||||
reliefIconsSeletionAny.classList.remove("pressed");
|
||||
reliefIconsDiv.querySelector("button").classList.add("pressed");
|
||||
}
|
||||
|
||||
viewbox.style("cursor", "crosshair").call(d3.drag().on("start", dragToAdd)).on("touchmove mousemove", moveBrush);
|
||||
tip("Drag to place relief icons within radius", true);
|
||||
}
|
||||
|
||||
function moveBrush() {
|
||||
showMainTip();
|
||||
const point = d3.mouse(this);
|
||||
const radius = +reliefRadius.value;
|
||||
moveCircle(point[0], point[1], radius);
|
||||
}
|
||||
|
||||
function dragToAdd() {
|
||||
const pressed = reliefIconsDiv.querySelector("button.pressed");
|
||||
if (!pressed) {tip("Please select an icon", false, error); return;}
|
||||
|
||||
const type = pressed.dataset.type;
|
||||
const r = +reliefRadius.value;
|
||||
const spacing = +reliefSpacing.value;
|
||||
const size = +reliefSize.value;
|
||||
|
||||
// build a quadtree
|
||||
const tree = d3.quadtree();
|
||||
const positions = [];
|
||||
terrain.selectAll("use").each(function() {
|
||||
const x = +this.getAttribute("x") + this.getAttribute("width") / 2;
|
||||
const y = +this.getAttribute("y") + this.getAttribute("height") / 2;
|
||||
tree.add([x, y, x]);
|
||||
const box = this.getBBox();
|
||||
positions.push(box.y + box.height);
|
||||
});
|
||||
|
||||
d3.event.on("drag", function() {
|
||||
const p = d3.mouse(this);
|
||||
moveCircle(p[0], p[1], r);
|
||||
|
||||
d3.range(Math.ceil(r/10)).forEach(function() {
|
||||
const a = Math.PI * 2 * Math.random();
|
||||
const rad = r * Math.random();
|
||||
const cx = p[0] + rad * Math.cos(a);
|
||||
const cy = p[1] + rad * Math.sin(a);
|
||||
|
||||
if (tree.find(cx, cy, spacing)) return; // too close to existing icon
|
||||
if (pack.cells.h[findCell(cx, cy)] < 20) return; // on water cell
|
||||
|
||||
const h = rn(size / 2 * (Math.random() * .4 + .8), 2);
|
||||
const x = rn(cx-h, 2);
|
||||
const y = rn(cy-h, 2);
|
||||
const z = y + h * 2;
|
||||
|
||||
let nth = 1;
|
||||
while (positions[nth] && z > positions[nth]) {nth++;}
|
||||
|
||||
tree.add([cx, cy]);
|
||||
positions.push(z);
|
||||
terrain.insert("use", ":nth-child("+nth+")").attr("xlink:href", type).attr("data-type", type)
|
||||
.attr("x", x).attr("y", y).attr("data-size", h*2).attr("width", h*2).attr("height", h*2);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function enterBulkRemoveMode() {
|
||||
reliefTools.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed"));
|
||||
reliefBulkRemove.classList.add("pressed");
|
||||
|
||||
reliefSizeDiv.style.display = "none";
|
||||
reliefRadiusDiv.style.display = "block";
|
||||
reliefSpacingDiv.style.display = "none";
|
||||
reliefIconsSeletionAny.style.display = "inline-block";
|
||||
|
||||
viewbox.style("cursor", "crosshair").call(d3.drag().on("start", dragToRemove)).on("touchmove mousemove", moveBrush);;
|
||||
tip("Drag to remove relief icons in radius", true);
|
||||
}
|
||||
|
||||
function dragToRemove() {
|
||||
const pressed = reliefIconsDiv.querySelector("button.pressed");
|
||||
if (!pressed) {tip("Please select an icon", false, error); return;}
|
||||
|
||||
const r = +reliefRadius.value;
|
||||
const type = pressed.dataset.type;
|
||||
const icons = type ? terrain.selectAll("use[data-type='"+type+"']") : terrain.selectAll("use");
|
||||
const tree = d3.quadtree();
|
||||
icons.each(function() {
|
||||
const x = +this.getAttribute("x") + this.getAttribute("width") / 2;
|
||||
const y = +this.getAttribute("y") + this.getAttribute("height") / 2;
|
||||
tree.add([x, y, this]);
|
||||
});
|
||||
|
||||
d3.event.on("drag", function() {
|
||||
const p = d3.mouse(this);
|
||||
moveCircle(p[0], p[1], r);
|
||||
tree.findAll(p[0], p[1], r).forEach(f => f[2].remove());
|
||||
});
|
||||
}
|
||||
|
||||
function changeIconSize() {
|
||||
const size = +reliefSize.value;
|
||||
reliefSize.value = reliefSizeNumber.value = size;
|
||||
if (!reliefIndividual.classList.contains("pressed")) return;
|
||||
|
||||
const shift = (size - +elSelected.attr("width")) / 2;
|
||||
elSelected.attr("width", size).attr("height", size).attr("data-size", size);
|
||||
const x = +elSelected.attr("x"), y = +elSelected.attr("y");
|
||||
elSelected.attr("x", x-shift).attr("y", y-shift);
|
||||
}
|
||||
|
||||
function changeIcon() {
|
||||
if (this.classList.contains("pressed")) return;
|
||||
|
||||
reliefIconsDiv.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed"))
|
||||
this.classList.add("pressed");
|
||||
|
||||
if (reliefIndividual.classList.contains("pressed")) {
|
||||
const type = this.dataset.type;
|
||||
elSelected.attr("xlink:href", type).attr("data-type", type);
|
||||
}
|
||||
}
|
||||
|
||||
function copyIcon() {
|
||||
const parent = elSelected.node().parentNode;
|
||||
const copy = elSelected.node().cloneNode(true);
|
||||
|
||||
let x = +elSelected.attr("x") - 3, y = +elSelected.attr("y") - 3;
|
||||
while (parent.querySelector("[x='"+x+"']","[x='"+y+"']")) {
|
||||
x -= 3; y -= 3;
|
||||
}
|
||||
|
||||
copy.setAttribute("x", x);
|
||||
copy.setAttribute("y", y);
|
||||
parent.insertBefore(copy, null);
|
||||
}
|
||||
|
||||
function removeIcon() {
|
||||
alertMessage.innerHTML = `Are you sure you want to remove the icon?`;
|
||||
$("#alert").dialog({resizable: false, title: "Remove relief icon",
|
||||
buttons: {
|
||||
Remove: function() {
|
||||
$(this).dialog("close");
|
||||
elSelected.remove();
|
||||
$("#reliefEditor").dialog("close");
|
||||
},
|
||||
Cancel: function() {$(this).dialog("close");}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeReliefEditor() {
|
||||
terrain.selectAll("use").call(d3.drag().on("drag", null)).classed("draggable", false);
|
||||
removeCircle();
|
||||
unselect();
|
||||
clearMainTip();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue