🆙 Small fixes for the Area and Neighborhood Wired

This commit is contained in:
duckietm
2026-03-05 14:27:56 +01:00
parent a53d788daf
commit 927e8da62e
3 changed files with 105 additions and 13 deletions
@@ -1,4 +1,4 @@
import { GetRoomEngine, RoomAreaSelectionManager } from '@nitrots/nitro-renderer';
import { GetRoomEngine, RoomAreaSelectionManager, RoomObjectCategory } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText } from '../../../../api';
import { Button, Text } from '../../../../common';
@@ -11,13 +11,16 @@ export const WiredActionFurniAreaView: FC<{}> = props =>
const [ rootY, setRootY ] = useState(0);
const [ areaWidth, setAreaWidth ] = useState(0);
const [ areaHeight, setAreaHeight ] = useState(0);
const [ filterExisting, setFilterExisting ] = useState(false);
const [ invert, setInvert ] = useState(false);
const { trigger = null, setIntParams } = useWired();
const save = useCallback(() =>
{
setIntParams([ rootX, rootY, areaWidth, areaHeight ]);
}, [ rootX, rootY, areaWidth, areaHeight, setIntParams ]);
setIntParams([ rootX, rootY, areaWidth, areaHeight, filterExisting ? 1 : 0, invert ? 1 : 0 ]);
}, [ rootX, rootY, areaWidth, areaHeight, filterExisting, invert, setIntParams ]);
// Activate the area selection manager when dialog opens, deactivate on close
useEffect(() =>
{
if(!trigger) return;
@@ -34,6 +37,7 @@ export const WiredActionFurniAreaView: FC<{}> = props =>
if(activated)
{
// Restore previously saved area highlight when re-opening dialog
if(trigger.intData.length >= 4 && trigger.intData[2] > 0 && trigger.intData[3] > 0)
{
GetRoomEngine().areaSelectionManager.setHighlight(
@@ -69,19 +73,38 @@ export const WiredActionFurniAreaView: FC<{}> = props =>
setAreaWidth(0);
setAreaHeight(0);
}
setFilterExisting(trigger.intData.length >= 5 && trigger.intData[4] === 1);
setInvert(trigger.intData.length >= 6 && trigger.intData[5] === 1);
}, [ trigger ]);
const hasArea = areaWidth > 0 && areaHeight > 0;
const pickedLimit = trigger?.maximumItemSelectionCount ?? 20;
const pickedCount = hasArea
? GetRoomEngine().getRoomObjects(GetRoomEngine().activeRoomId, RoomObjectCategory.FLOOR)
.filter(obj =>
{
const loc = obj.location;
const inArea = loc.x >= rootX && loc.x < rootX + areaWidth && loc.y >= rootY && loc.y < rootY + areaHeight;
return invert ? !inArea : inArea;
}).length
: 0;
return (
<WiredActionBaseView hasSpecialInput={ true } requiresFurni={ 0 } save={ save } cardStyle={ { width: '385px', height: '365px' } }>
<WiredActionBaseView hasSpecialInput={ true } requiresFurni={ 0 } save={ save } hideDelay={ true } cardStyle={ { width: '385px'} }>
<div className="flex flex-col gap-2">
<Text bold>{ LocalizeText('wiredfurni.params.area_selection') }</Text>
<Text small>{ LocalizeText('wiredfurni.params.area_selection.info') }</Text>
{ hasArea &&
<Text small>
{ LocalizeText('wiredfurni.params.area_selection.selected', [ 'x', 'y', 'w', 'h' ], [ rootX.toString(), rootY.toString(), areaWidth.toString(), areaHeight.toString() ]) }
{ LocalizeText('wiredfurni.params.area_selection:', [ 'x', 'y', 'w', 'h' ], [ rootX.toString(), rootY.toString(), areaWidth.toString(), areaHeight.toString() ]) }
</Text> }
{ hasArea &&
<Text small>
{ LocalizeText('wiredfurni.pickfurnis.caption', [ 'count', 'limit' ], [ pickedCount.toString(), pickedLimit.toString() ]) }
</Text> }
<div className="flex gap-1">
@@ -92,6 +115,28 @@ export const WiredActionFurniAreaView: FC<{}> = props =>
{ LocalizeText('wiredfurni.params.area_selection.clear') }
</Button>
</div>
<hr className="m-0 bg-dark" />
<Text bold>{ LocalizeText('wiredfurni.params.selector_options_selector') }</Text>
<label className="flex items-center gap-1">
<input
type="checkbox"
className="form-check-input"
checked={ filterExisting }
onChange={ e => setFilterExisting(e.target.checked) } />
<Text small>{ LocalizeText('wiredfurni.params.selector_option.0') }</Text>
</label>
<label className="flex items-center gap-1">
<input
type="checkbox"
className="form-check-input"
checked={ invert }
onChange={ e => setInvert(e.target.checked) } />
<Text small>{ LocalizeText('wiredfurni.params.selector_option.1') }</Text>
</label>
</div>
</WiredActionBaseView>
);
@@ -1,7 +1,8 @@
import { GetRoomEngine, RoomObjectCategory } from '@nitrots/nitro-renderer';
import { CSSProperties, FC, useCallback, useEffect, useState } from 'react';
import { FaMinus, FaPlus, FaTimes } from 'react-icons/fa';
import { MdGridOn } from 'react-icons/md';
import { LocalizeText, WiredFurniType } from '../../../../api';
import { GetRoomSession, LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
import { Button, Text } from '../../../../common';
import { useWired } from '../../../../hooks';
import { WiredActionBaseView } from '../actions/WiredActionBaseView';
@@ -46,10 +47,11 @@ const tileTop = (rx: number, ry: number) =>
interface GridProps {
selectedTiles: Tile[];
invert: boolean;
onToggle: (x: number, y: number) => void;
}
const NeighborhoodGrid: FC<GridProps> = ({ selectedTiles, onToggle }) =>
const NeighborhoodGrid: FC<GridProps> = ({ selectedTiles, invert, onToggle }) =>
{
const tiles: JSX.Element[] = [];
@@ -59,19 +61,20 @@ const NeighborhoodGrid: FC<GridProps> = ({ selectedTiles, onToggle }) =>
{
const isCenter = rx === 0 && ry === 0;
const isSelected = tileIncluded(selectedTiles, rx, ry);
const isActive = invert ? !isSelected : isSelected;
const left = tileLeft(rx, ry);
const top_ = tileTop(rx, ry);
const zIdx = rx + ry + GRID_RANGE * 2 + 10;
const bgColor = isCenter
? '#ff9500'
: isSelected
: isActive
? '#3399ff'
: '#2a3042';
const borderColor = isCenter
? '#cc6600'
: isSelected
: isActive
? '#1166cc'
: '#1a2032';
@@ -127,7 +130,7 @@ export const WiredSelectorFurniNeighborhoodView: FC<{}> = () =>
const [ curX, setCurX ] = useState(0);
const [ curY, setCurY ] = useState(0);
const { trigger = null, furniIds = [], setIntParams } = useWired();
const { trigger = null, furniIds = [], setIntParams, setFurniIds } = useWired();
useEffect(() =>
{
@@ -157,6 +160,46 @@ export const WiredSelectorFurniNeighborhoodView: FC<{}> = () =>
}
}, [ trigger ]);
useEffect(() =>
{
if(sourceType !== SOURCE_FURNI_PICKED || !trigger) return;
const roomId = GetRoomSession().roomId;
const wiredObj = GetRoomEngine().getRoomObject(roomId, trigger.id, RoomObjectCategory.FLOOR);
if(!wiredObj) return;
const wiredPos = wiredObj.getLocation();
const tileSet = new Set(selectedTiles.map(t => `${ t.x },${ t.y }`));
const limit = trigger.maximumItemSelectionCount;
const allFloorObjects = GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.FLOOR);
const newIds: number[] = [];
for(const obj of allFloorObjects)
{
if(newIds.length >= limit) break;
if(obj.id < 0 || obj.id === trigger.id) continue;
const pos = obj.getLocation();
const relX = Math.round(pos.x - wiredPos.x);
const relY = Math.round(pos.y - wiredPos.y);
const isInTiles = tileSet.has(`${ relX },${ relY }`);
if(invert ? !isInTiles : isInTiles) newIds.push(obj.id);
}
setFurniIds(prevValue =>
{
if(prevValue && prevValue.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prevValue);
WiredSelectionVisualizer.applySelectionShaderToFurni(newIds);
return newIds;
});
}, [ sourceType, selectedTiles, invert, trigger, setFurniIds ]);
const save = useCallback(() =>
{
const params: number[] = [
@@ -235,7 +278,7 @@ export const WiredSelectorFurniNeighborhoodView: FC<{}> = () =>
const pickedLimit = trigger?.maximumItemSelectionCount ?? 20;
return (
<WiredActionBaseView hasSpecialInput={ true } requiresFurni={ requiresFurni } save={ save } cardStyle={ { width: '480px', height: '750px' } }>
<WiredActionBaseView hasSpecialInput={ true } requiresFurni={ requiresFurni } save={ save } hideDelay={ true } cardStyle={ { width: '400px' } }>
<div className="flex flex-col gap-2">
<Text bold>{ LocalizeText('wiredfurni.params.neighborhood_selection') }</Text>
@@ -256,7 +299,7 @@ export const WiredSelectorFurniNeighborhoodView: FC<{}> = () =>
</div>
<div className="flex justify-center">
<NeighborhoodGrid selectedTiles={ selectedTiles } onToggle={ toggleTile } />
<NeighborhoodGrid selectedTiles={ selectedTiles } invert={ invert } onToggle={ toggleTile } />
</div>
<div className="flex items-center gap-2">
+5 -1
View File
@@ -15,6 +15,8 @@ const useWiredState = () =>
const [ allowsFurni, setAllowsFurni ] = useState<number>(WiredFurniType.STUFF_SELECTION_OPTION_NONE);
const [ selectByType, setSelectByType ] = useState<boolean>(false);
const [ invertSelection, setInvertSelection ] = useState<boolean>(false);
const [ neighborhoodTiles, setNeighborhoodTiles ] = useState<{ x: number; y: number }[] | null>(null);
const [ neighborhoodInvert, setNeighborhoodInvert ] = useState<boolean>(false);
const { showConfirm = null } = useNotification();
const saveWired = () =>
@@ -206,10 +208,12 @@ const useWiredState = () =>
setAllowsFurni(WiredFurniType.STUFF_SELECTION_OPTION_NONE);
setSelectByType(false);
setInvertSelection(false);
setNeighborhoodTiles(null);
setNeighborhoodInvert(false);
};
}, [ trigger ]);
return { trigger, setTrigger, intParams, setIntParams, stringParam, setStringParam, furniIds, setFurniIds, actionDelay, setActionDelay, setAllowsFurni, saveWired, selectObjectForWired, setSelectByType, setInvertSelection };
return { trigger, setTrigger, intParams, setIntParams, stringParam, setStringParam, furniIds, setFurniIds, actionDelay, setActionDelay, setAllowsFurni, saveWired, selectObjectForWired, setSelectByType, setInvertSelection, setNeighborhoodTiles, setNeighborhoodInvert };
};
export const useWired = () => useBetween(useWiredState);