🆙 FloorPlanner Add the select all button

This commit is contained in:
duckietm 2025-03-06 15:51:55 +01:00
parent 7e8f6254f9
commit e493428dc9
6 changed files with 93 additions and 36 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -683,6 +683,12 @@
height: 45px; height: 45px;
} }
&.icon-set-select {
background-image: url('@/assets/images/floorplaneditor/icon-select.png');
width: 40px;
height: 40px;
}
&.icon-tickets { &.icon-tickets {
background-image: url('@/assets/images/icons/tickets.png'); background-image: url('@/assets/images/icons/tickets.png');
width: 17px; width: 17px;

View File

@ -1,5 +1,5 @@
export const TILE_SIZE = 32; export const TILE_SIZE = 32;
export const MAX_NUM_TILE_PER_AXIS = 100; export const MAX_NUM_TILE_PER_AXIS = 95;
export const HEIGHT_SCHEME: string = 'x0123456789abcdefghijklmnopq'; export const HEIGHT_SCHEME: string = 'x0123456789abcdefghijklmnopq';

View File

@ -94,7 +94,7 @@ export class FloorplanEditor
const dx = Math.abs(mousePositionX - centreX); const dx = Math.abs(mousePositionX - centreX);
const dy = Math.abs(mousePositionY - centreY); const dy = Math.abs(mousePositionY - centreY);
const solution = (dx / (width * 0.5) + dy / (height * 0.5) <= 1);//todo: improve this const solution = (dx / (width * 0.5) + dy / (height * 0.5) <= 1); //todo: improve this
if(solution) if(solution)
{ {
@ -104,14 +104,12 @@ export class FloorplanEditor
{ {
this.onClick(x, y); this.onClick(x, y);
} }
else if(this._lastUsedTile.x !== x || this._lastUsedTile.y !== y) else if(this._lastUsedTile.x !== x || this._lastUsedTile.y !== y)
{ {
this._lastUsedTile.x = x; this._lastUsedTile.x = x;
this._lastUsedTile.y = y; this._lastUsedTile.y = y;
this.onClick(x, y); this.onClick(x, y);
} }
} }
return true; return true;
} }
@ -120,31 +118,30 @@ export class FloorplanEditor
return false; return false;
} }
private onClick(x: number, y: number): void private onClick(x: number, y: number, render: boolean = true, force: boolean = false): void
{ {
const tile = this._tilemap[y][x]; const tile = this._tilemap[y][x];
const heightIndex = HEIGHT_SCHEME.indexOf(tile.height); // When forcing, treat background ('x') as index 0.
let currentHeightIndex = (tile.height === 'x' && force) ? 0 : HEIGHT_SCHEME.indexOf(tile.height);
let futureHeightIndex = 0; let futureHeightIndex = 0;
switch(this._actionSettings.currentAction) switch(this._actionSettings.currentAction)
{ {
case FloorAction.DOOR: case FloorAction.DOOR:
if (!force && tile.height !== 'x')
if(tile.height !== 'x')
{ {
this._doorLocation.x = x; this._doorLocation.x = x;
this._doorLocation.y = y; this._doorLocation.y = y;
this.renderTiles(); if(render) this.renderTiles();
} }
return; return;
case FloorAction.UP: case FloorAction.UP:
if(tile.height === 'x') return; if (!force && tile.height === 'x') return;
futureHeightIndex = heightIndex + 1; futureHeightIndex = currentHeightIndex + 1;
break; break;
case FloorAction.DOWN: case FloorAction.DOWN:
if(tile.height === 'x' || (heightIndex <= 1)) return; if (!force && (tile.height === 'x' || (currentHeightIndex <= 1))) return;
futureHeightIndex = heightIndex - 1; futureHeightIndex = currentHeightIndex - 1;
break; break;
case FloorAction.SET: case FloorAction.SET:
futureHeightIndex = HEIGHT_SCHEME.indexOf(this._actionSettings.currentHeight); futureHeightIndex = HEIGHT_SCHEME.indexOf(this._actionSettings.currentHeight);
@ -155,25 +152,21 @@ export class FloorplanEditor
} }
if(futureHeightIndex === -1) return; if(futureHeightIndex === -1) return;
if(currentHeightIndex === futureHeightIndex) return;
if(heightIndex === futureHeightIndex) return; // Only update _width and _height if not forcing.
if (!force && futureHeightIndex > 0)
if(futureHeightIndex > 0)
{ {
if((x + 1) > this._width) this._width = x + 1; if ((x + 1) > this._width) this._width = x + 1;
if ((y + 1) > this._height) this._height = y + 1;
if((y + 1) > this._height) this._height = y + 1;
} }
const newHeight = HEIGHT_SCHEME[futureHeightIndex]; const newHeight = HEIGHT_SCHEME[futureHeightIndex];
if (!newHeight) return;
if(!newHeight) return;
// if(tile.isBlocked) return;
this._tilemap[y][x].height = newHeight; this._tilemap[y][x].height = newHeight;
this.renderTiles(); if(render) this.renderTiles();
} }
public renderTiles(): void public renderTiles(): void
@ -205,6 +198,51 @@ export class FloorplanEditor
} }
this.renderer.drawImage(this._image, asset.frame.x, asset.frame.y, asset.frame.w, asset.frame.h, positionX, positionY, asset.frame.w, asset.frame.h); this.renderer.drawImage(this._image, asset.frame.x, asset.frame.y, asset.frame.w, asset.frame.h, positionX, positionY, asset.frame.w, asset.frame.h);
// If the tile is selected, draw a semi-transparent blue overlay.
if (tile.selected)
{
this.renderer.fillStyle = 'rgba(0, 0, 255, 0.3)';
this.renderer.fillRect(positionX, positionY, asset.frame.w, asset.frame.h);
}
}
}
}
public toggleSelectAll(): void
{
const newState = true;
for (let y = 0; y < this._tilemap.length; y++)
{
for (let x = 0; x < this._tilemap[y].length; x++)
{
this._tilemap[y][x].selected = newState;
this.onClick(x, y, false, true);
}
}
this.recalcActiveArea();
this.renderTiles();
}
// New helper method to recalculate active area dimensions.
private recalcActiveArea(): void
{
this._width = 0;
this._height = 0;
for (let y = 0; y < this._tilemap.length; y++)
{
for (let x = 0; x < this._tilemap[y].length; x++)
{
if (this._tilemap[y][x].height !== 'x')
{
if ((x + 1) > this._width) this._width = x + 1;
if ((y + 1) > this._height) this._height = y + 1;
}
} }
} }
} }
@ -307,7 +345,6 @@ export class FloorplanEditor
} }
} }
const rows = []; const rows = [];
for(let y = 0; y < this._height; y++) for(let y = 0; y < this._height; y++)
@ -317,7 +354,6 @@ export class FloorplanEditor
for(let x = 0; x < this._width; x++) for(let x = 0; x < this._width; x++)
{ {
const tile = this._tilemap[y][x]; const tile = this._tilemap[y][x];
row[x] = tile.height; row[x] = tile.height;
} }
@ -341,8 +377,8 @@ export class FloorplanEditor
public clearCanvas(): void public clearCanvas(): void
{ {
this.renderer.fillStyle = '0x000000'; this.renderer.fillStyle = '#000000';
this.renderer.fillRect(0, 0, this._renderer.canvas.width, this._renderer.canvas.height); this.renderer.fillRect(0, 0, this._renderer.canvas.width, this._renderer.canvas.height);
} }
public get renderer(): CanvasRenderingContext2D public get renderer(): CanvasRenderingContext2D

View File

@ -2,11 +2,13 @@ export class Tile
{ {
private _height: string; private _height: string;
private _isBlocked: boolean; private _isBlocked: boolean;
private _selected: boolean; // new property
constructor(height: string, isBlocked: boolean) constructor(height: string, isBlocked: boolean)
{ {
this._height = height; this._height = height;
this._isBlocked = isBlocked; this._isBlocked = isBlocked;
this._selected = false; // default to not selected
} }
public get height(): string public get height(): string
@ -28,4 +30,14 @@ export class Tile
{ {
this._isBlocked = val; this._isBlocked = val;
} }
public get selected(): boolean
{
return this._selected;
}
public set selected(value: boolean)
{
this._selected = value;
}
} }

View File

@ -138,6 +138,9 @@ export const FloorplanOptionsView: FC<{}> = props =>
<LayoutGridItem itemActive={ (floorAction === FloorAction.DOOR) } onClick={ event => selectAction(FloorAction.DOOR) }> <LayoutGridItem itemActive={ (floorAction === FloorAction.DOOR) } onClick={ event => selectAction(FloorAction.DOOR) }>
<i className="icon icon-set-door" /> <i className="icon icon-set-door" />
</LayoutGridItem> </LayoutGridItem>
<LayoutGridItem onClick={ event => FloorplanEditor.instance.toggleSelectAll() }>
<i className="icon icon-set-select" />
</LayoutGridItem>
</Flex> </Flex>
</Column> </Column>
<Column alignItems="center" size={ 4 }> <Column alignItems="center" size={ 4 }>