mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 15:36:18 +00:00
🆙 Small fixes for the Area and Neighborhood Wired
This commit is contained in:
@@ -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 { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { LocalizeText } from '../../../../api';
|
import { LocalizeText } from '../../../../api';
|
||||||
import { Button, Text } from '../../../../common';
|
import { Button, Text } from '../../../../common';
|
||||||
@@ -11,13 +11,16 @@ export const WiredActionFurniAreaView: FC<{}> = props =>
|
|||||||
const [ rootY, setRootY ] = useState(0);
|
const [ rootY, setRootY ] = useState(0);
|
||||||
const [ areaWidth, setAreaWidth ] = useState(0);
|
const [ areaWidth, setAreaWidth ] = useState(0);
|
||||||
const [ areaHeight, setAreaHeight ] = useState(0);
|
const [ areaHeight, setAreaHeight ] = useState(0);
|
||||||
|
const [ filterExisting, setFilterExisting ] = useState(false);
|
||||||
|
const [ invert, setInvert ] = useState(false);
|
||||||
const { trigger = null, setIntParams } = useWired();
|
const { trigger = null, setIntParams } = useWired();
|
||||||
|
|
||||||
const save = useCallback(() =>
|
const save = useCallback(() =>
|
||||||
{
|
{
|
||||||
setIntParams([ rootX, rootY, areaWidth, areaHeight ]);
|
setIntParams([ rootX, rootY, areaWidth, areaHeight, filterExisting ? 1 : 0, invert ? 1 : 0 ]);
|
||||||
}, [ rootX, rootY, areaWidth, areaHeight, setIntParams ]);
|
}, [ rootX, rootY, areaWidth, areaHeight, filterExisting, invert, setIntParams ]);
|
||||||
|
|
||||||
|
// Activate the area selection manager when dialog opens, deactivate on close
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
if(!trigger) return;
|
if(!trigger) return;
|
||||||
@@ -34,6 +37,7 @@ export const WiredActionFurniAreaView: FC<{}> = props =>
|
|||||||
|
|
||||||
if(activated)
|
if(activated)
|
||||||
{
|
{
|
||||||
|
// Restore previously saved area highlight when re-opening dialog
|
||||||
if(trigger.intData.length >= 4 && trigger.intData[2] > 0 && trigger.intData[3] > 0)
|
if(trigger.intData.length >= 4 && trigger.intData[2] > 0 && trigger.intData[3] > 0)
|
||||||
{
|
{
|
||||||
GetRoomEngine().areaSelectionManager.setHighlight(
|
GetRoomEngine().areaSelectionManager.setHighlight(
|
||||||
@@ -69,19 +73,38 @@ export const WiredActionFurniAreaView: FC<{}> = props =>
|
|||||||
setAreaWidth(0);
|
setAreaWidth(0);
|
||||||
setAreaHeight(0);
|
setAreaHeight(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFilterExisting(trigger.intData.length >= 5 && trigger.intData[4] === 1);
|
||||||
|
setInvert(trigger.intData.length >= 6 && trigger.intData[5] === 1);
|
||||||
}, [ trigger ]);
|
}, [ trigger ]);
|
||||||
|
|
||||||
const hasArea = areaWidth > 0 && areaHeight > 0;
|
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 (
|
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">
|
<div className="flex flex-col gap-2">
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.area_selection') }</Text>
|
<Text bold>{ LocalizeText('wiredfurni.params.area_selection') }</Text>
|
||||||
<Text small>{ LocalizeText('wiredfurni.params.area_selection.info') }</Text>
|
<Text small>{ LocalizeText('wiredfurni.params.area_selection.info') }</Text>
|
||||||
|
|
||||||
{ hasArea &&
|
{ hasArea &&
|
||||||
<Text small>
|
<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> }
|
</Text> }
|
||||||
|
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
@@ -92,6 +115,28 @@ export const WiredActionFurniAreaView: FC<{}> = props =>
|
|||||||
{ LocalizeText('wiredfurni.params.area_selection.clear') }
|
{ LocalizeText('wiredfurni.params.area_selection.clear') }
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</WiredActionBaseView>
|
</WiredActionBaseView>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import { GetRoomEngine, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { CSSProperties, FC, useCallback, useEffect, useState } from 'react';
|
import { CSSProperties, FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { FaMinus, FaPlus, FaTimes } from 'react-icons/fa';
|
import { FaMinus, FaPlus, FaTimes } from 'react-icons/fa';
|
||||||
import { MdGridOn } from 'react-icons/md';
|
import { MdGridOn } from 'react-icons/md';
|
||||||
import { LocalizeText, WiredFurniType } from '../../../../api';
|
import { GetRoomSession, LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
|
||||||
import { Button, Text } from '../../../../common';
|
import { Button, Text } from '../../../../common';
|
||||||
import { useWired } from '../../../../hooks';
|
import { useWired } from '../../../../hooks';
|
||||||
import { WiredActionBaseView } from '../actions/WiredActionBaseView';
|
import { WiredActionBaseView } from '../actions/WiredActionBaseView';
|
||||||
@@ -46,10 +47,11 @@ const tileTop = (rx: number, ry: number) =>
|
|||||||
|
|
||||||
interface GridProps {
|
interface GridProps {
|
||||||
selectedTiles: Tile[];
|
selectedTiles: Tile[];
|
||||||
|
invert: boolean;
|
||||||
onToggle: (x: number, y: number) => void;
|
onToggle: (x: number, y: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NeighborhoodGrid: FC<GridProps> = ({ selectedTiles, onToggle }) =>
|
const NeighborhoodGrid: FC<GridProps> = ({ selectedTiles, invert, onToggle }) =>
|
||||||
{
|
{
|
||||||
const tiles: JSX.Element[] = [];
|
const tiles: JSX.Element[] = [];
|
||||||
|
|
||||||
@@ -59,19 +61,20 @@ const NeighborhoodGrid: FC<GridProps> = ({ selectedTiles, onToggle }) =>
|
|||||||
{
|
{
|
||||||
const isCenter = rx === 0 && ry === 0;
|
const isCenter = rx === 0 && ry === 0;
|
||||||
const isSelected = tileIncluded(selectedTiles, rx, ry);
|
const isSelected = tileIncluded(selectedTiles, rx, ry);
|
||||||
|
const isActive = invert ? !isSelected : isSelected;
|
||||||
const left = tileLeft(rx, ry);
|
const left = tileLeft(rx, ry);
|
||||||
const top_ = tileTop(rx, ry);
|
const top_ = tileTop(rx, ry);
|
||||||
const zIdx = rx + ry + GRID_RANGE * 2 + 10;
|
const zIdx = rx + ry + GRID_RANGE * 2 + 10;
|
||||||
|
|
||||||
const bgColor = isCenter
|
const bgColor = isCenter
|
||||||
? '#ff9500'
|
? '#ff9500'
|
||||||
: isSelected
|
: isActive
|
||||||
? '#3399ff'
|
? '#3399ff'
|
||||||
: '#2a3042';
|
: '#2a3042';
|
||||||
|
|
||||||
const borderColor = isCenter
|
const borderColor = isCenter
|
||||||
? '#cc6600'
|
? '#cc6600'
|
||||||
: isSelected
|
: isActive
|
||||||
? '#1166cc'
|
? '#1166cc'
|
||||||
: '#1a2032';
|
: '#1a2032';
|
||||||
|
|
||||||
@@ -127,7 +130,7 @@ export const WiredSelectorFurniNeighborhoodView: FC<{}> = () =>
|
|||||||
const [ curX, setCurX ] = useState(0);
|
const [ curX, setCurX ] = useState(0);
|
||||||
const [ curY, setCurY ] = useState(0);
|
const [ curY, setCurY ] = useState(0);
|
||||||
|
|
||||||
const { trigger = null, furniIds = [], setIntParams } = useWired();
|
const { trigger = null, furniIds = [], setIntParams, setFurniIds } = useWired();
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
@@ -157,6 +160,46 @@ export const WiredSelectorFurniNeighborhoodView: FC<{}> = () =>
|
|||||||
}
|
}
|
||||||
}, [ trigger ]);
|
}, [ 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 save = useCallback(() =>
|
||||||
{
|
{
|
||||||
const params: number[] = [
|
const params: number[] = [
|
||||||
@@ -235,7 +278,7 @@ export const WiredSelectorFurniNeighborhoodView: FC<{}> = () =>
|
|||||||
const pickedLimit = trigger?.maximumItemSelectionCount ?? 20;
|
const pickedLimit = trigger?.maximumItemSelectionCount ?? 20;
|
||||||
|
|
||||||
return (
|
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">
|
<div className="flex flex-col gap-2">
|
||||||
|
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.neighborhood_selection') }</Text>
|
<Text bold>{ LocalizeText('wiredfurni.params.neighborhood_selection') }</Text>
|
||||||
@@ -256,7 +299,7 @@ export const WiredSelectorFurniNeighborhoodView: FC<{}> = () =>
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<NeighborhoodGrid selectedTiles={ selectedTiles } onToggle={ toggleTile } />
|
<NeighborhoodGrid selectedTiles={ selectedTiles } invert={ invert } onToggle={ toggleTile } />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ const useWiredState = () =>
|
|||||||
const [ allowsFurni, setAllowsFurni ] = useState<number>(WiredFurniType.STUFF_SELECTION_OPTION_NONE);
|
const [ allowsFurni, setAllowsFurni ] = useState<number>(WiredFurniType.STUFF_SELECTION_OPTION_NONE);
|
||||||
const [ selectByType, setSelectByType ] = useState<boolean>(false);
|
const [ selectByType, setSelectByType ] = useState<boolean>(false);
|
||||||
const [ invertSelection, setInvertSelection ] = 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 { showConfirm = null } = useNotification();
|
||||||
|
|
||||||
const saveWired = () =>
|
const saveWired = () =>
|
||||||
@@ -206,10 +208,12 @@ const useWiredState = () =>
|
|||||||
setAllowsFurni(WiredFurniType.STUFF_SELECTION_OPTION_NONE);
|
setAllowsFurni(WiredFurniType.STUFF_SELECTION_OPTION_NONE);
|
||||||
setSelectByType(false);
|
setSelectByType(false);
|
||||||
setInvertSelection(false);
|
setInvertSelection(false);
|
||||||
|
setNeighborhoodTiles(null);
|
||||||
|
setNeighborhoodInvert(false);
|
||||||
};
|
};
|
||||||
}, [ trigger ]);
|
}, [ 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);
|
export const useWired = () => useBetween(useWiredState);
|
||||||
|
|||||||
Reference in New Issue
Block a user