🍺 Release of the FloorEditor

- Zoom in / out
- A button for full grid select / deselect
- Drag to select tiles or deselect tiles
This commit is contained in:
duckietm 2025-03-07 10:27:29 +01:00
parent 680eb4dd88
commit 6144d2c3b8
7 changed files with 68 additions and 30 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -689,6 +689,24 @@
height: 40px; height: 40px;
} }
&.icon-set-deselect {
background-image: url('@/assets/images/floorplaneditor/icon-deselect.png');
width: 40px;
height: 40px;
}
&.icon-set-squaresselect {
background-image: url('@/assets/images/floorplaneditor/icon-squaresselect.png');
width: 40px;
height: 40px;
}
&.icon-set-active-squaresselect {
background-image: url('@/assets/images/floorplaneditor/icon-squaresselect.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,6 +1,6 @@
import { GetOccupiedTilesMessageComposer, GetRoomEntryTileMessageComposer, NitroPoint, RoomEntryTileMessageEvent, RoomOccupiedTilesMessageEvent } from '@nitrots/nitro-renderer'; import { GetOccupiedTilesMessageComposer, GetRoomEntryTileMessageComposer, NitroPoint, RoomEntryTileMessageEvent, RoomOccupiedTilesMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useEffect, useRef, useState } from 'react'; import { FC, useEffect, useRef, useState } from 'react';
import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaSearchPlus, FaSearchMinus } from 'react-icons/fa'; // Added FaSearchPlus and FaSearchMinus for zoom icons import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaDotCircle, FaSearchPlus, FaSearchMinus, FaUndo } from 'react-icons/fa';
import { SendMessageComposer } from '../../../api'; import { SendMessageComposer } from '../../../api';
import { Base, Button, Column, ColumnProps, Flex, Grid } from '../../../common'; import { Base, Button, Column, ColumnProps, Flex, Grid } from '../../../common';
import { useMessageEvent } from '../../../hooks'; import { useMessageEvent } from '../../../hooks';
@ -113,6 +113,13 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
FloorplanEditor.instance.zoomOut(); FloorplanEditor.instance.zoomOut();
}; };
// Handler for resetting zoom to original level (1.0)
const handleResetZoom = () => {
FloorplanEditor.instance._zoomLevel = 1.0; // Reset to default zoom
FloorplanEditor.instance.adjustCanvasSize();
FloorplanEditor.instance.renderTiles();
};
useEffect(() => useEffect(() =>
{ {
return () => return () =>
@ -187,6 +194,9 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
<Button shrink onClick={ handleZoomIn }> <Button shrink onClick={ handleZoomIn }>
<FaSearchPlus className="fa-icon" /> <FaSearchPlus className="fa-icon" />
</Button> </Button>
<Button shrink onClick={ handleResetZoom }>
<FaDotCircle className="fa-icon" />
</Button>
<Button shrink onClick={ handleZoomOut }> <Button shrink onClick={ handleZoomOut }>
<FaSearchMinus className="fa-icon" /> <FaSearchMinus className="fa-icon" />
</Button> </Button>

View File

@ -1,4 +1,4 @@
import { FC, useState } from 'react'; import { FC, useState, useEffect } from 'react';
import { FaCaretLeft, FaCaretRight } from 'react-icons/fa'; import { FaCaretLeft, FaCaretRight } from 'react-icons/fa';
import { LocalizeText } from '../../../api'; import { LocalizeText } from '../../../api';
import { Column, Flex, LayoutGridItem, Slider, Text } from '../../../common'; import { Column, Flex, LayoutGridItem, Slider, Text } from '../../../common';
@ -17,14 +17,26 @@ export const FloorplanOptionsView: FC<{}> = props =>
const { visualizationSettings = null, setVisualizationSettings = null } = useFloorplanEditorContext(); const { visualizationSettings = null, setVisualizationSettings = null } = useFloorplanEditorContext();
const [ floorAction, setFloorAction ] = useState(FloorAction.SET); const [ floorAction, setFloorAction ] = useState(FloorAction.SET);
const [ floorHeight, setFloorHeight ] = useState(0); const [ floorHeight, setFloorHeight ] = useState(0);
const [ isSquareSelectMode, setIsSquareSelectMode ] = useState(FloorplanEditor.instance.squareSelectMode);
useEffect(() =>
{
setIsSquareSelectMode(FloorplanEditor.instance.squareSelectMode);
}, []);
const selectAction = (action: number) => const selectAction = (action: number) =>
{ {
setFloorAction(action); setFloorAction(action);
FloorplanEditor.instance.actionSettings.currentAction = action; FloorplanEditor.instance.actionSettings.currentAction = action;
} }
const toggleSquareSelectMode = () =>
{
const newMode = !FloorplanEditor.instance.squareSelectMode;
FloorplanEditor.instance.setSquareSelectMode(newMode);
setIsSquareSelectMode(newMode);
}
const changeDoorDirection = () => const changeDoorDirection = () =>
{ {
setVisualizationSettings(prevValue => setVisualizationSettings(prevValue =>
@ -47,11 +59,8 @@ export const FloorplanOptionsView: FC<{}> = props =>
const onFloorHeightChange = (value: number) => const onFloorHeightChange = (value: number) =>
{ {
if(isNaN(value) || (value <= 0)) value = 0; if(isNaN(value) || (value <= 0)) value = 0;
if(value > 26) value = 26; if(value > 26) value = 26;
setFloorHeight(value); setFloorHeight(value);
FloorplanEditor.instance.actionSettings.currentHeight = value.toString(36); FloorplanEditor.instance.actionSettings.currentHeight = value.toString(36);
} }
@ -60,9 +69,7 @@ export const FloorplanOptionsView: FC<{}> = props =>
setVisualizationSettings(prevValue => setVisualizationSettings(prevValue =>
{ {
const newValue = { ...prevValue }; const newValue = { ...prevValue };
newValue.thicknessFloor = value; newValue.thicknessFloor = value;
return newValue; return newValue;
}); });
} }
@ -72,9 +79,7 @@ export const FloorplanOptionsView: FC<{}> = props =>
setVisualizationSettings(prevValue => setVisualizationSettings(prevValue =>
{ {
const newValue = { ...prevValue }; const newValue = { ...prevValue };
newValue.thicknessWall = value; newValue.thicknessWall = value;
return newValue; return newValue;
}); });
} }
@ -82,15 +87,11 @@ export const FloorplanOptionsView: FC<{}> = props =>
const onWallHeightChange = (value: number) => const onWallHeightChange = (value: number) =>
{ {
if(isNaN(value) || (value <= 0)) value = MIN_WALL_HEIGHT; if(isNaN(value) || (value <= 0)) value = MIN_WALL_HEIGHT;
if(value > MAX_WALL_HEIGHT) value = MAX_WALL_HEIGHT; if(value > MAX_WALL_HEIGHT) value = MAX_WALL_HEIGHT;
setVisualizationSettings(prevValue => setVisualizationSettings(prevValue =>
{ {
const newValue = { ...prevValue }; const newValue = { ...prevValue };
newValue.wallHeight = value; newValue.wallHeight = value;
return newValue; return newValue;
}); });
} }
@ -98,18 +99,14 @@ export const FloorplanOptionsView: FC<{}> = props =>
const increaseWallHeight = () => const increaseWallHeight = () =>
{ {
let height = (visualizationSettings.wallHeight + 1); let height = (visualizationSettings.wallHeight + 1);
if(height > MAX_WALL_HEIGHT) height = MAX_WALL_HEIGHT; if(height > MAX_WALL_HEIGHT) height = MAX_WALL_HEIGHT;
onWallHeightChange(height); onWallHeightChange(height);
} }
const decreaseWallHeight = () => const decreaseWallHeight = () =>
{ {
let height = (visualizationSettings.wallHeight - 1); let height = (visualizationSettings.wallHeight - 1);
if(height <= 0) height = MIN_WALL_HEIGHT; if(height <= 0) height = MIN_WALL_HEIGHT;
onWallHeightChange(height); onWallHeightChange(height);
} }
@ -138,9 +135,13 @@ export const FloorplanOptionsView: FC<{}> = props =>
<i className="icon icon-set-door" /> <i className="icon icon-set-door" />
</LayoutGridItem> </LayoutGridItem>
<LayoutGridItem onClick={ event => FloorplanEditor.instance.toggleSelectAll() }> <LayoutGridItem onClick={ event => FloorplanEditor.instance.toggleSelectAll() }>
<i className="icon icon-set-select" /> <i className={`icon ${floorAction === FloorAction.UNSET ? 'icon-set-deselect' : 'icon-set-select'}`} />
</LayoutGridItem> </LayoutGridItem>
<LayoutGridItem itemActive={ FloorplanEditor.instance.squareSelectMode } onClick={ event => { FloorplanEditor.instance.setSquareSelectMode(!FloorplanEditor.instance.squareSelectMode);} }><i className="icon icon-set-select" /> <LayoutGridItem
itemActive={ isSquareSelectMode }
onClick={ toggleSquareSelectMode }
>
<i className={`icon ${isSquareSelectMode ? 'icon-set-active-squaresselect' : 'icon-set-squaresselect'}`} />
</LayoutGridItem> </LayoutGridItem>
</Flex> </Flex>
</Flex> </Flex>
@ -167,7 +168,16 @@ export const FloorplanOptionsView: FC<{}> = props =>
step={ 1 } step={ 1 }
value={ floorHeight } value={ floorHeight }
onChange={ event => onFloorHeightChange(event) } onChange={ event => onFloorHeightChange(event) }
renderThumb={ ({ style, ...rest }, state) => <div style={ { backgroundColor: `#${ COLORMAP[state.valueNow.toString(33)] }`, ...style } } { ...rest }>{ state.valueNow }</div> } /> renderThumb={ ({ style, key, ...rest }, state) => (
<div
key={key}
style={{ backgroundColor: `#${COLORMAP[state.valueNow.toString(33)]}`, ...style }}
{...rest}
>
{state.valueNow}
</div>
)}
/>
</Column> </Column>
<Column size={ 6 }> <Column size={ 6 }>
<Text bold>{ LocalizeText('floor.plan.editor.room.options') }</Text> <Text bold>{ LocalizeText('floor.plan.editor.room.options') }</Text>