Files
bworld/client/systems/tile_editor_system.ts
T
2026-02-24 15:36:10 -03:00

100 lines
2.8 KiB
TypeScript

import { System } from "$/common/ecs/mod.ts";
import { point_inside_rec } from "$/common/utils.ts";
import { ClientWorld } from "$/client/client_world.ts";
import { Camera } from "$/client/components/camera.ts";
import { Tilemap } from "$/client/components/tilemap.ts";
import { DebugUI } from "$/client/debug_ui.ts";
import { InputManager } from "$/client/input_manager.ts";
export class TileEditorSystem extends System {
constructor() {
super();
}
update(world: ClientWorld, _delta: number): void {
if (!world.debugging) {
return;
}
DebugUI.ctx.save();
DebugUI.ctx.setTransform(1, 0, 0, 1, 0, 0);
const ctx = world.ctx;
const camera_entity = world.get_entities().values().find((e) => e.get(Camera)?.active);
const camera = camera_entity?.get(Camera);
if (!camera) {
return;
}
for (const entity of world.get_entities()) {
const tilemap = entity.get(Tilemap);
if (!tilemap) {
continue;
}
const scaled_size = tilemap.tile_size * tilemap.scale;
const mouse = InputManager.get_mouse_position();
DebugUI.begin("Tile Editor", 500, 10, 300);
DebugUI.progress_bar(0.5);
if (DebugUI.button("Save")) {
navigator.clipboard.writeText(JSON.stringify(tilemap));
}
for (let i = 0; i < tilemap.rows; i += 1) {
for (let j = 0; j < tilemap.columns; j += 1) {
const x = DebugUI.cursor_x + j * scaled_size;
const y = DebugUI.cursor_y;
const hovered = point_inside_rec(mouse.x, mouse.y, x, y, scaled_size, scaled_size);
if (DebugUI.is_inside_windows(mouse.x, mouse.y) && hovered && InputManager.is_mouse_pressed(0)) {
InputManager.consume_mouse(0);
tilemap.selected_tile = i * tilemap.columns + j;
}
ctx.drawImage(
tilemap.image,
j * tilemap.tile_size + (j * tilemap.margin),
i * tilemap.tile_size + (i * tilemap.margin),
tilemap.tile_size,
tilemap.tile_size,
x,
y,
scaled_size,
scaled_size,
);
}
DebugUI.advance(scaled_size);
}
DebugUI.end();
if (tilemap.editing) {
const world_x = mouse.x + camera.x;
const world_y = mouse.y + camera.y;
const tx = Math.floor(world_x / (tilemap.tile_size * tilemap.scale));
const ty = Math.floor(world_y / (tilemap.tile_size * tilemap.scale));
if (InputManager.is_mouse_pressed(0)) {
const maybe_tile = tilemap.tiles.find((tile) => tile.x === tx && tile.y === ty);
if (maybe_tile?.index !== tilemap.selected_tile) {
tilemap.tiles.push({ x: tx, y: ty, index: tilemap.selected_tile });
}
} else if (InputManager.is_mouse_pressed(1)) {
InputManager.consume_mouse(1);
const index = tilemap.tiles.findLastIndex((tile) => tile.x === tx && tile.y === ty);
if (index !== -1) {
tilemap.tiles.splice(index, 1);
}
}
}
}
DebugUI.ctx.restore();
}
}