diff --git a/src/components/floorplan-editor/FloorplanEditorView.tsx b/src/components/floorplan-editor/FloorplanEditorView.tsx index 2ed3b02..f67d2aa 100644 --- a/src/components/floorplan-editor/FloorplanEditorView.tsx +++ b/src/components/floorplan-editor/FloorplanEditorView.tsx @@ -12,6 +12,9 @@ import { FloorplanCanvasView } from './views/FloorplanCanvasView'; import { FloorplanImportExportView } from './views/FloorplanImportExportView'; import { FloorplanOptionsView } from './views/FloorplanOptionsView'; + +type ScrollDirection = 'up' | 'down' | 'left' | 'right'; + export const FloorplanEditorView: FC<{}> = props => { const [ isVisible, setIsVisible ] = useState(false); @@ -31,6 +34,7 @@ export const FloorplanEditorView: FC<{}> = props => thicknessWall: 1, thicknessFloor: 1 }); + const [ canvasScrollHandler, setCanvasScrollHandler ] = useState<((direction: ScrollDirection) => void) | null>(null); const saveFloorChanges = () => { @@ -141,8 +145,8 @@ export const FloorplanEditorView: FC<{}> = props => setIsVisible(false) } /> - - + canvasScrollHandler && canvasScrollHandler(direction) } /> + diff --git a/src/components/floorplan-editor/common/ActionSettings.ts b/src/components/floorplan-editor/common/ActionSettings.ts deleted file mode 100644 index 8ac3825..0000000 --- a/src/components/floorplan-editor/common/ActionSettings.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { FloorAction, HEIGHT_SCHEME } from './Constants'; - -export class ActionSettings -{ - private _currentAction: number; - private _currentHeight: string; - - constructor() - { - this._currentAction = FloorAction.SET; - this._currentHeight = HEIGHT_SCHEME[1]; - } - - public get currentAction(): number - { - return this._currentAction; - } - - public set currentAction(value: number) - { - this._currentAction = value; - } - - public get currentHeight(): string - { - return this._currentHeight; - } - - public set currentHeight(value: string) - { - this._currentHeight = value; - } - - public clear(): void - { - this._currentAction = FloorAction.SET; - this._currentHeight = HEIGHT_SCHEME[1]; - } -} diff --git a/src/components/floorplan-editor/common/Constants.ts b/src/components/floorplan-editor/common/Constants.ts deleted file mode 100644 index da66d51..0000000 --- a/src/components/floorplan-editor/common/Constants.ts +++ /dev/null @@ -1,44 +0,0 @@ -export const TILE_SIZE = 32; -export const MAX_NUM_TILE_PER_AXIS = 64; - -export const HEIGHT_SCHEME: string = 'x0123456789abcdefghijklmnopq'; - -export class FloorAction -{ - public static readonly DOOR = 0; - public static readonly UP = 1; - public static readonly DOWN = 2; - public static readonly SET = 3; - public static readonly UNSET = 4; -} - -export const COLORMAP: object = { - 'x': '101010', - '0': '0065ff', - '1': '0091ff', - '2': '00bcff', - '3': '00e8ff', - '4': '00ffea', - '5': '00ffbf', - '6': '00ff93', - '7': '00ff68', - '8': '00ff3d', - '9': '19ff00', - 'a': '44ff00', - 'b': '70ff00', - 'c': '9bff00', - 'd': 'f2ff00', - 'e': 'ffe000', - 'f': 'ffb500', - 'g': 'ff8900', - 'h': 'ff5e00', - 'i': 'ff3200', - 'j': 'ff0700', - 'k': 'ff0023', - 'l': 'ff007a', - 'm': 'ff00a5', - 'n': 'ff00d1', - 'o': 'ff00fc', - 'p': 'd600ff', - 'q': 'aa00ff' -}; diff --git a/src/components/floorplan-editor/common/ConvertMapToString.ts b/src/components/floorplan-editor/common/ConvertMapToString.ts deleted file mode 100644 index 1579158..0000000 --- a/src/components/floorplan-editor/common/ConvertMapToString.ts +++ /dev/null @@ -1 +0,0 @@ -export const ConvertTileMapToString = (map: string) => map.replace(/\r\n|\r|\n/g, '\n').toLowerCase(); diff --git a/src/components/floorplan-editor/common/FloorplanEditor.ts b/src/components/floorplan-editor/common/FloorplanEditor.ts deleted file mode 100644 index a5e2d67..0000000 --- a/src/components/floorplan-editor/common/FloorplanEditor.ts +++ /dev/null @@ -1,442 +0,0 @@ -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'; - -export class FloorplanEditor { - private static _INSTANCE: FloorplanEditor = null; - - public static readonly TILE_BLOCKED = 'r_blocked'; - public static readonly TILE_DOOR = 'r_door'; - - private _tilemap: Tile[][]; - private _width: number; - private _height: number; - private _isPointerDown: boolean; - private _doorLocation: { x: number, y: number }; - private _lastUsedTile: { x: number, y: number }; - private _renderer: CanvasRenderingContext2D; - private _actionSettings: ActionSettings; - private _image: HTMLImageElement; - private _zoomLevel: number = 1.0; - private _squareSelectMode: boolean = false; - private _selectionStart: { x: number, y: number } | null = null; - private _selectionEnd: { x: number, y: number } | null = null; - - constructor() { - const width = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20; - const height = (TILE_SIZE * MAX_NUM_TILE_PER_AXIS) / 2 + 100; - - const canvas = document.createElement('canvas'); - canvas.height = height; - canvas.width = width; - canvas.style.touchAction = 'none'; - canvas.oncontextmenu = (e) => { e.preventDefault(); }; // Added from old code - - this._renderer = canvas.getContext('2d')!; - this._image = new Image(); - this._image.src = imageBase64; - - this._tilemap = []; - this._doorLocation = { x: 0, y: 0 }; - this._width = 0; - this._height = 0; - this._isPointerDown = false; - this._lastUsedTile = { x: -1, y: -1 }; - this._actionSettings = new ActionSettings(); - } - - public setSquareSelectMode(enabled: boolean): void { - this._squareSelectMode = enabled; - if (!enabled) { - this._selectionStart = null; - this._selectionEnd = null; - } - } - - public get squareSelectMode(): boolean { - return this._squareSelectMode; - } - - public onPointerRelease(): void { - this._isPointerDown = false; - if (this._squareSelectMode && this._selectionStart) { - this.finalizeSquareSelection(); - } - } - - public onPointerDown(event: PointerEvent): void { - if (this._squareSelectMode) { - event.preventDefault(); - const location = { x: event.offsetX / this._zoomLevel, y: event.offsetY / this._zoomLevel }; - const [tileX, tileY] = getTileFromScreenPosition(location.x, location.y); - const roundedX = Math.floor(tileX); - const roundedY = Math.floor(tileY); - this._selectionStart = { x: roundedX, y: roundedY }; - this._selectionEnd = { x: roundedX, y: roundedY }; - this._isPointerDown = true; - return; - } - if (event.button === 2) return; - const location = { x: event.offsetX / this._zoomLevel, y: event.offsetY / this._zoomLevel }; - this._isPointerDown = true; - this.tileHitDetection(location, true); - } - - public onPointerMove(event: PointerEvent): void { - if (!this._isPointerDown) return; - const location = { x: event.offsetX / this._zoomLevel, y: event.offsetY / this._zoomLevel }; - if (this._squareSelectMode && this._selectionStart) { - const [tileX, tileY] = getTileFromScreenPosition(location.x, location.y); - this._selectionEnd!.x = Math.floor(tileX); - this._selectionEnd!.y = Math.floor(tileY); - this.renderTiles(); - return; - } - this.tileHitDetection(location, false); - } - - private tileHitDetection(tempPoint: { x: number, y: number }, isClick: boolean = false): boolean { - const mousePositionX = Math.floor(tempPoint.x); - const mousePositionY = Math.floor(tempPoint.y); - const width = TILE_SIZE; - const height = TILE_SIZE / 2; - for (let y = 0; y < this._tilemap.length; y++) { - for (let x = 0; x < this._tilemap[y].length; x++) { - 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); - if (solution) { - if (this._isPointerDown) { - if (isClick) { - this.onClick(x, y); - } 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 false; - } - - private onClick(x: number, y: number, render: boolean = true, force: boolean = false): void { // Updated from old code - const tile = this._tilemap[y][x]; - let currentHeightIndex = (tile.height === 'x' && force) ? 0 : HEIGHT_SCHEME.indexOf(tile.height); - let futureHeightIndex = 0; - switch (this._actionSettings.currentAction) { - case FloorAction.DOOR: - if (!force && tile.height !== 'x') { - this._doorLocation.x = x; - this._doorLocation.y = y; - if (render) this.renderTiles(); - } - return; - case FloorAction.UP: - if (!force && tile.height === 'x') return; - futureHeightIndex = currentHeightIndex + 1; - break; - case FloorAction.DOWN: - if (!force && (tile.height === 'x' || (currentHeightIndex <= 1))) return; - futureHeightIndex = currentHeightIndex - 1; - break; - case FloorAction.SET: - futureHeightIndex = HEIGHT_SCHEME.indexOf(this._actionSettings.currentHeight); - break; - case FloorAction.UNSET: - futureHeightIndex = 0; - break; - } - if (futureHeightIndex === -1) return; - if (currentHeightIndex === futureHeightIndex) return; - if (!force && futureHeightIndex > 0) { - if ((x + 1) > this._width) this._width = x + 1; - if ((y + 1) > this._height) this._height = y + 1; - } - const newHeight = HEIGHT_SCHEME[futureHeightIndex]; - if (!newHeight) return; - this._tilemap[y][x].height = newHeight; - if (render) this.renderTiles(); - } - - public renderTiles(): void { - this.clearCanvas(); - this._renderer.save(); - this._renderer.scale(this._zoomLevel, this._zoomLevel); - - for (let y = 0; y < this._tilemap.length; y++) { - for (let x = 0; x < this._tilemap[y].length; x++) { - const tile = this._tilemap[y][x]; - let assetName = tile.height; - if (this._doorLocation.x === x && this._doorLocation.y === y) - assetName = FloorplanEditor.TILE_DOOR; - if (tile.isBlocked) assetName = FloorplanEditor.TILE_BLOCKED; - if ((tile.height === 'x' || tile.height === 'X') && tile.isBlocked) assetName = 'x'; - const [positionX, positionY] = getScreenPositionForTile(x, y); - const asset = spritesheet.frames[assetName]; - if (asset === undefined) { - console.warn(`Asset "${assetName}" not found in spritesheet.`); - continue; - } - 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 (this._squareSelectMode && this._isPointerDown && this._selectionStart && this._selectionEnd) { - const selMinX = Math.min(this._selectionStart.x, this._selectionEnd.x); - const selMaxX = Math.max(this._selectionStart.x, this._selectionEnd.x); - const selMinY = Math.min(this._selectionStart.y, this._selectionEnd.y); - const selMaxY = Math.max(this._selectionStart.y, this._selectionEnd.y); - if (x >= selMinX && x <= selMaxX && y >= selMinY && y <= selMaxY) { - this._renderer.fillStyle = 'rgba(0, 255, 0, 0.3)'; - this._renderer.fillRect(positionX, positionY, asset.frame.w, asset.frame.h); - continue; - } - } - - if (tile.selected) { - this._renderer.fillStyle = tile.isBlocked ? 'rgb(128, 0, 128)' : 'rgba(0, 0, 255, 0.3)'; - this._renderer.fillRect(positionX, positionY, asset.frame.w, asset.frame.h); - } - } - } - this._renderer.restore(); - } - - public toggleSelectAll(): void { // Added from old code - for (let y = 0; y < this._tilemap.length; y++) { - for (let x = 0; x < this._tilemap[y].length; x++) { - this._tilemap[y][x].selected = true; - if (this._actionSettings.currentAction !== FloorAction.DOOR) { - const tile = this._tilemap[y][x]; - let currentHeightIndex = tile.height === 'x' ? 0 : HEIGHT_SCHEME.indexOf(tile.height); - let futureHeightIndex = 0; - switch (this._actionSettings.currentAction) { - case FloorAction.UP: - if (tile.height === 'x') continue; - futureHeightIndex = currentHeightIndex + 1; - break; - case FloorAction.DOWN: - if (tile.height === 'x' || currentHeightIndex <= 1) continue; - futureHeightIndex = currentHeightIndex - 1; - break; - case FloorAction.SET: - futureHeightIndex = HEIGHT_SCHEME.indexOf(this._actionSettings.currentHeight); - break; - case FloorAction.UNSET: - futureHeightIndex = 0; - break; - default: - continue; - } - if (futureHeightIndex !== -1 && currentHeightIndex !== futureHeightIndex) { - const newHeight = HEIGHT_SCHEME[futureHeightIndex]; - if (newHeight) { - this._tilemap[y][x].height = newHeight; - if ((x + 1) > this._width) this._width = x + 1; - if ((y + 1) > this._height) this._height = y + 1; - } - } - } - } - } - this.recalcActiveArea(); - this.renderTiles(); - } - - private finalizeSquareSelection(): void { // Updated from old code - const startX = Math.floor(this._selectionStart!.x); - const startY = Math.floor(this._selectionStart!.y); - const endX = Math.floor(this._selectionEnd!.x); - const endY = Math.floor(this._selectionEnd!.y); - const minX = Math.min(startX, endX); - const maxX = Math.max(startX, endX); - const minY = Math.min(startY, endY); - const maxY = Math.max(startY, endY); - this.selectSquareField(minX, minY, maxX, maxY); - this._selectionStart = null; - this._selectionEnd = null; - this.renderTiles(); - } - - private selectSquareField(x1: number, y1: number, x2: number, y2: number): void { // Added from old code - for (let y = y1; y <= y2; y++) { - for (let x = x1; x <= x2; x++) { - if (this._tilemap[y] && this._tilemap[y][x]) { - this._tilemap[y][x].selected = true; - this.onClick(x, y, false, true); - } - } - } - this.recalcActiveArea(); - this.renderTiles(); - } - - private recalcActiveArea(): void { // Added from old code - 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; - } - } - } - } - - public setTilemap(map: string, blockedTiles: boolean[][]): void { - this._tilemap = []; - const roomMapStringSplit = map.split('\r'); - let width = 0; - let height = roomMapStringSplit.length; - for (let y = 0; y < height; y++) { - const originalRow = roomMapStringSplit[y]; - if (originalRow.length === 0) { - roomMapStringSplit.splice(y, 1); - height = roomMapStringSplit.length; - y--; - continue; - } - if (originalRow.length > width) { - width = originalRow.length; - } - } - for (let y = 0; y < height; y++) { - this._tilemap[y] = []; - const rowString = roomMapStringSplit[y]; - for (let x = 0; x < width; x++) { - const blocked = (blockedTiles[y] && blockedTiles[y][x]) || false; - const char = rowString[x]; - if ((!(char === 'x')) && (!(char === 'X')) && char) { - this._tilemap[y][x] = new Tile(char, blocked); - } else { - this._tilemap[y][x] = new Tile('x', blocked); - } - } - for (let x = width; x < MAX_NUM_TILE_PER_AXIS; x++) { - this._tilemap[y][x] = new Tile('x', false); - } - } - for (let y = height; y < MAX_NUM_TILE_PER_AXIS; y++) { - if (!this._tilemap[y]) this._tilemap[y] = []; - for (let x = 0; x < MAX_NUM_TILE_PER_AXIS; x++) { - this._tilemap[y][x] = new Tile('x', false); - } - } - this._width = width; - this._height = height; - } - - public getCurrentTilemapString(): string { - const highestTile = this._tilemap[this._height - 1][this._width - 1]; - if (highestTile.height === 'x') { - this._width = -1; - this._height = -1; - for (let y = MAX_NUM_TILE_PER_AXIS - 1; y >= 0; y--) { - if (!this._tilemap[y]) continue; - for (let x = MAX_NUM_TILE_PER_AXIS - 1; x >= 0; x--) { - if (!this._tilemap[y][x]) continue; - const tile = this._tilemap[y][x]; - if (tile.height !== 'x') { - if ((x + 1) > this._width) - this._width = x + 1; - if ((y + 1) > this._height) - this._height = y + 1; - } - } - } - } - const rows = []; - for (let y = 0; y < this._height; y++) { - const row = []; - for (let x = 0; x < this._width; x++) { - const tile = this._tilemap[y][x]; - row[x] = tile.height; - } - rows[y] = row.join(''); - } - return rows.join('\r'); - } - - public clear(): void { - this._tilemap = []; - this._doorLocation = { x: -1, y: -1 }; // Updated from old code (no .set method) - this._width = 0; - this._height = 0; - this._isPointerDown = false; - this._lastUsedTile = { x: -1, y: -1 }; // Updated from old code (no .set method) - this._actionSettings.clear(); - this.clearCanvas(); - } - - public clearCanvas(): void { - this._renderer.fillStyle = '#000000'; - this._renderer.fillRect(0, 0, this._renderer.canvas.width, this._renderer.canvas.height); - } - - public zoomIn(): void { // Added from old code - this._zoomLevel = Math.min(this._zoomLevel + 0.1, 2.0); - this.adjustCanvasSize(); - this.renderTiles(); - } - - public zoomOut(): void { // Added from old code - this._zoomLevel = Math.max(this._zoomLevel - 0.1, 0.5); - this.adjustCanvasSize(); - this.renderTiles(); - } - - private adjustCanvasSize(): void { // Added from old code - const baseWidth = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20; - const baseHeight = (TILE_SIZE * MAX_NUM_TILE_PER_AXIS) / 2 + 100; - this._renderer.canvas.width = baseWidth * this._zoomLevel; - this._renderer.canvas.height = baseHeight * this._zoomLevel; - } - - public get zoomLevel(): number { // Added from old code - return this._zoomLevel; - } - - public get renderer(): CanvasRenderingContext2D { - return this._renderer; - } - - public get tilemap(): Tile[][] { - return this._tilemap; - } - - public get doorLocation(): { x: number, y: number } { - return this._doorLocation; - } - - public set doorLocation(value: { x: number, y: number }) { - this._doorLocation = value; - } - - public get actionSettings(): ActionSettings { - return this._actionSettings; - } - - public static get instance(): FloorplanEditor { - if (!FloorplanEditor._INSTANCE) { - FloorplanEditor._INSTANCE = new FloorplanEditor(); - } - return FloorplanEditor._INSTANCE; - } -} \ No newline at end of file diff --git a/src/components/floorplan-editor/common/FloorplanResource.ts b/src/components/floorplan-editor/common/FloorplanResource.ts deleted file mode 100644 index 5d5f2b8..0000000 --- a/src/components/floorplan-editor/common/FloorplanResource.ts +++ /dev/null @@ -1,217 +0,0 @@ -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 }, - }, - } -}; diff --git a/src/components/floorplan-editor/common/IFloorplanSettings.ts b/src/components/floorplan-editor/common/IFloorplanSettings.ts deleted file mode 100644 index 5159527..0000000 --- a/src/components/floorplan-editor/common/IFloorplanSettings.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { IVisualizationSettings } from './IVisualizationSettings'; - -export interface IFloorplanSettings extends IVisualizationSettings -{ - tilemap: string; - reservedTiles: boolean[][]; - entryPoint: [ number, number ]; -} diff --git a/src/components/floorplan-editor/common/IVisualizationSettings.ts b/src/components/floorplan-editor/common/IVisualizationSettings.ts deleted file mode 100644 index 97d271c..0000000 --- a/src/components/floorplan-editor/common/IVisualizationSettings.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface IVisualizationSettings -{ - entryPointDir: number; - wallHeight: number; - thicknessWall: number; - thicknessFloor: number; -} diff --git a/src/components/floorplan-editor/common/Tile.ts b/src/components/floorplan-editor/common/Tile.ts deleted file mode 100644 index fd9c059..0000000 --- a/src/components/floorplan-editor/common/Tile.ts +++ /dev/null @@ -1,31 +0,0 @@ -export class Tile -{ - private _height: string; - private _isBlocked: boolean; - - constructor(height: string, isBlocked: boolean) - { - this._height = height; - this._isBlocked = isBlocked; - } - - public get height(): string - { - return this._height; - } - - public set height(height: string) - { - this._height = height; - } - - public get isBlocked(): boolean - { - return this._isBlocked; - } - - public set isBlocked(val: boolean) - { - this._isBlocked = val; - } -} diff --git a/src/components/floorplan-editor/common/Utils.ts b/src/components/floorplan-editor/common/Utils.ts deleted file mode 100644 index dcce8ea..0000000 --- a/src/components/floorplan-editor/common/Utils.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { TILE_SIZE } from './Constants'; - -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 - - return [ positionX, positionY ]; -}; - -export const getTileFromScreenPosition = (x: number, y: number): [number, number] => -{ - const translatedX = x - 1024; // 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; - - return [ realX, realY ]; -}; - -export const convertNumbersForSaving = (value: number): number => -{ - value = parseInt(value.toString()); - switch(value) - { - case 0: - return -2; - case 1: - return -1; - case 3: - return 1; - default: - return 0; - - } -}; - -export const convertSettingToNumber = (value: number): number => -{ - switch(value) - { - case 0.25: - return 0; - case 0.5: - return 1; - case 2: - return 3; - default: - return 2; - } -}; diff --git a/src/components/floorplan-editor/views/FloorplanCanvasView.tsx b/src/components/floorplan-editor/views/FloorplanCanvasView.tsx index f13b873..e8f39a8 100644 --- a/src/components/floorplan-editor/views/FloorplanCanvasView.tsx +++ b/src/components/floorplan-editor/views/FloorplanCanvasView.tsx @@ -1,15 +1,21 @@ import { GetOccupiedTilesMessageComposer, GetRoomEntryTileMessageComposer, RoomEntryTileMessageEvent, RoomOccupiedTilesMessageEvent } from '@nitrots/nitro-renderer'; import { FC, useEffect, useRef, useState } from 'react'; -import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp } from 'react-icons/fa'; import { SendMessageComposer } from '../../../api'; -import { Base, Button, Column, ColumnProps, Flex, Grid } from '../../../common'; +import { Base, Column, ColumnProps } from '../../../common'; import { useMessageEvent } from '../../../hooks'; import { useFloorplanEditorContext } from '../FloorplanEditorContext'; import { FloorplanEditor } from '@nitrots/nitro-renderer'; -export const FloorplanCanvasView: FC = props => +type ScrollDirection = 'up' | 'down' | 'left' | 'right'; + +interface FloorplanCanvasViewProps extends ColumnProps { - const { gap = 1, children = null, ...rest } = props; + setScrollHandler(handler: ((direction: ScrollDirection) => void) | null): void; +} + +export const FloorplanCanvasView: FC = props => +{ + const { gap = 1, children = null, setScrollHandler = null, ...rest } = props; const [ occupiedTilesReceived , setOccupiedTilesReceived ] = useState(false); const [ entryTileReceived, setEntryTileReceived ] = useState(false); const { originalFloorplanSettings = null, setOriginalFloorplanSettings = null, setVisualizationSettings = null } = useFloorplanEditorContext(); @@ -63,7 +69,7 @@ export const FloorplanCanvasView: FC = props => setEntryTileReceived(true); }); - const onClickArrowButton = (scrollDirection: string) => + const onClickArrowButton = (scrollDirection: ScrollDirection) => { const element = elementRef.current; @@ -164,35 +170,18 @@ export const FloorplanCanvasView: FC = props => } }, []); - const isSmallScreen = () => window.innerWidth < 768; + useEffect(() => + { + if(!setScrollHandler) return; + + setScrollHandler(() => onClickArrowButton); + + return () => setScrollHandler(null); + }, [ setScrollHandler ]); return ( - - - - - - - - - - - - - - - - - + { children } ); diff --git a/src/components/floorplan-editor/views/FloorplanOptionsView.tsx b/src/components/floorplan-editor/views/FloorplanOptionsView.tsx index 39e664f..4123410 100644 --- a/src/components/floorplan-editor/views/FloorplanOptionsView.tsx +++ b/src/components/floorplan-editor/views/FloorplanOptionsView.tsx @@ -1,8 +1,8 @@ import { FC, useState } from 'react'; -import { FaCaretLeft, FaCaretRight } from 'react-icons/fa'; +import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaCaretLeft, FaCaretRight } from 'react-icons/fa'; import ReactSlider from 'react-slider'; import { LocalizeText } from '../../../api'; -import { Column, Flex, LayoutGridItem, Text } from '../../../common'; +import { Button, Column, Flex, LayoutGridItem, Text } from '../../../common'; import { COLORMAP, FloorAction } from '@nitrots/nitro-renderer'; import { FloorplanEditor } from '@nitrots/nitro-renderer'; import { useFloorplanEditorContext } from '../FloorplanEditorContext'; @@ -13,8 +13,16 @@ const MAX_WALL_HEIGHT: number = 16; const MIN_FLOOR_HEIGHT: number = 0; const MAX_FLOOR_HEIGHT: number = 26; -export const FloorplanOptionsView: FC<{}> = props => +type ScrollDirection = 'up' | 'down' | 'left' | 'right'; + +interface FloorplanOptionsViewProps { + onCanvasScroll?(direction: ScrollDirection): void; +} + +export const FloorplanOptionsView: FC = props => +{ + const { onCanvasScroll = () => {} } = props; const { visualizationSettings = null, setVisualizationSettings = null } = useFloorplanEditorContext(); const [ floorAction, setFloorAction ] = useState(FloorAction.SET); const [ floorHeight, setFloorHeight ] = useState(0); @@ -27,7 +35,6 @@ export const FloorplanOptionsView: FC<{}> = props => FloorplanEditor.instance.actionSettings.currentAction = action; } - const toggleSquareSelectMode = () => { const nextValue = FloorplanEditor.instance.toggleSquareSelectMode(); @@ -168,24 +175,6 @@ export const FloorplanOptionsView: FC<{}> = props => - - - - { LocalizeText('floor.plan.editor.tile.height') }: { floorHeight } - onFloorHeightChange(event) } - renderThumb={ (props, state) => - { - const { key, style, ...rest } = (props as Record); - - return
{ state.valueNow }
; - } } /> -
{ LocalizeText('floor.plan.editor.room.options') } @@ -204,6 +193,47 @@ export const FloorplanOptionsView: FC<{}> = props =>
+ + + { LocalizeText('floor.plan.editor.tile.height') }: { floorHeight } +
+ onFloorHeightChange(event) } + renderThumb={ (props, state) => + { + const { key, style, ...rest } = (props as Record); + + return
{ state.valueNow }
; + } } /> +
+
+ + + + + + +
+ + + + + + + ); -} +} \ No newline at end of file diff --git a/src/css/index.css b/src/css/index.css index c358863..e44cbcd 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -335,61 +335,6 @@ body { } } -.nitro-slider { - display: flex; - align-items: center; - width: 100%; - height: 25px; - - .track { - height: 3px; - border-radius: .25rem; - overflow: hidden; - - &.track-0 { - background-color: #1e7295; - } - - &.track-1 { - background-color: #b6bec5; - } - } - - .thumb { - border-radius: 50%; - width: 25px; - height: 25px; - background-color: gray; - font-size: 10px; - text-align: center; - line-height: 25px; - padding: 0 3px; - - &:hover, - .active { - cursor: pointer; - } - - &.active { - outline: none; - } - - &.degree { - - &:after { - content: '\00b0' - } - } - - &.percent { - - &:after { - content: '\0025' - } - } - } -} - .layout-grid-item { height: var(--nitro-grid-column-min-height, unset); background-position: center; diff --git a/src/css/slider.css b/src/css/slider.css index 199c30e..528dbb0 100644 --- a/src/css/slider.css +++ b/src/css/slider.css @@ -6,15 +6,15 @@ .track { height: 3px; - border-radius: $border-radius; + border-radius: .25rem; overflow: hidden; &.track-0 { - background-color: $primary; + background-color: #1e7295; } &.track-1 { - background-color: $muted; + background-color: #b6bec5; } } @@ -51,4 +51,4 @@ } } } -} +} \ No newline at end of file