Add support for biome X and Z limits

This commit is contained in:
Wuzzy 2024-11-30 14:52:59 +01:00
parent 9fb06eaaf3
commit 7e978ce417
3 changed files with 166 additions and 45 deletions

View File

@ -162,7 +162,7 @@ h3 {
margin-top: 0.2em; margin-top: 0.2em;
margin-bottom: 0.2em; margin-bottom: 0.2em;
} }
.statAltitude { .statPosition {
font-weight: bold; font-weight: bold;
color: #ffff00; color: #ffff00;
} }

View File

@ -37,7 +37,7 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
<div id="diagramInfoContainer" class="borderedSection"> <div id="diagramInfoContainer" class="borderedSection">
<span id="errorMessage" hidden></span> <span id="errorMessage" hidden></span>
<span id="altitudeDisplay"></span> <span id="worldPositionDisplay"></span>
<br> <br>
<span id="rangeDisplay">&nbsp;</span> <span id="rangeDisplay">&nbsp;</span>
<br> <br>
@ -80,10 +80,24 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
<br> <br>
<label for="inputMinX">Min. X:&nbsp;</label>
<input id="inputMinX" class="numInput" type="number" value="-31000" step="1">
<label for="inputMaxX">Max. X:&nbsp;</label>
<input id="inputMaxX" class="numInput" type="number" value="31000" step="1">
<br>
<label for="inputMinY">Min. Y:&nbsp;</label> <label for="inputMinY">Min. Y:&nbsp;</label>
<input id="inputMinY" class="numInput" type="number" value="-31000" step="1"> <input id="inputMinY" class="numInput" type="number" value="-31000" step="1">
<label for="inputMaxY">Max. Y:&nbsp;</label> <label for="inputMaxY">Max. Y:&nbsp;</label>
<input id="inputMaxY" class="numInput" type="number" value="31000" step="1"> <input id="inputMaxY" class="numInput" type="number" value="31000" step="1">
<br>
<label for="inputMinZ">Min. Z:&nbsp;</label>
<input id="inputMinZ" class="numInput" type="number" value="-31000" step="1">
<label for="inputMaxZ">Max. Z:&nbsp;</label>
<input id="inputMaxZ" class="numInput" type="number" value="31000" step="1">
</div> </div>
</form> </form>
</div> </div>
@ -112,9 +126,16 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
<h2 class="configHeader"><span class="collapser" id="viewConfigHeaderLink"></span> Diagram view settings</h2> <h2 class="configHeader"><span class="collapser" id="viewConfigHeaderLink"></span> Diagram view settings</h2>
<div id="viewConfigContainer" class="configFrame"> <div id="viewConfigContainer" class="configFrame">
<form id="viewForm"> <form id="viewForm">
<label for="inputViewY">Altitude:&nbsp;</label> World position:&nbsp;
<label for="inputViewX">X:&nbsp;</label>
<input id="inputViewX" class="numInput" type="number" value="0" step="1">
<label for="inputViewY">Y:&nbsp;</label>
<input id="inputViewY" class="numInput" type="number" value="0" step="1"> <input id="inputViewY" class="numInput" type="number" value="0" step="1">
<label for="inputViewZ">Z:&nbsp;</label>
<input id="inputViewZ" class="numInput" type="number" value="0" step="1">
<br> <br>
<input id="inputCheckboxPoints" type="checkbox" checked> <input id="inputCheckboxPoints" type="checkbox" checked>

182
libpov.js
View File

@ -1,8 +1,12 @@
"use strict"; "use strict";
// Default values for the min. and max. Y of biomes // Min. and max. possible coordinates of biomes
const MIN_Y_DEFAULT = -31000 const MIN_X = -31000
const MAX_Y_DEFAULT = 31000 const MAX_X = 31000
const MIN_Y = -31000
const MAX_Y = 31000
const MIN_Z = -31000
const MAX_Z = 31000
// Draw a grid line every GRID_STEP units // Draw a grid line every GRID_STEP units
const GRID_STEP = 10 const GRID_STEP = 10
@ -129,8 +133,10 @@ let draw_humidity_min, draw_humidity_max;
let midpoint_heat; let midpoint_heat;
let midpoint_humidity; let midpoint_humidity;
// Y altitude at which the diagram is currently viewed at // XYZ at which the diagram is currently viewed at
let viewX = 0;
let viewY = 0; let viewY = 0;
let viewZ = 0;
let v6_flag_snowbiomes = true; let v6_flag_snowbiomes = true;
let v6_flag_jungles = true; let v6_flag_jungles = true;
@ -306,7 +312,7 @@ function addBiomeRaw(biomeDef) {
} }
// Add a default biome at the midpoint // Add a default biome at the midpoint
addBiomeRaw({name: "default", heat: midpoint_heat, humidity: midpoint_humidity, min_y: MIN_Y_DEFAULT, max_y: MAX_Y_DEFAULT}); addBiomeRaw({name: "default", heat: midpoint_heat, humidity: midpoint_humidity, min_x: MIN_X, max_x: MAX_X, min_y: MIN_Y, max_y: MAX_Y, min_z: MIN_Z, max_z: MAX_Z});
// Add a new random biome to the biome list with the given biome definition. // Add a new random biome to the biome list with the given biome definition.
// Then select it and update widgets // Then select it and update widgets
@ -327,10 +333,28 @@ function addBiome(biomeDef) {
draw(true); draw(true);
} }
// Get the Y value of the viewed altitude // Get the X, Y or Z value of the viewed coordinate
function getViewY() { function getViewCoord(axis) {
if (axis === "x") {
return viewX;
} else if (axis === "y") {
return viewY; return viewY;
} else if (axis === "z") {
return viewZ;
}
} }
// Set the X, Y or Z value of the viewed coordinate
function setViewCoord(axis, value) {
if (axis === "x") {
viewX = value;
} else if (axis === "y") {
viewY = value;
} else if (axis === "z") {
viewZ = value;
}
}
// Returns the biome point by its given ID // Returns the biome point by its given ID
// or null if it couldn't be found // or null if it couldn't be found
function getBiomeByID(id) { function getBiomeByID(id) {
@ -835,13 +859,13 @@ function clear(context) {
return true; return true;
} }
/* Returns all biome points except those whose Y limits fall out of the /* Returns all biome points except those whose XYZ limits fall out of the
given y value */ given x, y and z values */
function getRenderedPoints(y) { function getRenderedPoints(x, y, z) {
let points = []; let points = [];
for (let p=0; p<biomePoints.length; p++) { for (let p=0; p<biomePoints.length; p++) {
let point = biomePoints[p]; let point = biomePoints[p];
if (y >= point.min_y && y <= point.max_y) { if (x >= point.min_x && x <= point.max_x && y >= point.min_y && y <= point.max_y && z >= point.min_z && z <= point.max_z) {
points.push(point); points.push(point);
} }
} }
@ -890,7 +914,7 @@ function showDiagramMessage(context, text) {
context.font = "200% sans-serif"; context.font = "200% sans-serif";
} }
context.fillText(text, voronoiCanvas.width/2, voronoiCanvas.height/2); context.fillText(text, voronoiCanvas.width/2, voronoiCanvas.height/2);
updateAltitudeText(); updateWorldPositionText();
} }
// Check if a diagram can be drawn on the draw context and // Check if a diagram can be drawn on the draw context and
@ -903,7 +927,7 @@ function checkDrawValid(context) {
if (!voronoiCanvas.hidden) { if (!voronoiCanvas.hidden) {
voronoiCanvas.hidden = true; voronoiCanvas.hidden = true;
coordinateDisplay.hidden = true; coordinateDisplay.hidden = true;
altitudeDisplay.hidden = true; worldPositionDisplay.hidden = true;
rangeDisplay.hidden = true; rangeDisplay.hidden = true;
configDiv.hidden = true; configDiv.hidden = true;
@ -953,7 +977,9 @@ function drawModern(recalculate) {
let context = getDrawContext(); let context = getDrawContext();
let w = voronoiCanvas.width; let w = voronoiCanvas.width;
let h = voronoiCanvas.height; let h = voronoiCanvas.height;
let y = getViewY(); let x = getViewCoord("x");
let y = getViewCoord("y");
let z = getViewCoord("z");
// shorter function name (for "convert") // shorter function name (for "convert")
let conv = biomeCoordsToCanvasPixelCoords let conv = biomeCoordsToCanvasPixelCoords
@ -963,20 +989,20 @@ function drawModern(recalculate) {
return false; return false;
} }
let points = getRenderedPoints(y); let points = getRenderedPoints(x, y, z);
// Fail and render a special message if there are no biomes // Fail and render a special message if there are no biomes
if (points.length === 0) { if (points.length === 0) {
if (biomePoints.length === 0) { if (biomePoints.length === 0) {
showDiagramMessage(context, "No biomes."); showDiagramMessage(context, "No biomes.");
} else { } else {
showDiagramMessage(context, "No biomes in this Y altitude."); showDiagramMessage(context, "No biomes at these coordinates.");
} }
drawError = true; drawError = true;
putResizeCorner(context); putResizeCorner(context);
return false; return false;
} }
updateAltitudeText(); updateWorldPositionText();
let voronoiError = function() { let voronoiError = function() {
showDiagramMessage(context, "Error in Javascript-Voronoi!"); showDiagramMessage(context, "Error in Javascript-Voronoi!");
@ -1151,7 +1177,6 @@ function drawV6() {
let context = getDrawContext(); let context = getDrawContext();
let w = voronoiCanvas.width; let w = voronoiCanvas.width;
let h = voronoiCanvas.height; let h = voronoiCanvas.height;
let y = getViewY();
clear(context); clear(context);
if (!checkDrawValid(context)) { if (!checkDrawValid(context)) {
@ -1398,8 +1423,12 @@ function updateWidgetStates() {
} }
inputHeat.disabled = state; inputHeat.disabled = state;
inputHumidity.disabled = state; inputHumidity.disabled = state;
inputMinX.disabled = state;
inputMaxX.disabled = state;
inputMinY.disabled = state; inputMinY.disabled = state;
inputMaxY.disabled = state; inputMaxY.disabled = state;
inputMinZ.disabled = state;
inputMaxZ.disabled = state;
inputBiomeName.disabled = state; inputBiomeName.disabled = state;
removeBiomeButton.disabled = state; removeBiomeButton.disabled = state;
for (let c=0; c<CELL_COLORS.length; c++) { for (let c=0; c<CELL_COLORS.length; c++) {
@ -1415,8 +1444,12 @@ function updateWidgetStates() {
let point = biomePoints[biomeSelector.selectedIndex]; let point = biomePoints[biomeSelector.selectedIndex];
inputHeat.value = point.heat; inputHeat.value = point.heat;
inputHumidity.value = point.humidity; inputHumidity.value = point.humidity;
inputMinX.value = point.min_x;
inputMaxX.value = point.max_x;
inputMinY.value = point.min_y; inputMinY.value = point.min_y;
inputMaxY.value = point.max_y; inputMaxY.value = point.max_y;
inputMinZ.value = point.min_z;
inputMaxZ.value = point.max_z;
inputBiomeName.value = point.name; inputBiomeName.value = point.name;
let colorIndex = point.colorIndex; let colorIndex = point.colorIndex;
for (let c=0; c<CELL_COLORS.length; c++) { for (let c=0; c<CELL_COLORS.length; c++) {
@ -1529,7 +1562,10 @@ function biomeCoordsToCanvasPixelCoords(heat, humidity) {
function getNearestPointFromCanvasPos(x, y, maxDist) { function getNearestPointFromCanvasPos(x, y, maxDist) {
let nearestPoint = null; let nearestPoint = null;
let nearestDist = null; let nearestDist = null;
let points = getRenderedPoints(getViewY()); let vx = getViewCoord("x");
let vy = getViewCoord("y");
let vz = getViewCoord("z");
let points = getRenderedPoints(vx, vy, vz);
for (let i=0; i<points.length; i++) { for (let i=0; i<points.length; i++) {
let point = points[i]; let point = points[i];
let [pixelX, pixelY] = biomeCoordsToCanvasPixelCoords(point.heat, point.humidity); let [pixelX, pixelY] = biomeCoordsToCanvasPixelCoords(point.heat, point.humidity);
@ -1579,7 +1615,10 @@ is dragging it */
function updatePointWhenDragged(pointID) { function updatePointWhenDragged(pointID) {
if (pointID !== null && !drawError && biomeMode === "modern") { if (pointID !== null && !drawError && biomeMode === "modern") {
let selectedPoint = null; let selectedPoint = null;
let points = getRenderedPoints(getViewY()); let x = getViewCoord("x");
let y = getViewCoord("y");
let z = getViewCoord("z");
let points = getRenderedPoints(x, y, z);
for (let i=0; i<points.length; i++) { for (let i=0; i<points.length; i++) {
if (points[i].id === dragDropPointID) { if (points[i].id === dragDropPointID) {
selectedPoint = points[i]; selectedPoint = points[i];
@ -1603,10 +1642,13 @@ function updatePointWhenDragged(pointID) {
} }
} }
/* Updates the text showing the current altitude (Y height) /* Updates the text showing the current coordinates
the diagram currently applies */ the diagram currently applies */
function updateAltitudeText() { function updateWorldPositionText() {
altitudeDisplay.innerHTML = "showing diagram for altitude Y=<span class='statAltitude'>"+getViewY()+"</span>"; let x = getViewCoord("x");
let y = getViewCoord("y");
let z = getViewCoord("z");
worldPositionDisplay.innerHTML = "showing biomes at world coordinates XYZ=<span class='statPosition'>("+x+","+y+","+z+")</span>";
} }
@ -1899,7 +1941,7 @@ voronoiCanvas.ondblclick = function(event) {
let [he, hu] = canvasPixelCoordsToBiomeCoords(event.offsetX, event.offsetY); let [he, hu] = canvasPixelCoordsToBiomeCoords(event.offsetX, event.offsetY);
he = Math.round(he); he = Math.round(he);
hu = Math.round(hu); hu = Math.round(hu);
addBiome({name: generateBiomeName(lastBiomeID), heat:he, humidity: hu, min_y:MIN_Y_DEFAULT, max_y:MAX_Y_DEFAULT}); addBiome({name: generateBiomeName(lastBiomeID), heat:he, humidity: hu, min_x:MIN_X, max_x:MAX_Y, min_y:MIN_Y, max_y:MAX_Y, min_z:MIN_Z, max_z:MAX_Z});
} }
voronoiCanvas.onmouseup = function(event) { voronoiCanvas.onmouseup = function(event) {
// end drag-n-drop // end drag-n-drop
@ -1932,8 +1974,12 @@ biomeSelector.onchange = function() {
let point = biomePoints[biomeSelector.selectedIndex]; let point = biomePoints[biomeSelector.selectedIndex];
inputHeat.value = point.heat; inputHeat.value = point.heat;
inputHumidity.value = point.humidity; inputHumidity.value = point.humidity;
inputMinX.value = point.min_x;
inputMaxX.value = point.max_x;
inputMinY.value = point.min_y; inputMinY.value = point.min_y;
inputMaxY.value = point.max_y; inputMaxY.value = point.max_y;
inputMinZ.value = point.min_z;
inputMaxZ.value = point.max_z;
} }
updateWidgetStates(); updateWidgetStates();
} }
@ -1946,7 +1992,7 @@ addBiomeButton.onclick = function() {
let hu_max = Math.min(MAX_HEAT_HUMIDITY_VALUE, limit_humidity_max); let hu_max = Math.min(MAX_HEAT_HUMIDITY_VALUE, limit_humidity_max);
let he = Math.round(he_min + Math.random() * (he_max - he_min)); let he = Math.round(he_min + Math.random() * (he_max - he_min));
let hu = Math.round(hu_min + Math.random() * (hu_max - hu_min)); let hu = Math.round(hu_min + Math.random() * (hu_max - hu_min));
addBiome({name: generateBiomeName(lastBiomeID), heat: he, humidity: hu, min_y: MIN_Y_DEFAULT, max_y: MAX_Y_DEFAULT}); addBiome({name: generateBiomeName(lastBiomeID), heat: he, humidity: hu, min_x:MIN_X, max_x:MAX_Y, min_y:MIN_Y, max_y:MAX_Y, min_z:MIN_Z, max_z:MAX_Z});
} }
removeBiomeButton.onclick = function() { removeBiomeButton.onclick = function() {
if (biomeSelector.selectedOptions.length === 0) { if (biomeSelector.selectedOptions.length === 0) {
@ -1999,12 +2045,24 @@ inputHeat.oninput = function() {
inputHumidity.oninput = function() { inputHumidity.oninput = function() {
handleBiomeNumberInput("humidity", this); handleBiomeNumberInput("humidity", this);
} }
inputMinX.oninput = function() {
handleBiomeNumberInput("min_x", this);
}
inputMaxX.oninput = function() {
handleBiomeNumberInput("max_x", this);
}
inputMinY.oninput = function() { inputMinY.oninput = function() {
handleBiomeNumberInput("min_y", this); handleBiomeNumberInput("min_y", this);
} }
inputMaxY.oninput = function() { inputMaxY.oninput = function() {
handleBiomeNumberInput("max_y", this); handleBiomeNumberInput("max_y", this);
} }
inputMinZ.oninput = function() {
handleBiomeNumberInput("min_z", this);
}
inputMaxZ.oninput = function() {
handleBiomeNumberInput("max_z", this);
}
inputBiomeName.oninput = function() { inputBiomeName.oninput = function() {
onChangeBiomeValueWidget("name", this.value); onChangeBiomeValueWidget("name", this.value);
} }
@ -2014,33 +2072,63 @@ inputHeat.onblur = function() {
inputHumidity.onblur = function() { inputHumidity.onblur = function() {
handleBiomeNumberBlur("humidity", this, 0); handleBiomeNumberBlur("humidity", this, 0);
} }
inputMinX.onblur = function() {
handleBiomeNumberBlur("min_x", this, MIN_X);
}
inputMaxX.onblur = function() {
handleBiomeNumberBlur("max_x", this, MAX_X);
}
inputMinY.onblur = function() { inputMinY.onblur = function() {
handleBiomeNumberBlur("min_y", this, -31000); handleBiomeNumberBlur("min_y", this, MIN_Y);
} }
inputMaxY.onblur = function() { inputMaxY.onblur = function() {
handleBiomeNumberBlur("max_y", this, 31000); handleBiomeNumberBlur("max_y", this, MAX_Y);
}
inputMinZ.onblur = function() {
handleBiomeNumberBlur("min_z", this, MIN_Z);
}
inputMaxZ.onblur = function() {
handleBiomeNumberBlur("max_z", this, MAX_Z);
} }
/* Diagram view settings events */ /* Diagram view settings events */
inputViewY.oninput = function() { let h_inputViewXYZ_oninput = function(axis, value) {
let y = +this.value; if (value === null) {
if (y === null) {
return; return;
} }
viewY = Math.floor(y); setViewCoord(axis, Math.floor(value));
draw(true); draw(true);
updateAltitudeText(); updateWorldPositionText();
} }
inputViewY.onblur = function() { let h_inputViewXYZ_onblur = function(axis, value, ref) {
let y = +this.value; if (value === null || value === "") {
if (y === null || this.value === "") { ref.value = 0;
this.value = 0; setViewCoord("axis", 0);
viewY = 0;
draw(true); draw(true);
updateAltitudeText(); updateWorldPositionText();
} }
} }
inputViewX.oninput = function() {
h_inputViewXYZ_oninput("x", this.value);
}
inputViewX.onblur = function() {
h_inputViewXYZ_onblur("x", this.value, this);
}
inputViewY.oninput = function() {
h_inputViewXYZ_oninput("y", this.value);
}
inputViewY.onblur = function() {
h_inputViewXYZ_onblur("y", this.value, this);
}
inputViewZ.oninput = function() {
h_inputViewXYZ_oninput("z", this.value);
}
inputViewZ.onblur = function() {
h_inputViewXYZ_onblur("z", this.value, this);
}
inputCheckboxNames.onchange = function() { inputCheckboxNames.onchange = function() {
showNames = this.checked; showNames = this.checked;
@ -2193,8 +2281,8 @@ inputExportLua.onclick = function() {
str += ` name = \"${escapedName}\",\n`; str += ` name = \"${escapedName}\",\n`;
str += ` heat_point = ${biome.heat},\n`; str += ` heat_point = ${biome.heat},\n`;
str += ` humidity_point = ${biome.humidity},\n`; str += ` humidity_point = ${biome.humidity},\n`;
str += ` y_min = ${biome.min_y},\n`; str += ` min_pos { x = ${biome.min_x}, y = ${biome.min_y}, z = ${biome.min_z} },\n`;
str += ` y_max = ${biome.max_y},\n`; str += ` max_pos { x = ${biome.max_x}, y = ${biome.max_y}, z = ${biome.max_z} },\n`;
str += "})\n"; str += "})\n";
} }
exportSectionText.innerText = str; exportSectionText.innerText = str;
@ -2219,8 +2307,12 @@ inputExportJSON.onclick = function() {
jsonPoint.name = biome.name; jsonPoint.name = biome.name;
jsonPoint.heat_point = biome.heat; jsonPoint.heat_point = biome.heat;
jsonPoint.humidity_point = biome.humidity; jsonPoint.humidity_point = biome.humidity;
jsonPoint.x_min = biome.min_x;
jsonPoint.x_max = biome.max_x;
jsonPoint.y_min = biome.min_y; jsonPoint.y_min = biome.min_y;
jsonPoint.y_max = biome.max_y; jsonPoint.y_max = biome.max_y;
jsonPoint.z_min = biome.min_z;
jsonPoint.z_max = biome.max_z;
jsonPoints.push(jsonPoint); jsonPoints.push(jsonPoint);
} }
@ -2272,8 +2364,12 @@ inputExportAmidstForMinetest.onclick = function() {
} else { } else {
jsonPoint.color = { r: 255, g: 255, b: 255 }; jsonPoint.color = { r: 255, g: 255, b: 255 };
} }
jsonPoint.x_min = biome.min_x;
jsonPoint.x_max = biome.max_x;
jsonPoint.y_min = biome.min_y; jsonPoint.y_min = biome.min_y;
jsonPoint.y_max = biome.max_y; jsonPoint.y_max = biome.max_y;
jsonPoint.z_min = biome.min_z;
jsonPoint.z_max = biome.max_z;
jsonPoint.heat_point = biome.heat; jsonPoint.heat_point = biome.heat;
jsonPoint.humidity_point = biome.humidity; jsonPoint.humidity_point = biome.humidity;
jsonPoints.push(jsonPoint); jsonPoints.push(jsonPoint);
@ -2376,8 +2472,12 @@ inputImportSubmit.onclick = function() {
name: parsedPoint.name, name: parsedPoint.name,
heat: parsedPoint.heat_point, heat: parsedPoint.heat_point,
humidity: parsedPoint.humidity_point, humidity: parsedPoint.humidity_point,
min_x: parsedPoint.x_min,
max_x: parsedPoint.x_max,
min_y: parsedPoint.y_min, min_y: parsedPoint.y_min,
max_y: parsedPoint.y_max, max_y: parsedPoint.y_max,
min_z: parsedPoint.z_min,
max_z: parsedPoint.z_max,
colorIndex: lastBiomeID % CELL_COLORS.length, colorIndex: lastBiomeID % CELL_COLORS.length,
}; };
lastBiomeID++; lastBiomeID++;
@ -2471,7 +2571,7 @@ window.addEventListener("load", function() {
}) })
window.addEventListener("load", repopulateBiomeSelector); window.addEventListener("load", repopulateBiomeSelector);
window.addEventListener("load", updateWidgetStates); window.addEventListener("load", updateWidgetStates);
window.addEventListener("load", updateAltitudeText); window.addEventListener("load", updateWorldPositionText);
window.addEventListener("load", unhideContent); window.addEventListener("load", unhideContent);
window.addEventListener("load", fitCanvasInBody); window.addEventListener("load", fitCanvasInBody);
window.addEventListener("load", disableFormSubmission); window.addEventListener("load", disableFormSubmission);