New ramp types
Build Dusk / run-tests (push) Failing after 5m33s
Build Dusk / build-linux (push) Successful in 5m3s
Build Dusk / build-psp (push) Successful in 1m17s
Build Dusk / build-knulli (push) Successful in 4m45s
Build Dusk / build-gamecube (push) Successful in 3m49s
Build Dusk / build-gamecube-iso (push) Successful in 3m50s
Build Dusk / build-wii (push) Successful in 3m29s
Build Dusk / build-wii-iso (push) Successful in 4m4s
Build Dusk / run-tests (push) Failing after 5m33s
Build Dusk / build-linux (push) Successful in 5m3s
Build Dusk / build-psp (push) Successful in 1m17s
Build Dusk / build-knulli (push) Successful in 4m45s
Build Dusk / build-gamecube (push) Successful in 3m49s
Build Dusk / build-gamecube-iso (push) Successful in 3m50s
Build Dusk / build-wii (push) Successful in 3m29s
Build Dusk / build-wii-iso (push) Successful in 4m4s
This commit is contained in:
@@ -52,10 +52,8 @@
|
||||
<span id="zLevelLabel">0</span>
|
||||
</div>
|
||||
<div class="d-flex gap-3">
|
||||
<div class="d-flex flex-column gap-2">
|
||||
<button type="button" id="fillToggle" class="btn btn-sm btn-outline-secondary">Fill: Off</button>
|
||||
<div id="tilePalette" class="tile-palette"></div>
|
||||
</div>
|
||||
<div id="toolPalette" class="tile-palette"></div>
|
||||
<div id="tilePalette" class="tile-palette"></div>
|
||||
<canvas id="gridCanvas" class="border tile-grid" width="512" height="512"></canvas>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
{ type: ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST, name: "Ramp NW", color: "#ff5722" },
|
||||
{ type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST, name: "Ramp SE", color: "#9c27b0" },
|
||||
{ type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST, name: "Ramp SW", color: "#e91e63" },
|
||||
{ type: ChunkTerrain.TILE_SHAPE_RAMP_NORTHEAST_INNER, name: "Ramp NE Inner", color: "#795548" },
|
||||
{ type: ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST_INNER, name: "Ramp NW Inner", color: "#607d8b" },
|
||||
{ type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST_INNER, name: "Ramp SE Inner", color: "#8bc34a" },
|
||||
{ type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST_INNER, name: "Ramp SW Inner", color: "#ffc107" },
|
||||
];
|
||||
const SHAPE_COLORS = Object.fromEntries(SHAPES.map((s) => [s.type, s.color]));
|
||||
|
||||
@@ -31,6 +35,10 @@
|
||||
[ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST]: { dx: -1, dy: -1 },
|
||||
[ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST]: { dx: 1, dy: 1 },
|
||||
[ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST]: { dx: -1, dy: 1 },
|
||||
[ChunkTerrain.TILE_SHAPE_RAMP_NORTHEAST_INNER]: { dx: 1, dy: -1 },
|
||||
[ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST_INNER]: { dx: -1, dy: -1 },
|
||||
[ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST_INNER]: { dx: 1, dy: 1 },
|
||||
[ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST_INNER]: { dx: -1, dy: 1 },
|
||||
};
|
||||
|
||||
// Draws an arrow centered at (cx, cy) pointing toward the ramp's high
|
||||
@@ -65,6 +73,66 @@
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Draws a small pencil icon centered in a `size`x`size` canvas.
|
||||
function drawPencilIcon(ctx, size) {
|
||||
ctx.save();
|
||||
ctx.translate(size / 2, size / 2);
|
||||
ctx.rotate(-Math.PI / 4);
|
||||
|
||||
const shaftW = size * 0.18;
|
||||
const shaftH = size * 0.62;
|
||||
|
||||
ctx.fillStyle = "#e0e0e0";
|
||||
ctx.fillRect(-shaftW / 2, shaftH * 0.28, shaftW, shaftH * 0.22);
|
||||
|
||||
ctx.fillStyle = "#f0c419";
|
||||
ctx.fillRect(-shaftW / 2, -shaftH * 0.5, shaftW, shaftH * 0.78);
|
||||
|
||||
ctx.fillStyle = "#8d6e63";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(-shaftW / 2, -shaftH * 0.5);
|
||||
ctx.lineTo(shaftW / 2, -shaftH * 0.5);
|
||||
ctx.lineTo(0, -shaftH * 0.5 - shaftW);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// Draws a small paint bucket icon centered in a `size`x`size` canvas.
|
||||
function drawBucketIcon(ctx, size) {
|
||||
ctx.save();
|
||||
ctx.translate(size / 2, size / 2);
|
||||
|
||||
const w = size * 0.5, h = size * 0.34;
|
||||
|
||||
ctx.strokeStyle = "#e0e0e0";
|
||||
ctx.lineWidth = Math.max(1, size * 0.06);
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, -h * 0.4, w * 0.4, Math.PI, 0);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.fillStyle = "#03a9f4";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(-w / 2, -h * 0.2);
|
||||
ctx.lineTo(w / 2, -h * 0.2);
|
||||
ctx.lineTo(w * 0.32, h * 0.6);
|
||||
ctx.lineTo(-w * 0.32, h * 0.6);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(-w * 0.55, h * 0.75, size * 0.06, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
const TOOLS = [
|
||||
{ id: "pencil", name: "Pencil", draw: drawPencilIcon },
|
||||
{ id: "bucket", name: "Paint Bucket", draw: drawBucketIcon },
|
||||
];
|
||||
|
||||
let coord = { x: 0, y: 0, z: 0 };
|
||||
let tiles = new Int32Array(ChunkTerrain.TILE_COUNT);
|
||||
let meshes = [];
|
||||
@@ -74,7 +142,7 @@
|
||||
let zoomWorldH = 20;
|
||||
let dirty = false;
|
||||
let hoverTile = null;
|
||||
let fillMode = false;
|
||||
let activeTool = "pencil";
|
||||
|
||||
let mapRenderer = null;
|
||||
let terrainMesh = null;
|
||||
@@ -372,6 +440,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
function buildToolPalette() {
|
||||
const el = document.getElementById("toolPalette");
|
||||
el.innerHTML = "";
|
||||
for(const tool of TOOLS) {
|
||||
const btn = document.createElement("button");
|
||||
btn.type = "button";
|
||||
btn.className = "tile-swatch" + (tool.id === activeTool ? " active" : "");
|
||||
btn.style.background = "#2a2d33";
|
||||
btn.title = tool.name;
|
||||
btn.addEventListener("click", () => {
|
||||
activeTool = tool.id;
|
||||
buildToolPalette();
|
||||
});
|
||||
|
||||
const icon = document.createElement("canvas");
|
||||
icon.width = 32;
|
||||
icon.height = 32;
|
||||
icon.className = "tile-swatch-icon";
|
||||
tool.draw(icon.getContext("2d"), 32);
|
||||
btn.appendChild(icon);
|
||||
|
||||
el.appendChild(btn);
|
||||
}
|
||||
}
|
||||
|
||||
function canvasToTile(e, canvas) {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const cell = canvas.width / ChunkTerrain.CHUNK_WIDTH;
|
||||
@@ -655,7 +748,7 @@
|
||||
let draggingMeshIndex = -1;
|
||||
|
||||
gridCanvas.addEventListener("mousedown", (e) => {
|
||||
if(fillMode) {
|
||||
if(activeTool === "bucket") {
|
||||
fillAt(e);
|
||||
return;
|
||||
}
|
||||
@@ -719,14 +812,6 @@
|
||||
|
||||
document.getElementById("btnSave").addEventListener("click", runSave);
|
||||
|
||||
document.getElementById("fillToggle").addEventListener("click", () => {
|
||||
fillMode = !fillMode;
|
||||
const btn = document.getElementById("fillToggle");
|
||||
btn.textContent = fillMode ? "Fill: On" : "Fill: Off";
|
||||
btn.classList.toggle("btn-secondary", fillMode);
|
||||
btn.classList.toggle("btn-outline-secondary", !fillMode);
|
||||
});
|
||||
|
||||
document.getElementById("btnAddMesh").addEventListener("click", () => {
|
||||
const base = document.getElementById("meshPicker").value;
|
||||
if(!base) return;
|
||||
@@ -766,6 +851,7 @@
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
buildPalette();
|
||||
buildToolPalette();
|
||||
mapRenderer = MapRenderer.create(document.getElementById("previewCanvas"));
|
||||
bindEvents();
|
||||
await Promise.all([buildChunkBrowseList(), buildMeshPicker()]);
|
||||
|
||||
Reference in New Issue
Block a user