Editor: center/pad the level, fix some bugs with pencil drawing

This commit is contained in:
Eevee (Evelyn Woods) 2020-11-28 11:07:02 -07:00
parent 349af15e05
commit dff3081194
4 changed files with 60 additions and 26 deletions

View File

@ -191,7 +191,12 @@
also deal with levels vs level /packs/ somehow, not sure how that'll work (including downloading them, yeargh?)
-->
</header>
<div class="level"><!-- level canvas and any overlays go here --></div>
<div class="editor-canvas">
<div class="-container">
<!-- level canvas and any overlays go here -->
<!-- the container is to allow them to scroll as a single unit -->
</div>
</div>
<nav class="controls">
<div id="editor-toolbar">
<!-- tools go here -->

View File

@ -84,6 +84,19 @@ class MouseOperation {
this.cleanup();
}
*iter_touched_cells(gxf, gyf) {
for (let pt of walk_grid(
this.gx1f, this.gy1f, gxf, gyf,
// Bound the grid walk to one cell beyond the edges of the level, so that dragging the
// mouse in from outside the actual edges still works reliably
-1, -1, this.editor.stored_level.size_x, this.editor.stored_level.size_y))
{
if (this.editor.is_in_bounds(...pt)) {
yield pt;
}
}
}
// Implement these
start() {}
step(x, y) {}
@ -94,8 +107,9 @@ class MouseOperation {
class PanOperation extends MouseOperation {
step(mx, my) {
this.editor.viewport_el.scrollLeft -= mx - this.mx1;
this.editor.viewport_el.scrollTop -= my - this.my1;
let target = this.editor.viewport_el.parentNode;
target.scrollLeft -= mx - this.mx1;
target.scrollTop -= my - this.my1;
}
}
@ -107,7 +121,7 @@ class PencilOperation extends DrawOperation {
this.editor.place_in_cell(this.gx1, this.gy1, this.editor.palette_selection);
}
step(mx, my, gxf, gyf) {
for (let [x, y] of walk_grid(this.gx1f, this.gy1f, gxf, gyf)) {
for (let [x, y] of this.iter_touched_cells(gxf, gyf)) {
this.editor.place_in_cell(x, y, this.editor.palette_selection);
}
}
@ -125,7 +139,7 @@ class ForceFloorOperation extends DrawOperation {
// the same direction, but shouldn't
let i = 0;
let prevx, prevy;
for (let [x, y] of walk_grid(this.gx1f, this.gy1f, gxf, gyf)) {
for (let [x, y] of this.iter_touched_cells(gxf, gyf)) {
i++;
// The very first cell is the one the mouse was already in, and we don't
// have a movement direction yet, so leave that alone
@ -542,7 +556,7 @@ export class Editor extends PrimaryView {
constructor(conductor) {
super(conductor, document.body.querySelector('main#editor'));
this.viewport_el = this.root.querySelector('.level');
this.viewport_el = this.root.querySelector('.editor-canvas .-container');
// FIXME don't hardcode size here, convey this to renderer some other way
this.renderer = new CanvasRenderer(this.conductor.tileset, 32);
@ -575,6 +589,7 @@ export class Editor extends PrimaryView {
}
else if (ev.button === 1) {
// Middle button: always pan
console.log("middle button!");
this.mouse_op = new PanOperation(this, ev);
ev.preventDefault();
@ -593,7 +608,10 @@ export class Editor extends PrimaryView {
this.renderer.draw();
}
});
this.viewport_el.addEventListener('mousemove', ev => {
// Once the mouse is down, we should accept mouse movement anywhere
window.addEventListener('mousemove', ev => {
if (! this.active)
return;
if (! this.mouse_op)
return;
if ((ev.buttons & this.mouse_op.button_mask) === 0) {
@ -766,7 +784,7 @@ export class Editor extends PrimaryView {
}
}
is_in_level(x, y) {
is_in_bounds(x, y) {
return 0 <= x && x < this.stored_level.size_x && 0 <= y && y < this.stored_level.size_y;
}
@ -775,11 +793,6 @@ export class Editor extends PrimaryView {
if (! name)
return;
// TODO seems like a big problem to silently ignore, but it can happen from mouse
// coordinates while drawing
if (! this.is_in_level(x, y))
return;
let type = TILE_TYPES[name];
let direction;
if (type.is_actor) {

View File

@ -153,7 +153,7 @@ export function string_from_buffer_ascii(buf, start = 0, len) {
}
// Cast a line through a grid and yield every cell it touches
export function* walk_grid(x0, y0, x1, y1) {
export function* walk_grid(x0, y0, x1, y1, min_a, min_b, max_a, max_b) {
// TODO if the ray starts outside the grid (extremely unlikely), we should
// find the point where it ENTERS the grid, otherwise the 'while'
// conditions below will stop immediately
@ -193,27 +193,24 @@ export function* walk_grid(x0, y0, x1, y1) {
step_a = -step_a;
offset_x = 1 - offset_x;
}
// Zero offset means we're on a grid line, so we're actually a full cell
// away from the next grid line
if (offset_x === 0) {
else if (offset_x === 0) {
// Zero offset means we're on a grid line, so we're a full cell away from the next grid line
// (if we're moving forward; if we're moving backward, the next cell really is 0 away)
offset_x = 1;
}
let step_b = 1;
let offset_y = 1 - (y0 - b);
let offset_y = 1 - (y0 - b);
if (dy < 0) {
dy = -dy;
step_b = -step_b;
offset_y = 1 - offset_y;
}
if (offset_y === 0) {
else if (offset_y === 0) {
offset_y = 1;
}
let err = dy * offset_x - dx * offset_y;
let min_a = 0, min_b = 0;
// TODO get these passed in fool
let max_a = 31, max_b = 31;
if (dx > dy) {
// Main axis is x/a
while (min_a <= a && a <= max_a && min_b <= b && b <= max_b) {
@ -252,6 +249,8 @@ export function* walk_grid(x0, y0, x1, y1) {
}
}
}
window.walk_grid = walk_grid;
// console.table(Array.from(walk_grid(13, 27.133854389190674, 12.90625, 27.227604389190674)))
// Root class to indirect over where we might get files from
// - a pool of uploaded in-memory files

View File

@ -883,14 +883,31 @@ main.--has-demo .demo-controls {
margin: auto 1em;
}
#editor .level {
#editor .editor-canvas {
grid-area: level;
position: relative;
overflow: auto;
/* Padding and background make it easier to tell when we're at the edge of the map */
/* TODO padding should be half a cell, and svg should respect it too */
/* padding: 1em; */
/* Flex layout to center the canvas and overlay together */
display: flex;
align-items: center;
justify-content: center;
align-items: safe center;
justify-content: safe center;
background: #202020;
border: 0.125em solid black;
}
#editor .editor-canvas .-container {
/* Give the canvas/overlay a bit of a margin; it has to be a border because, due to some quirk
* of overflowing flexboxes I guess, padding and margins won't extend the scroll area on the
* right and bottom */
/* TODO padding should be half a cell? */
border: 1em solid transparent;
}
#editor .editor-canvas canvas {
display: block;
width: calc(var(--viewport-width) * var(--tile-width) * var(--scale));
--viewport-width: 9;
--viewport-height: 9;
}
/* SVG overlays */
#editor svg.level-editor-overlay {