Fix: Move Floorplan out of Pixi and make it full selectable

This commit is contained in:
duckietm 2024-03-18 14:22:08 +01:00
parent 8c244f1132
commit 304e945c13
17 changed files with 401 additions and 179 deletions

21
src/common/Slider.tsx Normal file
View File

@ -0,0 +1,21 @@
import { FC } from 'react';
import ReactSlider, { ReactSliderProps } from 'react-slider';
import { Button } from './Button';
import { Flex } from './Flex';
import { FaAngleLeft, FaAngleRight } from 'react-icons/fa';
export interface SliderProps extends ReactSliderProps
{
disabledButton?: boolean;
}
export const Slider: FC<SliderProps> = props =>
{
const { disabledButton, max, min, value, onChange, ...rest } = props;
return <Flex fullWidth gap={ 1 }>
{ !disabledButton && <Button disabled={ min >= value } onClick={ () => onChange(min < value ? value - 1 : min, 0) }><FaAngleLeft /></Button> }
<ReactSlider className={ 'nitro-slider' } max={ max } min={ min } value={ value } onChange={ onChange } { ...rest } />
{ !disabledButton && <Button disabled={ max <= value } onClick={ () => onChange(max > value ? value + 1 : max, 0) }><FaAngleRight /></Button> }
</Flex>;
}

View File

@ -16,6 +16,7 @@ export * from './HorizontalRule';
export * from './InfiniteScroll';
export * from './layout';
export * from './layout/limited-edition';
export * from "./Slider";
export * from './Text';
export * from './transitions';
export * from './types';

View File

@ -4,6 +4,6 @@
}
.floorplan-import-export {
width: 500px;
width: 630px;
height: 475px;
}

View File

@ -3,11 +3,11 @@ import { FC, useEffect, useState } from 'react';
import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../api';
import { Button, ButtonGroup, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common';
import { useMessageEvent, useRoomEngineEvent } from '../../hooks';
import { FloorplanEditorContextProvider } from './FloorplanEditorContext';
import { FloorplanEditor } from './common/FloorplanEditor';
import { IFloorplanSettings } from './common/IFloorplanSettings';
import { IVisualizationSettings } from './common/IVisualizationSettings';
import { convertNumbersForSaving, convertSettingToNumber } from './common/Utils';
import { FloorplanEditorContextProvider } from './FloorplanEditorContext';
import { FloorplanCanvasView } from './views/FloorplanCanvasView';
import { FloorplanImportExportView } from './views/FloorplanImportExportView';
import { FloorplanOptionsView } from './views/FloorplanOptionsView';
@ -135,11 +135,6 @@ export const FloorplanEditorView: FC<{}> = props =>
return () => RemoveLinkEventTracker(linkTracker);
}, []);
useEffect(() =>
{
FloorplanEditor.instance.initialize();
}, []);
return (
<FloorplanEditorContextProvider value={ { originalFloorplanSettings: originalFloorplanSettings, setOriginalFloorplanSettings: setOriginalFloorplanSettings, visualizationSettings: visualizationSettings, setVisualizationSettings: setVisualizationSettings } }>
{ isVisible &&
@ -162,4 +157,4 @@ export const FloorplanEditorView: FC<{}> = props =>
<FloorplanImportExportView onCloseClick={ () => setImportExportVisible(false) } /> }
</FloorplanEditorContextProvider>
);
}
}

View File

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

View File

@ -1,10 +1,11 @@
import { GetAssetManager, IGraphicAssetCollection, NitroPoint, NitroTilemap, PixiApplicationProxy, PixiInteractionEventProxy, POINT_STRUCT_SIZE } from '@nitrots/nitro-renderer';
import { NitroPoint } from '@nitrots/nitro-renderer';
import { ActionSettings } from './ActionSettings';
import { FloorAction, HEIGHT_SCHEME, MAX_NUM_TILE_PER_AXIS, TILE_SIZE } from './Constants';
import { imageBase64, spritesheet } from './FloorplanResource';
import { Tile } from './Tile';
import { getScreenPositionForTile, getTileFromScreenPosition } from './Utils';
import { getScreenPositionForTile } from './Utils';
export class FloorplanEditor extends PixiApplicationProxy
export class FloorplanEditor
{
private static _INSTANCE: FloorplanEditor = null;
@ -14,160 +15,107 @@ export class FloorplanEditor extends PixiApplicationProxy
private _tilemap: Tile[][];
private _width: number;
private _height: number;
private _isHolding: boolean;
private _isPointerDown: boolean;
private _doorLocation: NitroPoint;
private _lastUsedTile: NitroPoint;
private _tilemapRenderer: NitroTilemap;
private _renderer: CanvasRenderingContext2D;
private _actionSettings: ActionSettings;
private _isInitialized: boolean;
private _assetCollection: IGraphicAssetCollection;
private _image: HTMLImageElement;
constructor()
{
const width = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20;
const height = (TILE_SIZE * MAX_NUM_TILE_PER_AXIS) / 2 + 100;
super({
width: width,
height: height,
backgroundColor: 0x000000,
antialias: true,
autoDensity: true,
resolution: 1,
sharedLoader: true,
sharedTicker: true
});
const canvas = document.createElement('canvas');
canvas.height = height;
canvas.width = width;
canvas.style.touchAction = 'none';
this._renderer = canvas.getContext('2d');
this._image = new Image();
this._image.src = imageBase64;
this._tilemap = [];
this._doorLocation = new NitroPoint(0, 0);
this._width = 0;
this._height = 0;
this._isHolding = false;
this._isPointerDown = false;
this._lastUsedTile = new NitroPoint(-1, -1);
this._actionSettings = new ActionSettings();
}
public initialize(): void
public onPointerRelease(): void
{
if(this._isInitialized) return;
this._isPointerDown = false;
}
const collection = GetAssetManager().getCollection('floor_editor');
public onPointerDown(event: PointerEvent): void
{
if(event.button === 2) return;
if(!collection) return;
const location = new NitroPoint(event.offsetX, event.offsetY);
this._assetCollection = collection;
this._tilemapRenderer = new NitroTilemap(collection.baseTexture);
this.registerEventListeners();
this.stage.addChild(this._tilemapRenderer);
this._isPointerDown = true;
this._isInitialized = true;
this.tileHitDetection(location, true);
}
private registerEventListeners(): void
public onPointerMove(event: PointerEvent): void
{
//this._tilemapRenderer.interactive = true;
const tempPoint = new NitroPoint();
// @ts-ignore
this._tilemapRenderer.containsPoint = (position) =>
{
this._tilemapRenderer.worldTransform.applyInverse(position, tempPoint);
return this.tileHitDetection(tempPoint, false);
};
this._tilemapRenderer.on('pointerup', () =>
{
this._isHolding = false;
});
this._tilemapRenderer.on('pointerout', () =>
{
this._isHolding = false;
});
this._tilemapRenderer.on('pointerdown', (event: PixiInteractionEventProxy) =>
{
if(!(event.data.originalEvent instanceof PointerEvent) && !(event.data.originalEvent instanceof TouchEvent)) return;
const pointerEvent = event.data.originalEvent;
if((pointerEvent instanceof MouseEvent) && pointerEvent.button === 2) return;
const location = event.data.global;
this.tileHitDetection(location, true);
});
this._tilemapRenderer.on('click', (event: PixiInteractionEventProxy) =>
{
if(!(event.data.originalEvent instanceof PointerEvent)) return;
const pointerEvent = event.data.originalEvent;
if(pointerEvent.button === 2) return;
const location = event.data.global;
this.tileHitDetection(location, true, true);
});
if(!this._isPointerDown) return;
const location = new NitroPoint(event.offsetX, event.offsetY);
this.tileHitDetection(location, false);
}
private tileHitDetection(tempPoint: NitroPoint, setHolding: boolean, isClick: boolean = false): boolean
private tileHitDetection(tempPoint: NitroPoint, isClick: boolean = false): boolean
{
// @ts-ignore
const buffer = this._tilemapRenderer.pointsBuf;
const bufSize = POINT_STRUCT_SIZE;
const mousePositionX = Math.floor(tempPoint.x);
const mousePositionY = Math.floor(tempPoint.y);
const len = buffer.length;
const width = TILE_SIZE;
const height = TILE_SIZE / 2;
if(setHolding)
for(let y = 0; y < this._tilemap.length; y++)
{
this._isHolding = true;
}
for(let j = 0; j < len; j += bufSize)
{
const bufIndex = j + bufSize;
const data = buffer.slice(j, bufIndex);
const width = TILE_SIZE;
const height = TILE_SIZE / 2;
const mousePositionX = Math.floor(tempPoint.x);
const mousePositionY = Math.floor(tempPoint.y);
const tileStartX = data[2];
const tileStartY = data[3];
const centreX = tileStartX + (width / 2);
const centreY = tileStartY + (height / 2);
const dx = Math.abs(mousePositionX - centreX);
const dy = Math.abs(mousePositionY - centreY);
const solution = (dx / (width * 0.5) + dy / (height * 0.5) <= 1);//todo: improve this
if(solution)
for(let x = 0; x < this.tilemap[y].length; x++)
{
if(this._isHolding)
const [ tileStartX, tileStartY ] = getScreenPositionForTile(x, y);
const centreX = tileStartX + (width / 2);
const centreY = tileStartY + (height / 2);
const dx = Math.abs(mousePositionX - centreX);
const dy = Math.abs(mousePositionY - centreY);
const solution = (dx / (width * 0.5) + dy / (height * 0.5) <= 1);//todo: improve this
if(solution)
{
const [ realX, realY ] = getTileFromScreenPosition(tileStartX, tileStartY);
if(isClick)
if(this._isPointerDown)
{
this.onClick(realX, realY);
}
if(isClick)
{
this.onClick(x, y);
}
else if(this._lastUsedTile.x !== realX || this._lastUsedTile.y !== realY)
{
this._lastUsedTile.x = realX;
this._lastUsedTile.y = realY;
this.onClick(realX, realY);
}
else if(this._lastUsedTile.x !== x || this._lastUsedTile.y !== y)
{
this._lastUsedTile.x = x;
this._lastUsedTile.y = y;
this.onClick(x, y);
}
}
return true;
}
return true;
}
}
return false;
}
@ -221,7 +169,7 @@ export class FloorplanEditor extends PixiApplicationProxy
if(!newHeight) return;
if(tile.isBlocked) return;
// if(tile.isBlocked) return;
this._tilemap[y][x].height = newHeight;
@ -230,7 +178,7 @@ export class FloorplanEditor extends PixiApplicationProxy
public renderTiles(): void
{
this.tilemapRenderer.clear();
this.clearCanvas();
for(let y = 0; y < this._tilemap.length; y++)
{
@ -244,10 +192,13 @@ export class FloorplanEditor extends PixiApplicationProxy
if(tile.isBlocked) assetName = FloorplanEditor.TILE_BLOCKED;
//if((tile.height === 'x') || tile.height === 'X') continue;
const [ positionX, positionY ] = getScreenPositionForTile(x, y);
if ((tile.height === 'x' || tile.height === 'X') && tile.isBlocked) assetName = 'x';
this._tilemapRenderer.tile(this._assetCollection.getTexture(`floor_editor_${ assetName }`), positionX, positionY);
const [ positionX, positionY ] = getScreenPositionForTile(x, y);
const asset = spritesheet.frames[assetName];
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);
}
}
}
@ -372,20 +323,25 @@ export class FloorplanEditor extends PixiApplicationProxy
public clear(): void
{
this._tilemapRenderer.interactive = false;
this._tilemap = [];
this._doorLocation.set(-1, -1);
this._width = 0;
this._height = 0;
this._isHolding = false;
this._isPointerDown = false;
this._lastUsedTile.set(-1, -1);
this._actionSettings.clear();
this._tilemapRenderer.clear();
this.clearCanvas();
}
public get tilemapRenderer(): NitroTilemap
public clearCanvas(): void
{
return this._tilemapRenderer;
this.renderer.fillStyle = '0x000000';
this.renderer.fillRect(0, 0, this._renderer.canvas.width, this._renderer.canvas.height);
}
public get renderer(): CanvasRenderingContext2D
{
return this._renderer;
}
public get tilemap(): Tile[][]
@ -417,4 +373,4 @@ export class FloorplanEditor extends PixiApplicationProxy
return FloorplanEditor._INSTANCE;
}
}
}

View File

@ -0,0 +1,227 @@
export const imageBase64 =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGwAAAC+CAMAAADnThrbAAAAYFBMVEUAAAAiIiIAZf8A6P8A/5MZ/wCb/wD/tQD/MgD/AHr/APxDXocAkf8A/+oA/2hE/wDy/wD/iQD/BwD/AKXWAP////8AvP8A/78A/z1w/wD/4AD/XgD/ACP/ANGqAP8QEBBSz3qJAAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAABJxJREFUeNrt1tuOszoMBeDpD7QFBloKDGf6/m+51UTj1PUhN1uWOup3vSQLkSzn6+vV4fAV9X9lLIcdDv/+xWKHw/d3PPPzE8k8Rj1osceoBz3z4yiZ31HauN9R2rjfUcq451HSuOdR0rjnUcK411HcuNdR3LjXUcw4btTrOG7U6zhu1Ms4adTzOGnU8zhpVBh30Eb5cQ/fKp/5UR1+51l9mfU/Mz6NxvfMuEGMu9G49f/y8vzLz4Ikif/8qopnhiF6FhNHP9aVo2cGR71lCZAvbAXkzADE/kgQvooqhM8MCNuMCUFLtiJoZiBI5ycsvD4qFs4MLLTNElFYjJUoZAYRPAsSlV/5lcpnBhU8C6y+zPqfGZ9G43tm3CDG3Wjc+p9N/Z7PgjSN//y6jmfGMXoWU0c/1rWjZ0ZHvWUpkC9sDeTMCMT+SBG+imqEz4wI24wpQUu2JmhmJEjnpyy8PmoWzowstM1SUViMtShkRhE8C1KVX/m1ymdGFTwLrL7M+p8Zn0bje2bcIMbdaNz6n039ns+CLIv//Mslnpmm6FnMHP1YXxw9MznqLcuAfGEvQM5MQOyPDOGr6ILwmQlhmzEjaMleCJqZCNL5GQuvjwsLZyYW2maZKCzGiyhkJhE8CzKVX/kXlc9MKngWWH2Z9T8zPo3G98y4QYy70bj1P5v6PZ8Fx2P851+v8cw8R8/i0dGP9dXRM7Oj3rIjkC/sFciZGYj9cUT4KroifGZG2GY8ErRkrwTNzATp/CMLr48rC2dmFtpmR1FYjFdRyMwieBYcVX7lX1U+M6vgWWD1Zdb/zPg0Gt8z4wYx7kbj1v9s6vd8FpxO8Z/fNPHMskTP4snRj3Xj6JnFUW/ZCcgXtgFyZgFif5wQvooahM8sCNuMJ4KWbEPQzEKQzj+x8PpoWDizsNA2O4nCYmxEIbOI4FlwUvmV36h8ZlHBs8Dqy6z/mfFpNL5nxg1i3I3Grf/Z1O/5LDif4z//dotn1jV6Fs+Ofqxvjp5ZHfWWnYF8YW9AzqxA7I8zwlfRDeEzK8I245mgJXsjaGYlSOefWXh93Fg4s7LQNjuLwmK8iUJmFcGz4KzyK/+m8plVBc8Cqy+z/mfGp9H4nhk3iHE3Grf+Z1O/57Mgz+M/v23jmW2LnsXc0Y916+iZzVFvWQ7kC9sCObMBsT9yhK+iFuEzG8I2Y07Qkm0JmtkI0vk5C6+PloUzGwtts1wUFmMrCplNBM+CXOVXfqvymU0FzwKrL7P+Z8an0fieGTeIcTcat/5nU7/ns6Ao4j+/6+KZfY+excLRj3Xn6JndUW9ZAeQL2wE5swOxPwqEr6IO4TM7wjZjQdCS7Qia2QnS+QULr4+OhTM7C22zQhQWYycKmV0Ez4JC5Vd+p/KZXQXPAqsvs/5nxqfR+J4ZN4hxNxq3/mdTv+ezoCzjP7/v45n7PXoWS0c/1r2jZ+6OestKIF/YHsiZOxD7o0T4KuoRPnNH2GYsCVqyPUEzd4J0fsnC66Nn4cydhbZZKQqLsReFzF0Ez4JS5Vd+r/KZuwqeBVZfZv3PjE+j8T0zbhDjbjRu/b+0PP8DZwi9QurvbfwAAAAASUVORK5CYII=';
export const spritesheet = {
frames: {
'0': {
frame: { x: 1, y: 1, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'1': {
frame: { x: 37, y: 1, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'2': {
frame: { x: 73, y: 1, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'3': {
frame: { x: 1, y: 20, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'4': {
frame: { x: 37, y: 20, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'5': {
frame: { x: 73, y: 20, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'6': {
frame: { x: 1, y: 39, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'7': {
frame: { x: 37, y: 39, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'8': {
frame: { x: 73, y: 39, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'9': {
frame: { x: 1, y: 58, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'a': {
frame: { x: 37, y: 58, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'b': {
frame: { x: 73, y: 58, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'c': {
frame: { x: 1, y: 77, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'd': {
frame: { x: 37, y: 77, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'e': {
frame: { x: 73, y: 77, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'f': {
frame: { x: 1, y: 96, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'g': {
frame: { x: 37, y: 96, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'h': {
frame: { x: 73, y: 96, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'i': {
frame: { x: 1, y: 115, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'j': {
frame: { x: 37, y: 115, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'k': {
frame: { x: 73, y: 115, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'l': {
frame: { x: 1, y: 134, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'm': {
frame: { x: 37, y: 134, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'n': {
frame: { x: 73, y: 134, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'o': {
frame: { x: 1, y: 153, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'p': {
frame: { x: 37, y: 153, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'q': {
frame: { x: 73, y: 153, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'r_blocked': {
frame: { x: 1, y: 172, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'r_door': {
frame: { x: 37, y: 172, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
'x': {
frame: { x: 73, y: 172, w: 34, h: 17 },
rotated: false,
trimmed: false,
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 },
},
},
meta: {
app: 'https://www.codeandweb.com/texturepacker',
version: '1.0',
image: 'tiles.png',
format: 'RGBA8888',
size: { w: 108, h: 190 },
scale: '1',
smartupdate:
'$TexturePacker:SmartUpdate:6d0f8373580629749f786a0b0f6c6bb9:96dff9df69bdc6938cf02f254bbe028b:accbe1e7e294ded8391337fc1c446319$',
},
};

View File

@ -5,14 +5,14 @@ export const getScreenPositionForTile = (x: number, y: number): [number , number
let positionX = (x * TILE_SIZE / 2) - (y * TILE_SIZE / 2);
const positionY = (x * TILE_SIZE / 4) + (y * TILE_SIZE / 4);
positionX = positionX + 1024; // center the map in the canvas
positionX = positionX + 1600; // center the map in the canvas
return [ positionX, positionY ];
}
export const getTileFromScreenPosition = (x: number, y: number): [number, number] =>
{
const translatedX = x - 1024; // after centering translation
const translatedX = x - 1600; // after centering translation
const realX = ((translatedX /(TILE_SIZE / 2)) + (y / (TILE_SIZE / 4))) / 2;
const realY = ((y /(TILE_SIZE / 4)) - (translatedX / (TILE_SIZE / 2))) / 2;

View File

@ -4,8 +4,8 @@ import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp } from 'react-icons/f
import { SendMessageComposer } from '../../../api';
import { Base, Button, Column, ColumnProps, Flex, Grid } from '../../../common';
import { useMessageEvent } from '../../../hooks';
import { FloorplanEditor } from '../common/FloorplanEditor';
import { useFloorplanEditorContext } from '../FloorplanEditorContext';
import { FloorplanEditor } from '../common/FloorplanEditor';
export const FloorplanCanvasView: FC<ColumnProps> = props =>
{
@ -32,7 +32,7 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
setOccupiedTilesReceived(true);
elementRef.current.scrollTo((FloorplanEditor.instance.view.width / 3), 0);
elementRef.current.scrollTo((FloorplanEditor.instance.renderer.canvas.width / 3), 0);
});
useMessageEvent<RoomEntryTileMessageEvent>(RoomEntryTileMessageEvent, event =>
@ -86,6 +86,25 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
}
}
const onPointerEvent = (event: PointerEvent) =>
{
event.preventDefault();
switch(event.type)
{
case 'pointerout':
case 'pointerup':
FloorplanEditor.instance.onPointerRelease();
break;
case 'pointerdown':
FloorplanEditor.instance.onPointerDown(event);
break;
case 'pointermove':
FloorplanEditor.instance.onPointerMove(event);
break;
}
}
useEffect(() =>
{
return () =>
@ -116,22 +135,46 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
SendMessageComposer(new GetRoomEntryTileMessageComposer());
SendMessageComposer(new GetOccupiedTilesMessageComposer());
FloorplanEditor.instance.tilemapRenderer.interactive = true;
const currentElement = elementRef.current;
if(!elementRef.current) return;
if(!currentElement) return;
currentElement.appendChild(FloorplanEditor.instance.renderer.canvas);
elementRef.current.appendChild(FloorplanEditor.instance.renderer.view);
currentElement.addEventListener('pointerup', onPointerEvent);
currentElement.addEventListener('pointerout', onPointerEvent);
currentElement.addEventListener('pointerdown', onPointerEvent);
currentElement.addEventListener('pointermove', onPointerEvent);
return () =>
{
if(currentElement)
{
currentElement.removeEventListener('pointerup', onPointerEvent);
currentElement.removeEventListener('pointerout', onPointerEvent);
currentElement.removeEventListener('pointerdown', onPointerEvent);
currentElement.removeEventListener('pointermove', onPointerEvent);
}
}
}, []);
const isSmallScreen = () => window.innerWidth < 768;
return (
<Column gap={ gap } { ...rest }>
<Grid overflow="hidden" gap={ 1 }>
<Column center size={ 1 }>
<Column center size={ 1 } className="d-md-none">
<Button className="d-md-none" onClick={ event => onClickArrowButton('left') }>
<FaArrowLeft className="fa-icon" />
</Button>
</Column>
<Column overflow="hidden" size={ 10 } gap={ 1 }>
<Column overflow="hidden" size={ isSmallScreen() ? 10: 12 } gap={ 1 }>
<Flex justifyContent="center" className="d-md-none">
<Button shrink onClick={ event => onClickArrowButton('up') }>
<FaArrowUp className="fa-icon" />
@ -144,7 +187,7 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
</Button>
</Flex>
</Column>
<Column center size={ 1 }>
<Column center size={ 1 } className="d-md-none">
<Button className="d-md-none" onClick={ event => onClickArrowButton('right') }>
<FaArrowRight className="fa-icon" />
</Button>
@ -153,4 +196,4 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
{ children }
</Column>
);
}
}

View File

@ -52,4 +52,4 @@ export const FloorplanImportExportView: FC<FloorplanImportExportViewProps> = pro
</NitroCardContentView>
</NitroCardView>
);
}
}

View File

@ -1,8 +1,7 @@
import { FC, useState } from 'react';
import { FaCaretLeft, FaCaretRight } from 'react-icons/fa';
import ReactSlider from 'react-slider';
import { LocalizeText } from '../../../api';
import { Column, Flex, LayoutGridItem, Text } from '../../../common';
import { Column, Flex, LayoutGridItem, Slider, Text } from '../../../common';
import { COLORMAP, FloorAction } from '../common/Constants';
import { FloorplanEditor } from '../common/FloorplanEditor';
import { useFloorplanEditorContext } from '../FloorplanEditorContext';
@ -157,8 +156,7 @@ export const FloorplanOptionsView: FC<{}> = props =>
<Flex gap={ 1 }>
<Column size={ 6 }>
<Text bold>{ LocalizeText('floor.plan.editor.tile.height') }: { floorHeight }</Text>
<ReactSlider
className="nitro-slider"
<Slider
min={ MIN_FLOOR_HEIGHT }
max={ MAX_FLOOR_HEIGHT }
step={ 1 }
@ -186,4 +184,4 @@ export const FloorplanOptionsView: FC<{}> = props =>
</Flex>
</Column>
);
}
}

View File

@ -1,6 +1,6 @@
import { BaseTexture, Resource, Texture } from '@pixi/core';
import { Spritesheet } from '@pixi/spritesheet';
import { Dict } from '@pixi/utils';
import { Dict } from '../utils';
import { GetTickerTime } from '../../pixi-proxy';
import { GraphicAsset } from './GraphicAsset';
import { GraphicAssetPalette } from './GraphicAssetPalette';

View File

@ -87,6 +87,7 @@ export class SocketConnection extends EventDispatcher implements IConnection
this._dataBuffer = new ArrayBuffer(0);
this._socket = new WebSocket(socketUrl);
this._socket.binaryType = 'arraybuffer';
this._socket.addEventListener(WebSocketEventEnum.CONNECTION_OPENED, this.onOpen);
this._socket.addEventListener(WebSocketEventEnum.CONNECTION_CLOSED, this.onClose);
@ -104,6 +105,8 @@ export class SocketConnection extends EventDispatcher implements IConnection
this._socket.removeEventListener(WebSocketEventEnum.CONNECTION_MESSAGE, this.onMessage);
if(this._socket.readyState === WebSocket.OPEN) this._socket.close();
NitroLogger.error('Bye Bye connection.');
this._socket = null;
}
@ -129,16 +132,9 @@ export class SocketConnection extends EventDispatcher implements IConnection
//this.dispatchConnectionEvent(SocketConnectionEvent.CONNECTION_MESSAGE, event);
const reader = new FileReader();
this._dataBuffer = this.concatArrayBuffers(this._dataBuffer, event.data);
reader.readAsArrayBuffer(event.data);
reader.onloadend = () =>
{
this._dataBuffer = this.concatArrayBuffers(this._dataBuffer, (reader.result as ArrayBuffer));
this.processReceivedData();
};
this.processReceivedData();
}
private dispatchConnectionEvent(type: string, event: Event): void

View File

@ -2,7 +2,6 @@ import '@pixi/canvas-display';
import { BatchRenderer, extensions } from '@pixi/core';
import { Extract } from '@pixi/extract';
import '@pixi/graphics-extras';
import { InteractionManager } from '@pixi/interaction';
import { AppLoaderPlugin } from '@pixi/loaders';
import '@pixi/math-extras';
import '@pixi/mixin-cache-as-bitmap';
@ -17,7 +16,6 @@ extensions.add(
BatchRenderer,
Extract,
TilingSpriteRenderer,
InteractionManager,
SpritesheetLoader,
AppLoaderPlugin,
TickerPlugin);

View File

@ -1,6 +0,0 @@
import { Tilemap } from '@pixi/tilemap';
export class NitroTilemap extends Tilemap
{
}

View File

@ -1,4 +0,0 @@
import { InteractionEvent } from '@pixi/interaction';
export class PixiInteractionEventProxy extends InteractionEvent
{}

View File

@ -1,4 +1,3 @@
export { POINT_STRUCT_SIZE } from '@pixi/tilemap';
export * from './adjustment-filter';
export * from './CopyChannelFilter';
export * from './GetTicker';
@ -16,9 +15,7 @@ export * from './NitroRenderTexture';
export * from './NitroSprite';
export * from './NitroSpritesheet';
export * from './NitroTexture';
export * from './NitroTilemap';
export * from './PaletteMapFilter';
export * from './PixiApplicationProxy';
export * from './PixiInteractionEventProxy';
export * from './RoomTextureUtils';
export * from './TextureUtils';