mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
Polish wired editor UI and source selection flows
This commit is contained in:
@@ -20,5 +20,8 @@
|
|||||||
"widget.room.chat.clear_history": "leeg geschiedenis",
|
"widget.room.chat.clear_history": "leeg geschiedenis",
|
||||||
"widget.room.youtube.shared": "YouTube word gedeeld",
|
"widget.room.youtube.shared": "YouTube word gedeeld",
|
||||||
"widget.room.youtube.open_video": "Open de video",
|
"widget.room.youtube.open_video": "Open de video",
|
||||||
"wiredfurni.params.area_selection.selected": "Geselecteerd gebied: Lengte=%x%, Breedte=%y%, breedte=%w%, hoogte=%h%"
|
"wiredfurni.params.area_selection.selected": "Geselecteerd gebied: Lengte=%x%, Breedte=%y%, breedte=%w%, hoogte=%h%",
|
||||||
|
"wiredfurni.params.sources.users.11": "L'utente cliccato",
|
||||||
|
"wiredfurni.params.setexecutions": "Quantità di esecuzioni: %amount%",
|
||||||
|
"wiredfurni.params.settimewindow": "Tempo massimo consentito: %timewindow% secondi"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
{
|
{
|
||||||
"socket.url": "ws:localhost:2097",
|
"socket.url": "ws://192.168.1.52:2096",
|
||||||
"asset.url": "http://localhost:3000/public\nitro-assets\gamedata",
|
"asset.url": "https://client.paxxo.online/nitro/bundled",
|
||||||
"image.library.url": "http://localhost:3000/swf/gamedata/c_images/",
|
"image.library.url": "https://client.paxxo.online/c_images/",
|
||||||
"hof.furni.url": "http://localhost:3000/",
|
"hof.furni.url": "https://client.paxxo.online/c_images/dcr/hof_furni",
|
||||||
"images.url": "${asset.url}/images",
|
"images.url": "https://client.paxxo.online/nitro/images",
|
||||||
"gamedata.url": "${asset.url}",
|
"gamedata.url": "https://client.paxxo.online/nitro/gamedata",
|
||||||
"sounds.url": "${asset.url}/sounds/%sample%.mp3",
|
"sounds.url": "${asset.url}/sounds/%sample%.mp3",
|
||||||
"external.texts.url": [
|
"external.texts.url": [
|
||||||
"${gamedata.url}/config/ExternalTexts.json",
|
"${gamedata.url}/ExternalTexts.json",
|
||||||
"${gamedata.url}//config/UITexts.json"
|
"${gamedata.url}/UITexts.json"
|
||||||
],
|
],
|
||||||
"external.samples.url": "${hof.furni.url}/gamedata/sounds/sound_machine_sample_%sample%.mp3",
|
"external.samples.url": "${hof.furni.url}/mp3/sound_machine_sample_%sample%.mp3",
|
||||||
"furnidata.url": "${gamedata.url}/config/FurnitureData.json?v=1",
|
"furnidata.url": "${gamedata.url}/FurnitureData.json?v=1",
|
||||||
"productdata.url": "${gamedata.url}/config/ProductData.json?v=1",
|
"productdata.url": "${gamedata.url}/ProductData.json?v=1",
|
||||||
"avatar.actions.url": "${gamedata.url}/config/HabboAvatarActions.json?v=1",
|
"avatar.actions.url": "${gamedata.url}/HabboAvatarActions.json?v=1",
|
||||||
"avatar.figuredata.url": "${gamedata.url}/config/FigureData.json?v=1",
|
"avatar.figuredata.url": "${gamedata.url}/FigureData.json?v=1",
|
||||||
"avatar.figuremap.url": "${gamedata.url}/config/FigureMap.json?v=1",
|
"avatar.figuremap.url": "${gamedata.url}/FigureMap.json?v=1",
|
||||||
"avatar.effectmap.url": "${gamedata.url}/config/EffectMap.json?v=1",
|
"avatar.effectmap.url": "${gamedata.url}/EffectMap.json?v=1",
|
||||||
"avatar.asset.url": "${asset.url}/clothes/%libname%.nitro",
|
"avatar.asset.url": "${asset.url}/figure/%libname%.nitro",
|
||||||
"avatar.asset.effect.url": "${asset.url}/effect/%libname%.nitro",
|
"avatar.asset.effect.url": "${asset.url}/effect/%libname%.nitro",
|
||||||
"furni.asset.url": "${asset.url}/furniture/%libname%.nitro",
|
"furni.asset.url": "${asset.url}/furniture/%libname%.nitro",
|
||||||
"furni.asset.icon.url": "${gamedata.url}/icons/%libname%%param%_icon.png",
|
"furni.asset.icon.url": "${hof.furni.url}/icons/%libname%%param%_icon.png",
|
||||||
"generic.asset.url": "${asset.url}/generic_custom/%libname%.nitro",
|
|
||||||
"pet.asset.url": "${asset.url}/pets/%libname%.nitro",
|
"pet.asset.url": "${asset.url}/pets/%libname%.nitro",
|
||||||
|
"generic.asset.url": "${asset.url}/generic/%libname%.nitro",
|
||||||
"badge.asset.url": "${image.library.url}album1584/%badgename%.gif",
|
"badge.asset.url": "${image.library.url}album1584/%badgename%.gif",
|
||||||
"furni.rotation.bounce.steps": 20,
|
"furni.rotation.bounce.steps": 20,
|
||||||
"furni.rotation.bounce.height": 0.0625,
|
"furni.rotation.bounce.height": 0.0625,
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"system.log.warn": true,
|
"system.log.warn": true,
|
||||||
"system.log.error": true,
|
"system.log.error": true,
|
||||||
"system.log.events": false,
|
"system.log.events": false,
|
||||||
"system.log.packets": false,
|
"system.log.packets": true,
|
||||||
"system.fps.animation": 24,
|
"system.fps.animation": 24,
|
||||||
"system.fps.max": 60,
|
"system.fps.max": 60,
|
||||||
"system.pong.manually": true,
|
"system.pong.manually": true,
|
||||||
@@ -39,7 +39,6 @@
|
|||||||
"room.color.skip.transition": true,
|
"room.color.skip.transition": true,
|
||||||
"room.landscapes.enabled": true,
|
"room.landscapes.enabled": true,
|
||||||
"room.zoom.enabled": true,
|
"room.zoom.enabled": true,
|
||||||
"timezone.settings": "America/Los_Angeles",
|
|
||||||
"avatar.mandatory.libraries": [
|
"avatar.mandatory.libraries": [
|
||||||
"bd:1",
|
"bd:1",
|
||||||
"li:0"
|
"li:0"
|
||||||
@@ -578,11 +577,11 @@
|
|||||||
"elephants"
|
"elephants"
|
||||||
],
|
],
|
||||||
"preload.assets.urls": [
|
"preload.assets.urls": [
|
||||||
"${asset.url}/bundled/generic/avatar_additions.nitro",
|
"${asset.url}/generic/avatar_additions.nitro",
|
||||||
"${asset.url}/bundled/generic/group_badge.nitro",
|
"${asset.url}/generic/group_badge.nitro",
|
||||||
"${asset.url}/bundled/generic/floor_editor.nitro",
|
"${asset.url}/generic/floor_editor.nitro",
|
||||||
"${images.url}/loading_icon.png",
|
"${images.url}/loading_icon.png",
|
||||||
"${images.url}/clear_icon.png",
|
"${images.url}/clear_icon.png",
|
||||||
"${images.url}/big_arrow.png"
|
"${images.url}/big_arrow.png"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -62,4 +62,6 @@ export class WiredActionLayoutCode
|
|||||||
public static MOVE_PHYSICS_EXTRA: number = 61;
|
public static MOVE_PHYSICS_EXTRA: number = 61;
|
||||||
public static UNSEEN_EXTRA: number = 62;
|
public static UNSEEN_EXTRA: number = 62;
|
||||||
public static RANDOM_EXTRA: number = 63;
|
public static RANDOM_EXTRA: number = 63;
|
||||||
|
public static EXEC_IN_ORDER_EXTRA: number = 64;
|
||||||
|
public static EXECUTION_LIMIT_EXTRA: number = 65;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ export const Slider: FC<SliderProps> = props =>
|
|||||||
return parseFloat(nextValue.toFixed(precision));
|
return parseFloat(nextValue.toFixed(precision));
|
||||||
};
|
};
|
||||||
|
|
||||||
return <Flex fullWidth gap={ 1 }>
|
return <Flex fullWidth gap={ 1 } classNames={ [ 'nitro-slider-wrapper' ] }>
|
||||||
{ !disabledButton && <Button disabled={ minimum >= currentValue } onClick={ () => onChange(roundToStep(minimum < currentValue ? currentValue - buttonStep : minimum), 0) }><FaAngleLeft /></Button> }
|
{ !disabledButton && <Button classNames={ [ 'nitro-slider-button', 'nitro-slider-button-left' ] } disabled={ minimum >= currentValue } onClick={ () => onChange(roundToStep(minimum < currentValue ? currentValue - buttonStep : minimum), 0) }><FaAngleLeft /></Button> }
|
||||||
<ReactSlider className={ 'nitro-slider' } max={ max } min={ min } step={ step } value={ value } onChange={ onChange } { ...rest } />
|
<ReactSlider className={ 'nitro-slider' } max={ max } min={ min } step={ step } value={ value } onChange={ onChange } { ...rest } />
|
||||||
{ !disabledButton && <Button disabled={ maximum <= currentValue } onClick={ () => onChange(roundToStep(maximum > currentValue ? currentValue + buttonStep : maximum), 0) }><FaAngleRight /></Button> }
|
{ !disabledButton && <Button classNames={ [ 'nitro-slider-button', 'nitro-slider-button-right' ] } disabled={ maximum <= currentValue } onClick={ () => onChange(roundToStep(maximum > currentValue ? currentValue + buttonStep : maximum), 0) }><FaAngleRight /></Button> }
|
||||||
</Flex>;
|
</Flex>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,16 @@ export interface WiredBaseViewProps
|
|||||||
validate?: () => boolean;
|
validate?: () => boolean;
|
||||||
cardStyle?: CSSProperties;
|
cardStyle?: CSSProperties;
|
||||||
footer?: ReactNode;
|
footer?: ReactNode;
|
||||||
|
footerCollapsible?: boolean;
|
||||||
|
selectionPreview?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WiredBaseView: FC<PropsWithChildren<WiredBaseViewProps>> = props =>
|
export const WiredBaseView: FC<PropsWithChildren<WiredBaseViewProps>> = props =>
|
||||||
{
|
{
|
||||||
const { wiredType = '', requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, validate = null, children = null, hasSpecialInput = false, cardStyle = undefined, footer = null } = props;
|
const { wiredType = '', requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, validate = null, children = null, hasSpecialInput = false, cardStyle = undefined, footer = null, footerCollapsible = true, selectionPreview = null } = props;
|
||||||
const [ wiredName, setWiredName ] = useState<string>(null);
|
const [ wiredName, setWiredName ] = useState<string>(null);
|
||||||
const [ wiredDescription, setWiredDescription ] = useState<string>(null);
|
|
||||||
const [ needsSave, setNeedsSave ] = useState<boolean>(false);
|
const [ needsSave, setNeedsSave ] = useState<boolean>(false);
|
||||||
|
const [ showFooter, setShowFooter ] = useState(false);
|
||||||
const { trigger = null, setTrigger = null, setIntParams = null, setStringParam = null, setFurniIds = null, setAllowsFurni = null, saveWired = null } = useWired();
|
const { trigger = null, setTrigger = null, setIntParams = null, setStringParam = null, setFurniIds = null, setAllowsFurni = null, saveWired = null } = useWired();
|
||||||
|
|
||||||
const clearRoomAreaSelection = () =>
|
const clearRoomAreaSelection = () =>
|
||||||
@@ -59,6 +61,8 @@ export const WiredBaseView: FC<PropsWithChildren<WiredBaseViewProps>> = props =>
|
|||||||
{
|
{
|
||||||
if(!trigger) return;
|
if(!trigger) return;
|
||||||
|
|
||||||
|
setShowFooter(false);
|
||||||
|
|
||||||
WiredSelectionVisualizer.clearAllSelectionShaders();
|
WiredSelectionVisualizer.clearAllSelectionShaders();
|
||||||
|
|
||||||
const spriteId = (trigger.spriteId || -1);
|
const spriteId = (trigger.spriteId || -1);
|
||||||
@@ -67,12 +71,10 @@ export const WiredBaseView: FC<PropsWithChildren<WiredBaseViewProps>> = props =>
|
|||||||
if(!furniData)
|
if(!furniData)
|
||||||
{
|
{
|
||||||
setWiredName(('NAME: ' + spriteId));
|
setWiredName(('NAME: ' + spriteId));
|
||||||
setWiredDescription(('NAME: ' + spriteId));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
setWiredName(furniData.name);
|
setWiredName(furniData.name);
|
||||||
setWiredDescription(furniData.description);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasSpecialInput)
|
if(hasSpecialInput)
|
||||||
@@ -115,36 +117,62 @@ export const WiredBaseView: FC<PropsWithChildren<WiredBaseViewProps>> = props =>
|
|||||||
|
|
||||||
if(resolvedCardStyle.width !== undefined)
|
if(resolvedCardStyle.width !== undefined)
|
||||||
{
|
{
|
||||||
resolvedCardStyle.minWidth = resolvedCardStyle.width;
|
if(typeof resolvedCardStyle.width === 'number')
|
||||||
|
{
|
||||||
|
resolvedCardStyle.maxWidth = Math.min(resolvedCardStyle.width, 324);
|
||||||
|
}
|
||||||
|
else if(typeof resolvedCardStyle.width === 'string')
|
||||||
|
{
|
||||||
|
const match = resolvedCardStyle.width.trim().match(/^(\d+(?:\.\d+)?)px$/i);
|
||||||
|
|
||||||
|
resolvedCardStyle.maxWidth = match ? `${ Math.min(parseFloat(match[1]), 324) }px` : resolvedCardStyle.width;
|
||||||
|
}
|
||||||
|
|
||||||
delete resolvedCardStyle.width;
|
delete resolvedCardStyle.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(resolvedCardStyle.minWidth === undefined) resolvedCardStyle.minWidth = 216;
|
||||||
|
if(resolvedCardStyle.maxWidth === undefined) resolvedCardStyle.maxWidth = 'min(90vw, 324px)';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NitroCardView className="nitro-wired" theme="primary-slim" uniqueKey="nitro-wired" isResizable={ false } style={ resolvedCardStyle }>
|
<NitroCardView className="nitro-wired" theme="primary-slim" uniqueKey="nitro-wired" isResizable={ false } style={ resolvedCardStyle }>
|
||||||
<NitroCardHeaderView headerText={ LocalizeText('wiredfurni.title') } onCloseClick={ onClose } />
|
<NitroCardHeaderView classNames={ [ 'nitro-wired__header' ] } headerText={ LocalizeText('wiredfurni.title') } onCloseClick={ onClose } />
|
||||||
<NitroCardContentView>
|
<NitroCardContentView classNames={ [ 'nitro-wired__content' ] } gap={ 2 }>
|
||||||
<div className="flex flex-col gap-1">
|
<div className="nitro-wired__section nitro-wired__summary">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center justify-center gap-1">
|
||||||
<i className={ `icon icon-wired-${ wiredType }` } />
|
<i className={ `icon icon-wired-${ wiredType }` } />
|
||||||
<Text bold>{ wiredName }</Text>
|
<Text bold className="nitro-wired__summary-title">{ wiredName }</Text>
|
||||||
</div>
|
</div>
|
||||||
<Text small>{ wiredDescription }</Text>
|
|
||||||
</div>
|
</div>
|
||||||
{ !!children && <hr className="m-0 bg-dark" /> }
|
{ !!children && <div className="nitro-wired__divider" /> }
|
||||||
{ children }
|
{ !!children && <div className="nitro-wired__section nitro-wired__section--body">{ children }</div> }
|
||||||
{ (requiresFurni > WiredFurniType.STUFF_SELECTION_OPTION_NONE) &&
|
{ (requiresFurni > WiredFurniType.STUFF_SELECTION_OPTION_NONE) &&
|
||||||
<>
|
<>
|
||||||
<hr className="m-0 bg-dark" />
|
<div className="nitro-wired__divider" />
|
||||||
<WiredFurniSelectorView />
|
<div className="nitro-wired__section nitro-wired__section--selector">
|
||||||
|
{ selectionPreview || <WiredFurniSelectorView /> }
|
||||||
|
</div>
|
||||||
</> }
|
</> }
|
||||||
{ footer &&
|
{ footer &&
|
||||||
<>
|
<>
|
||||||
<hr className="m-0 bg-dark" />
|
<div className="nitro-wired__divider" />
|
||||||
{ footer }
|
<div className="nitro-wired__section nitro-wired__section--footer">
|
||||||
|
{ footerCollapsible
|
||||||
|
? (
|
||||||
|
<>
|
||||||
|
<button className="nitro-wired__advanced-toggle" type="button" onClick={ () => setShowFooter(value => !value) }>
|
||||||
|
{ LocalizeText(showFooter ? 'wiredfurni.params.sources.collapse' : 'wiredfurni.params.sources.expand') }
|
||||||
|
</button>
|
||||||
|
{ showFooter && <div className="nitro-wired__advanced-body">{ footer }</div> }
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
: footer }
|
||||||
|
</div>
|
||||||
</> }
|
</> }
|
||||||
<div className="flex items-center gap-1">
|
<div className="nitro-wired__divider" />
|
||||||
<Button fullWidth variant="success" onClick={ onSave }>{ LocalizeText('wiredfurni.ready') }</Button>
|
<div className="flex items-center gap-1 nitro-wired__actions">
|
||||||
<Button fullWidth variant="secondary" onClick={ onClose }>{ LocalizeText('cancel') }</Button>
|
<Button fullWidth variant="success" classNames={ [ 'nitro-wired__button', 'nitro-wired__button--primary' ] } onClick={ onSave }>{ LocalizeText('wiredfurni.ready') }</Button>
|
||||||
|
<Button fullWidth variant="secondary" classNames={ [ 'nitro-wired__button', 'nitro-wired__button--secondary' ] } onClick={ onClose }>{ LocalizeText('cancel') }</Button>
|
||||||
</div>
|
</div>
|
||||||
</NitroCardContentView>
|
</NitroCardContentView>
|
||||||
</NitroCardView>
|
</NitroCardView>
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { FaChevronLeft, FaChevronRight, FaMousePointer } from 'react-icons/fa';
|
||||||
|
import { LocalizeText } from '../../../api';
|
||||||
|
import { Button, Text } from '../../../common';
|
||||||
|
import { WiredSourceOption } from './WiredSourcesSelector';
|
||||||
|
|
||||||
|
interface WiredFurniSelectionSourceRowProps
|
||||||
|
{
|
||||||
|
title: string;
|
||||||
|
titleIsLiteral?: boolean;
|
||||||
|
options: WiredSourceOption[];
|
||||||
|
value: number;
|
||||||
|
selectionKind: 'primary' | 'secondary';
|
||||||
|
selectionActive: boolean;
|
||||||
|
selectionCount: number;
|
||||||
|
selectionLimit: number;
|
||||||
|
selectionEnabledValues: number[];
|
||||||
|
showSelectionToggle?: boolean;
|
||||||
|
onChange: (value: number) => void;
|
||||||
|
onSelectionActivate?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WiredFurniSelectionSourceRow: FC<WiredFurniSelectionSourceRowProps> = props =>
|
||||||
|
{
|
||||||
|
const { title = '', titleIsLiteral = false, options = [], value = 0, selectionKind = 'primary', selectionActive = false, selectionCount = 0, selectionLimit = 0, selectionEnabledValues = [], showSelectionToggle = true, onChange = null, onSelectionActivate = null } = props;
|
||||||
|
const currentIndex = Math.max(0, options.findIndex(option => (option.value === value)));
|
||||||
|
const currentOption = options[currentIndex] ?? options[0];
|
||||||
|
const canActivateSelection = !!onSelectionActivate && selectionEnabledValues.includes(currentOption?.value);
|
||||||
|
const shouldShowCount = selectionEnabledValues.includes(currentOption?.value);
|
||||||
|
const countText = selectionLimit ? `[${ selectionCount }/${ selectionLimit }]` : `[${ selectionCount }]`;
|
||||||
|
const labelText = currentOption ? LocalizeText(currentOption.label) : '';
|
||||||
|
const displayText = shouldShowCount ? `${ labelText } ${ countText }` : labelText;
|
||||||
|
const resolvedTitle = titleIsLiteral ? title : LocalizeText(title);
|
||||||
|
|
||||||
|
const cycleValue = (direction: -1 | 1) =>
|
||||||
|
{
|
||||||
|
if(!options.length || !onChange) return;
|
||||||
|
|
||||||
|
const nextIndex = (currentIndex + direction + options.length) % options.length;
|
||||||
|
|
||||||
|
onChange(options[nextIndex].value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="nitro-wired__source-row">
|
||||||
|
<div className="flex items-center justify-between gap-2">
|
||||||
|
<Text>{ resolvedTitle }</Text>
|
||||||
|
{ showSelectionToggle &&
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={ `nitro-wired__selection-toggle nitro-wired__selection-toggle--${ selectionKind } ${ selectionActive ? 'is-active' : '' }` }
|
||||||
|
disabled={ !canActivateSelection }
|
||||||
|
onClick={ () => onSelectionActivate && onSelectionActivate() }>
|
||||||
|
<FaMousePointer />
|
||||||
|
</button> }
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<Button variant="primary" classNames={ [ 'nitro-wired__picker-button' ] } className="px-2 py-1" onClick={ () => cycleValue(-1) }><FaChevronLeft /></Button>
|
||||||
|
<div className="flex min-w-0 flex-1 items-center justify-center nitro-wired__picker-label">
|
||||||
|
<Text small className="text-center">{ displayText }</Text>
|
||||||
|
</div>
|
||||||
|
<Button variant="primary" classNames={ [ 'nitro-wired__picker-button' ] } className="px-2 py-1" onClick={ () => cycleValue(1) }><FaChevronRight /></Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -8,9 +8,9 @@ export const WiredFurniSelectorView: FC<{}> = props =>
|
|||||||
const { trigger = null, furniIds = [] } = useWired();
|
const { trigger = null, furniIds = [] } = useWired();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1 nitro-wired__furni-selector">
|
||||||
<Text bold>{ LocalizeText('wiredfurni.pickfurnis.caption', [ 'count', 'limit' ], [ furniIds.length.toString(), trigger.maximumItemSelectionCount.toString() ]) }</Text>
|
<Text bold className="nitro-wired__furni-selector-title">{ LocalizeText('wiredfurni.pickfurnis.caption', [ 'count', 'limit' ], [ furniIds.length.toString(), trigger.maximumItemSelectionCount.toString() ]) }</Text>
|
||||||
<Text small>{ LocalizeText('wiredfurni.pickfurnis.desc') }</Text>
|
<Text small className="nitro-wired__furni-selector-description">{ LocalizeText('wiredfurni.pickfurnis.desc') }</Text>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import { FC } from 'react';
|
import { FurnitureFloorUpdateEvent, GetRoomEngine, GetSessionDataManager, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectVariable, Triggerable } from '@nitrots/nitro-renderer';
|
||||||
|
import { FC, ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { FaChevronLeft, FaChevronRight } from 'react-icons/fa';
|
import { FaChevronLeft, FaChevronRight } from 'react-icons/fa';
|
||||||
import { LocalizeText } from '../../../api';
|
import { GetRoomSession, LocalizeText } from '../../../api';
|
||||||
import { Button, Text } from '../../../common';
|
import { Button, Text } from '../../../common';
|
||||||
|
import { useMessageEvent, useNitroEvent, useWired } from '../../../hooks';
|
||||||
|
|
||||||
export const FURNI_SOURCES = [
|
export const FURNI_SOURCES = [
|
||||||
{ value: 0, label: 'wiredfurni.params.sources.furni.0' },
|
|
||||||
{ value: 100, label: 'wiredfurni.params.sources.furni.100' },
|
{ value: 100, label: 'wiredfurni.params.sources.furni.100' },
|
||||||
{ value: 200, label: 'wiredfurni.params.sources.furni.200' },
|
{ value: 200, label: 'wiredfurni.params.sources.furni.200' },
|
||||||
{ value: 201, label: 'wiredfurni.params.sources.furni.201' }
|
{ value: 201, label: 'wiredfurni.params.sources.furni.201' },
|
||||||
|
{ value: 0, label: 'wiredfurni.params.sources.furni.0' }
|
||||||
];
|
];
|
||||||
|
|
||||||
export const USER_SOURCES = [
|
export const USER_SOURCES = [
|
||||||
@@ -16,6 +18,9 @@ export const USER_SOURCES = [
|
|||||||
{ value: 201, label: 'wiredfurni.params.sources.users.201' }
|
{ value: 201, label: 'wiredfurni.params.sources.users.201' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const CLICKED_USER_SOURCE_VALUE = 11;
|
||||||
|
export const CLICKED_USER_SOURCE = { value: CLICKED_USER_SOURCE_VALUE, label: 'wiredfurni.params.sources.users.11' };
|
||||||
|
|
||||||
export const BOT_SOURCES = [
|
export const BOT_SOURCES = [
|
||||||
{ value: 0, label: 'wiredfurni.params.sources.users.0' },
|
{ value: 0, label: 'wiredfurni.params.sources.users.0' },
|
||||||
{ value: 100, label: 'wiredfurni.params.sources.users.100' },
|
{ value: 100, label: 'wiredfurni.params.sources.users.100' },
|
||||||
@@ -29,6 +34,45 @@ export interface WiredSourceOption
|
|||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FURNI_SOURCE_LABEL_ORDER = [
|
||||||
|
'wiredfurni.params.sources.furni.100',
|
||||||
|
'wiredfurni.params.sources.furni.101',
|
||||||
|
'wiredfurni.params.sources.furni.200',
|
||||||
|
'wiredfurni.params.sources.furni.201',
|
||||||
|
'wiredfurni.params.sources.furni.0',
|
||||||
|
'wiredfurni.params.sources.furni.900'
|
||||||
|
];
|
||||||
|
|
||||||
|
const USER_SOURCE_LABEL_ORDER = [
|
||||||
|
'wiredfurni.params.sources.users.0',
|
||||||
|
'wiredfurni.params.sources.users.11',
|
||||||
|
'wiredfurni.params.sources.users.100',
|
||||||
|
'wiredfurni.params.sources.users.101',
|
||||||
|
'wiredfurni.params.sources.users.200',
|
||||||
|
'wiredfurni.params.sources.users.201',
|
||||||
|
'wiredfurni.params.sources.users.900'
|
||||||
|
];
|
||||||
|
|
||||||
|
const getSourceSortIndex = (label: string, category: 'furni' | 'users') =>
|
||||||
|
{
|
||||||
|
const order = (category === 'furni') ? FURNI_SOURCE_LABEL_ORDER : USER_SOURCE_LABEL_ORDER;
|
||||||
|
const index = order.indexOf(label);
|
||||||
|
|
||||||
|
return (index >= 0) ? index : (order.length + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sortWiredSourceOptions = (options: WiredSourceOption[], category: 'furni' | 'users') =>
|
||||||
|
{
|
||||||
|
return [ ...options ].sort((left, right) =>
|
||||||
|
{
|
||||||
|
const orderDifference = getSourceSortIndex(left.label, category) - getSourceSortIndex(right.label, category);
|
||||||
|
|
||||||
|
if(orderDifference !== 0) return orderDifference;
|
||||||
|
|
||||||
|
return left.value - right.value;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
interface WiredSourcesSelectorProps
|
interface WiredSourcesSelectorProps
|
||||||
{
|
{
|
||||||
showFurni?: boolean;
|
showFurni?: boolean;
|
||||||
@@ -39,10 +83,122 @@ interface WiredSourcesSelectorProps
|
|||||||
usersTitle?: string;
|
usersTitle?: string;
|
||||||
furniSources?: WiredSourceOption[];
|
furniSources?: WiredSourceOption[];
|
||||||
userSources?: WiredSourceOption[];
|
userSources?: WiredSourceOption[];
|
||||||
|
allowClickedUserSource?: boolean;
|
||||||
|
furniDetail?: ReactNode;
|
||||||
|
userDetail?: ReactNode;
|
||||||
onChangeFurni?: (source: number) => void;
|
onChangeFurni?: (source: number) => void;
|
||||||
onChangeUsers?: (source: number) => void;
|
onChangeUsers?: (source: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BOT_SOURCE_TITLE = 'wiredfurni.params.sources.users.title.bots';
|
||||||
|
|
||||||
|
const CLICK_USER_TRIGGER_NAME = 'wf_trg_click_user';
|
||||||
|
const isClickUserTriggerName = (value?: string) =>
|
||||||
|
{
|
||||||
|
if(!value) return false;
|
||||||
|
|
||||||
|
return value.toLowerCase().startsWith(CLICK_USER_TRIGGER_NAME);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasClickUserTriggerInStack = (trigger: Triggerable) =>
|
||||||
|
{
|
||||||
|
if(!trigger) return false;
|
||||||
|
|
||||||
|
const roomSession = GetRoomSession();
|
||||||
|
const roomId = roomSession?.roomId ?? GetRoomEngine().activeRoomId;
|
||||||
|
|
||||||
|
if(roomId == null || roomId < 0) return false;
|
||||||
|
|
||||||
|
const triggerObject = GetRoomEngine().getRoomObject(roomId, trigger.id, RoomObjectCategory.FLOOR);
|
||||||
|
|
||||||
|
if(!triggerObject) return false;
|
||||||
|
|
||||||
|
const triggerLocation = triggerObject.getLocation();
|
||||||
|
const roomObjects = GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.FLOOR) || [];
|
||||||
|
|
||||||
|
for(const roomObject of roomObjects)
|
||||||
|
{
|
||||||
|
if(!roomObject) continue;
|
||||||
|
|
||||||
|
const location = roomObject.getLocation();
|
||||||
|
|
||||||
|
if(!location || location.x !== triggerLocation.x || location.y !== triggerLocation.y) continue;
|
||||||
|
|
||||||
|
const typeId = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_TYPE_ID);
|
||||||
|
const furniData = GetSessionDataManager().getFloorItemData(typeId);
|
||||||
|
|
||||||
|
if(isClickUserTriggerName(furniData?.className) || isClickUserTriggerName(furniData?.fullName) || isClickUserTriggerName(furniData?.name)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAvailableUserSources = (trigger: Triggerable, userSources: WiredSourceOption[], currentUserSource: number, usersTitle = 'wiredfurni.params.sources.users.title', allowClickedUserSource = true) =>
|
||||||
|
{
|
||||||
|
if(!allowClickedUserSource || usersTitle === BOT_SOURCE_TITLE) return userSources;
|
||||||
|
if(userSources.some(option => option.value === CLICKED_USER_SOURCE_VALUE)) return userSources;
|
||||||
|
|
||||||
|
if(!hasClickUserTriggerInStack(trigger)) return userSources;
|
||||||
|
|
||||||
|
const triggerIndex = userSources.findIndex(option => option.value === 0);
|
||||||
|
|
||||||
|
if(triggerIndex === -1) return [ ...userSources, CLICKED_USER_SOURCE ];
|
||||||
|
|
||||||
|
return [
|
||||||
|
...userSources.slice(0, triggerIndex + 1),
|
||||||
|
CLICKED_USER_SOURCE,
|
||||||
|
...userSources.slice(triggerIndex + 1)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAvailableUserSources = (trigger: Triggerable, userSources: WiredSourceOption[] = USER_SOURCES, usersTitle = 'wiredfurni.params.sources.users.title', allowClickedUserSource = true) =>
|
||||||
|
{
|
||||||
|
const [ hasClickUserTrigger, setHasClickUserTrigger ] = useState(false);
|
||||||
|
|
||||||
|
const refreshStackSources = useCallback(() =>
|
||||||
|
{
|
||||||
|
setHasClickUserTrigger(hasClickUserTriggerInStack(trigger));
|
||||||
|
}, [ trigger ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
refreshStackSources();
|
||||||
|
|
||||||
|
if(!trigger) return;
|
||||||
|
|
||||||
|
const intervalId = window.setInterval(refreshStackSources, 100);
|
||||||
|
|
||||||
|
return () => window.clearInterval(intervalId);
|
||||||
|
}, [ refreshStackSources, trigger ]);
|
||||||
|
|
||||||
|
useNitroEvent<RoomEngineObjectEvent>([
|
||||||
|
RoomEngineObjectEvent.ADDED,
|
||||||
|
RoomEngineObjectEvent.REMOVED,
|
||||||
|
RoomEngineObjectEvent.PLACED,
|
||||||
|
RoomEngineObjectEvent.CONTENT_UPDATED
|
||||||
|
], event =>
|
||||||
|
{
|
||||||
|
if(!trigger) return;
|
||||||
|
if(event.category !== RoomObjectCategory.FLOOR) return;
|
||||||
|
|
||||||
|
const roomSession = GetRoomSession();
|
||||||
|
const roomId = roomSession?.roomId ?? GetRoomEngine().activeRoomId;
|
||||||
|
|
||||||
|
if(event.roomId !== roomId) return;
|
||||||
|
|
||||||
|
refreshStackSources();
|
||||||
|
}, !!trigger);
|
||||||
|
|
||||||
|
useMessageEvent<FurnitureFloorUpdateEvent>(FurnitureFloorUpdateEvent, () =>
|
||||||
|
{
|
||||||
|
if(!trigger) return;
|
||||||
|
|
||||||
|
refreshStackSources();
|
||||||
|
});
|
||||||
|
|
||||||
|
return useMemo(() => getAvailableUserSources(trigger, userSources, 0, usersTitle, allowClickedUserSource && hasClickUserTrigger), [ allowClickedUserSource, hasClickUserTrigger, trigger, userSources, usersTitle ]);
|
||||||
|
};
|
||||||
|
|
||||||
export const WiredSourcesSelector: FC<WiredSourcesSelectorProps> = props =>
|
export const WiredSourcesSelector: FC<WiredSourcesSelectorProps> = props =>
|
||||||
{
|
{
|
||||||
const {
|
const {
|
||||||
@@ -54,35 +210,51 @@ export const WiredSourcesSelector: FC<WiredSourcesSelectorProps> = props =>
|
|||||||
usersTitle = 'wiredfurni.params.sources.users.title',
|
usersTitle = 'wiredfurni.params.sources.users.title',
|
||||||
furniSources = FURNI_SOURCES,
|
furniSources = FURNI_SOURCES,
|
||||||
userSources = USER_SOURCES,
|
userSources = USER_SOURCES,
|
||||||
|
allowClickedUserSource = true,
|
||||||
|
furniDetail = null,
|
||||||
|
userDetail = null,
|
||||||
onChangeFurni = null,
|
onChangeFurni = null,
|
||||||
onChangeUsers = null
|
onChangeUsers = null
|
||||||
} = props;
|
} = props;
|
||||||
|
const { trigger = null } = useWired();
|
||||||
|
const availableUserSources = useAvailableUserSources(trigger, userSources, usersTitle, allowClickedUserSource);
|
||||||
|
const orderedFurniSources = useMemo(() => sortWiredSourceOptions(furniSources, 'furni'), [ furniSources ]);
|
||||||
|
const orderedUserSources = useMemo(() => sortWiredSourceOptions(availableUserSources, 'users'), [ availableUserSources ]);
|
||||||
|
|
||||||
const furniIndex = Math.max(0, furniSources.findIndex(s => s.value === furniSource));
|
useEffect(() =>
|
||||||
const userIndex = Math.max(0, userSources.findIndex(s => s.value === userSource));
|
{
|
||||||
|
if(!showUsers || !onChangeUsers) return;
|
||||||
|
if(userSource !== CLICKED_USER_SOURCE_VALUE) return;
|
||||||
|
if(availableUserSources.some(source => source.value === CLICKED_USER_SOURCE_VALUE)) return;
|
||||||
|
|
||||||
|
onChangeUsers(0);
|
||||||
|
}, [ availableUserSources, onChangeUsers, showUsers, userSource ]);
|
||||||
|
|
||||||
|
const furniIndex = Math.max(0, orderedFurniSources.findIndex(s => s.value === furniSource));
|
||||||
|
const userIndex = Math.max(0, orderedUserSources.findIndex(s => s.value === userSource));
|
||||||
|
|
||||||
const prevFurni = () =>
|
const prevFurni = () =>
|
||||||
{
|
{
|
||||||
const next = (furniIndex - 1 + furniSources.length) % furniSources.length;
|
const next = (furniIndex - 1 + orderedFurniSources.length) % orderedFurniSources.length;
|
||||||
onChangeFurni && onChangeFurni(furniSources[next].value);
|
onChangeFurni && onChangeFurni(orderedFurniSources[next].value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const nextFurni = () =>
|
const nextFurni = () =>
|
||||||
{
|
{
|
||||||
const next = (furniIndex + 1) % furniSources.length;
|
const next = (furniIndex + 1) % orderedFurniSources.length;
|
||||||
onChangeFurni && onChangeFurni(furniSources[next].value);
|
onChangeFurni && onChangeFurni(orderedFurniSources[next].value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const prevUsers = () =>
|
const prevUsers = () =>
|
||||||
{
|
{
|
||||||
const next = (userIndex - 1 + userSources.length) % userSources.length;
|
const next = (userIndex - 1 + orderedUserSources.length) % orderedUserSources.length;
|
||||||
onChangeUsers && onChangeUsers(userSources[next].value);
|
onChangeUsers && onChangeUsers(orderedUserSources[next].value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const nextUsers = () =>
|
const nextUsers = () =>
|
||||||
{
|
{
|
||||||
const next = (userIndex + 1) % userSources.length;
|
const next = (userIndex + 1) % orderedUserSources.length;
|
||||||
onChangeUsers && onChangeUsers(userSources[next].value);
|
onChangeUsers && onChangeUsers(orderedUserSources[next].value);
|
||||||
};
|
};
|
||||||
|
|
||||||
if(!showFurni && !showUsers) return null;
|
if(!showFurni && !showUsers) return null;
|
||||||
@@ -92,13 +264,14 @@ export const WiredSourcesSelector: FC<WiredSourcesSelectorProps> = props =>
|
|||||||
{ showFurni &&
|
{ showFurni &&
|
||||||
<>
|
<>
|
||||||
<Text bold>{ LocalizeText(furniTitle) }</Text>
|
<Text bold>{ LocalizeText(furniTitle) }</Text>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-1">
|
||||||
<Button variant="primary" className="px-2 py-1" onClick={ prevFurni }><FaChevronLeft /></Button>
|
<Button variant="primary" classNames={ [ 'nitro-wired__picker-button' ] } className="px-2 py-1" onClick={ prevFurni }><FaChevronLeft /></Button>
|
||||||
<div className="flex flex-1 items-center justify-center">
|
<div className="flex min-w-0 flex-1 items-center justify-center nitro-wired__picker-label">
|
||||||
<Text small>{ LocalizeText(furniSources[furniIndex].label) }</Text>
|
<Text small className="text-center">{ LocalizeText(orderedFurniSources[furniIndex].label) }</Text>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="primary" className="px-2 py-1" onClick={ nextFurni }><FaChevronRight /></Button>
|
<Button variant="primary" classNames={ [ 'nitro-wired__picker-button' ] } className="px-2 py-1" onClick={ nextFurni }><FaChevronRight /></Button>
|
||||||
</div>
|
</div>
|
||||||
|
{ furniDetail && <div className="nitro-wired__source-detail">{ furniDetail }</div> }
|
||||||
</> }
|
</> }
|
||||||
|
|
||||||
{ showFurni && showUsers && <hr className="m-0 bg-dark" /> }
|
{ showFurni && showUsers && <hr className="m-0 bg-dark" /> }
|
||||||
@@ -106,13 +279,14 @@ export const WiredSourcesSelector: FC<WiredSourcesSelectorProps> = props =>
|
|||||||
{ showUsers &&
|
{ showUsers &&
|
||||||
<>
|
<>
|
||||||
<Text bold>{ LocalizeText(usersTitle) }</Text>
|
<Text bold>{ LocalizeText(usersTitle) }</Text>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-1">
|
||||||
<Button variant="primary" className="px-2 py-1" onClick={ prevUsers }><FaChevronLeft /></Button>
|
<Button variant="primary" classNames={ [ 'nitro-wired__picker-button' ] } className="px-2 py-1" onClick={ prevUsers }><FaChevronLeft /></Button>
|
||||||
<div className="flex flex-1 items-center justify-center">
|
<div className="flex min-w-0 flex-1 items-center justify-center nitro-wired__picker-label">
|
||||||
<Text small>{ LocalizeText(userSources[userIndex].label) }</Text>
|
<Text small className="text-center">{ LocalizeText(orderedUserSources[userIndex].label) }</Text>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="primary" className="px-2 py-1" onClick={ nextUsers }><FaChevronRight /></Button>
|
<Button variant="primary" classNames={ [ 'nitro-wired__picker-button' ] } className="px-2 py-1" onClick={ nextUsers }><FaChevronRight /></Button>
|
||||||
</div>
|
</div>
|
||||||
|
{ userDetail && <div className="nitro-wired__source-detail">{ userDetail }</div> }
|
||||||
</> }
|
</> }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ export interface WiredActionBaseViewProps
|
|||||||
cardStyle?: CSSProperties;
|
cardStyle?: CSSProperties;
|
||||||
hideDelay?: boolean;
|
hideDelay?: boolean;
|
||||||
footer?: ReactNode;
|
footer?: ReactNode;
|
||||||
|
footerCollapsible?: boolean;
|
||||||
|
selectionPreview?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WiredActionBaseView: FC<PropsWithChildren<WiredActionBaseViewProps>> = props =>
|
export const WiredActionBaseView: FC<PropsWithChildren<WiredActionBaseViewProps>> = props =>
|
||||||
{
|
{
|
||||||
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, validate = null, hasSpecialInput = false, children = null, cardStyle = undefined, hideDelay = false, footer = null } = props;
|
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, validate = null, hasSpecialInput = false, children = null, cardStyle = undefined, hideDelay = false, footer = null, footerCollapsible = true, selectionPreview = null } = props;
|
||||||
const { trigger = null, actionDelay = 0, setActionDelay = null } = useWired();
|
const { trigger = null, actionDelay = 0, setActionDelay = null } = useWired();
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
@@ -27,10 +29,10 @@ export const WiredActionBaseView: FC<PropsWithChildren<WiredActionBaseViewProps>
|
|||||||
}, [ trigger, setActionDelay ]);
|
}, [ trigger, setActionDelay ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ save } validate={ validate } wiredType="action" cardStyle={ cardStyle } footer={ footer }>
|
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ save } validate={ validate } wiredType="action" cardStyle={ cardStyle } footer={ footer } footerCollapsible={ footerCollapsible } selectionPreview={ selectionPreview }>
|
||||||
{ children }
|
{ children }
|
||||||
{ !hideDelay && !!children && <hr className="m-0 bg-dark" /> }
|
{ !hideDelay && !!children && <div className="nitro-wired__divider" /> }
|
||||||
{ !hideDelay && <div className="flex flex-col">
|
{ !hideDelay && <div className="flex flex-col nitro-wired__section nitro-wired__section--delay">
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.delay', [ 'seconds' ], [ GetWiredTimeLocale(actionDelay) ]) }</Text>
|
<Text bold>{ LocalizeText('wiredfurni.params.delay', [ 'seconds' ], [ GetWiredTimeLocale(actionDelay) ]) }</Text>
|
||||||
<Slider
|
<Slider
|
||||||
max={ 20 }
|
max={ 20 }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Text } from '../../../../common';
|
|||||||
import { useWired } from '../../../../hooks';
|
import { useWired } from '../../../../hooks';
|
||||||
import { NitroInput } from '../../../../layout';
|
import { NitroInput } from '../../../../layout';
|
||||||
import { WiredActionBaseView } from './WiredActionBaseView';
|
import { WiredActionBaseView } from './WiredActionBaseView';
|
||||||
import { WiredSourceOption, WiredSourcesSelector } from '../WiredSourcesSelector';
|
import { CLICKED_USER_SOURCE_VALUE, WiredSourceOption, WiredSourcesSelector } from '../WiredSourcesSelector';
|
||||||
import { WiredHandItemField } from '../WiredHandItemField';
|
import { WiredHandItemField } from '../WiredHandItemField';
|
||||||
|
|
||||||
const USER_SOURCE_OPTIONS: WiredSourceOption[] = [
|
const USER_SOURCE_OPTIONS: WiredSourceOption[] = [
|
||||||
@@ -20,7 +20,7 @@ const BOT_SOURCE_OPTIONS: WiredSourceOption[] = [
|
|||||||
{ value: 201, label: 'wiredfurni.params.sources.users.201' }
|
{ value: 201, label: 'wiredfurni.params.sources.users.201' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const normalizeUserSource = (value: number) => (USER_SOURCE_OPTIONS.some(option => (option.value === value)) ? value : 0);
|
const normalizeUserSource = (value: number) => ((value === CLICKED_USER_SOURCE_VALUE) || USER_SOURCE_OPTIONS.some(option => (option.value === value)) ? value : 0);
|
||||||
const normalizeBotSource = (value: number, hasBotName = false) => (BOT_SOURCE_OPTIONS.some(option => (option.value === value)) ? value : (hasBotName ? 100 : 0));
|
const normalizeBotSource = (value: number, hasBotName = false) => (BOT_SOURCE_OPTIONS.some(option => (option.value === value)) ? value : (hasBotName ? 100 : 0));
|
||||||
|
|
||||||
export const WiredActionBotGiveHandItemView: FC<{}> = props =>
|
export const WiredActionBotGiveHandItemView: FC<{}> = props =>
|
||||||
@@ -56,7 +56,7 @@ export const WiredActionBotGiveHandItemView: FC<{}> = props =>
|
|||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<WiredSourcesSelector showUsers={ true } userSource={ userSource } userSources={ USER_SOURCE_OPTIONS } onChangeUsers={ setUserSource } />
|
<WiredSourcesSelector showUsers={ true } userSource={ userSource } userSources={ USER_SOURCE_OPTIONS } onChangeUsers={ setUserSource } />
|
||||||
<hr className="m-0 bg-dark" />
|
<hr className="m-0 bg-dark" />
|
||||||
<WiredSourcesSelector showUsers={ true } userSource={ botSource } userSources={ BOT_SOURCE_OPTIONS } usersTitle="wiredfurni.params.sources.users.title.bots" onChangeUsers={ value => setBotSource(normalizeBotSource(value, (botName.length > 0))) } />
|
<WiredSourcesSelector showUsers={ true } userSource={ botSource } userSources={ BOT_SOURCE_OPTIONS } usersTitle="wiredfurni.params.sources.users.title.bots" allowClickedUserSource={ false } onChangeUsers={ value => setBotSource(normalizeBotSource(value, (botName.length > 0))) } />
|
||||||
</div>
|
</div>
|
||||||
}>
|
}>
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
|
import { WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
|
||||||
import { Button, Text } from '../../../../common';
|
|
||||||
import { useWired } from '../../../../hooks';
|
import { useWired } from '../../../../hooks';
|
||||||
import { WiredSourcesSelector, FURNI_SOURCES, WiredSourceOption } from '../WiredSourcesSelector';
|
import { WiredFurniSelectionSourceRow } from '../WiredFurniSelectionSourceRow';
|
||||||
|
import { FURNI_SOURCES, sortWiredSourceOptions, WiredSourceOption } from '../WiredSourcesSelector';
|
||||||
import { WiredActionBaseView } from './WiredActionBaseView';
|
import { WiredActionBaseView } from './WiredActionBaseView';
|
||||||
|
|
||||||
const SOURCE_TRIGGER = 0;
|
const SOURCE_TRIGGER = 0;
|
||||||
@@ -10,12 +10,12 @@ const SOURCE_SELECTED = 100;
|
|||||||
const SOURCE_SECONDARY_SELECTED = 101;
|
const SOURCE_SECONDARY_SELECTED = 101;
|
||||||
const FURNI_DELIMITER = ';';
|
const FURNI_DELIMITER = ';';
|
||||||
|
|
||||||
const TARGET_FURNI_SOURCES: WiredSourceOption[] = [
|
const TARGET_FURNI_SOURCES: WiredSourceOption[] = sortWiredSourceOptions([
|
||||||
{ value: 0, label: 'wiredfurni.params.sources.furni.0' },
|
{ value: 0, label: 'wiredfurni.params.sources.furni.0' },
|
||||||
{ value: SOURCE_SECONDARY_SELECTED, label: 'wiredfurni.params.sources.furni.101' },
|
{ value: SOURCE_SECONDARY_SELECTED, label: 'wiredfurni.params.sources.furni.101' },
|
||||||
{ value: 200, label: 'wiredfurni.params.sources.furni.200' },
|
{ value: 200, label: 'wiredfurni.params.sources.furni.200' },
|
||||||
{ value: 201, label: 'wiredfurni.params.sources.furni.201' }
|
{ value: 201, label: 'wiredfurni.params.sources.furni.201' }
|
||||||
];
|
], 'furni');
|
||||||
|
|
||||||
type SelectionMode = 'move' | 'target';
|
type SelectionMode = 'move' | 'target';
|
||||||
|
|
||||||
@@ -185,49 +185,32 @@ export const WiredActionFurniToFurniView: FC<{}> = () =>
|
|||||||
hasSpecialInput={ true }
|
hasSpecialInput={ true }
|
||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID }
|
||||||
save={ save }
|
save={ save }
|
||||||
footer={
|
selectionPreview={
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<WiredSourcesSelector
|
<WiredFurniSelectionSourceRow
|
||||||
showFurni={ true }
|
title="wiredfurni.params.sources.furni.title.mv.0"
|
||||||
furniTitle="wiredfurni.params.sources.furni.title.mv.0"
|
options={ FURNI_SOURCES }
|
||||||
furniSources={ FURNI_SOURCES }
|
value={ moveSource }
|
||||||
furniSource={ moveSource }
|
selectionKind="primary"
|
||||||
onChangeFurni={ setMoveSource } />
|
selectionActive={ selectionMode === 'move' }
|
||||||
<hr className="m-0 bg-dark" />
|
selectionCount={ moveFurniIds.length }
|
||||||
<WiredSourcesSelector
|
selectionLimit={ selectionLimit }
|
||||||
showFurni={ true }
|
selectionEnabledValues={ [ SOURCE_SELECTED ] }
|
||||||
furniTitle="wiredfurni.params.sources.furni.title.mv.1"
|
onChange={ setMoveSource }
|
||||||
furniSources={ TARGET_FURNI_SOURCES }
|
onSelectionActivate={ () => switchSelection('move') } />
|
||||||
furniSource={ targetSource }
|
<WiredFurniSelectionSourceRow
|
||||||
onChangeFurni={ value => setTargetSource((value === SOURCE_SELECTED) ? SOURCE_SECONDARY_SELECTED : value) } />
|
title="wiredfurni.params.sources.furni.title.mv.1"
|
||||||
|
options={ TARGET_FURNI_SOURCES }
|
||||||
|
value={ targetSource }
|
||||||
|
selectionKind="secondary"
|
||||||
|
selectionActive={ selectionMode === 'target' }
|
||||||
|
selectionCount={ targetFurniIds.length }
|
||||||
|
selectionLimit={ selectionLimit }
|
||||||
|
selectionEnabledValues={ [ SOURCE_SECONDARY_SELECTED ] }
|
||||||
|
onChange={ value => setTargetSource((value === SOURCE_SELECTED) ? SOURCE_SECONDARY_SELECTED : value) }
|
||||||
|
onSelectionActivate={ () => switchSelection('target') } />
|
||||||
</div>
|
</div>
|
||||||
}>
|
}
|
||||||
<div className="flex flex-col gap-3">
|
/>
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.sources.furni.title.mv.0') }</Text>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Button
|
|
||||||
variant={ (selectionMode === 'move') ? 'primary' : 'secondary' }
|
|
||||||
disabled={ moveSource !== SOURCE_SELECTED }
|
|
||||||
onClick={ () => switchSelection('move') }>
|
|
||||||
{ LocalizeText('wiredfurni.params.sources.furni.100') }
|
|
||||||
</Button>
|
|
||||||
<Text small>{ selectionLimit ? `${ moveFurniIds.length }/${ selectionLimit }` : moveFurniIds.length }</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.sources.furni.title.mv.1') }</Text>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Button
|
|
||||||
variant={ (selectionMode === 'target') ? 'primary' : 'secondary' }
|
|
||||||
disabled={ targetSource !== SOURCE_SECONDARY_SELECTED }
|
|
||||||
onClick={ () => switchSelection('target') }>
|
|
||||||
{ LocalizeText('wiredfurni.params.sources.furni.101') }
|
|
||||||
</Button>
|
|
||||||
<Text small>{ selectionLimit ? `${ targetFurniIds.length }/${ selectionLimit }` : targetFurniIds.length }</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</WiredActionBaseView>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ import { WiredExtraFilterFurniView } from '../extras/WiredExtraFilterFurniView';
|
|||||||
import { WiredExtraFilterUserView } from '../extras/WiredExtraFilterUserView';
|
import { WiredExtraFilterUserView } from '../extras/WiredExtraFilterUserView';
|
||||||
import { WiredExtraAnimationTimeView } from '../extras/WiredExtraAnimationTimeView';
|
import { WiredExtraAnimationTimeView } from '../extras/WiredExtraAnimationTimeView';
|
||||||
import { WiredExtraMoveCarryUsersView } from '../extras/WiredExtraMoveCarryUsersView';
|
import { WiredExtraMoveCarryUsersView } from '../extras/WiredExtraMoveCarryUsersView';
|
||||||
|
import { WiredExtraExecuteInOrderView } from '../extras/WiredExtraExecuteInOrderView';
|
||||||
|
import { WiredExtraExecutionLimitView } from '../extras/WiredExtraExecutionLimitView';
|
||||||
import { WiredExtraMoveNoAnimationView } from '../extras/WiredExtraMoveNoAnimationView';
|
import { WiredExtraMoveNoAnimationView } from '../extras/WiredExtraMoveNoAnimationView';
|
||||||
import { WiredExtraMovePhysicsView } from '../extras/WiredExtraMovePhysicsView';
|
import { WiredExtraMovePhysicsView } from '../extras/WiredExtraMovePhysicsView';
|
||||||
import { WiredExtraRandomView } from '../extras/WiredExtraRandomView';
|
import { WiredExtraRandomView } from '../extras/WiredExtraRandomView';
|
||||||
@@ -183,6 +185,10 @@ export const WiredActionLayoutView = (code: number) =>
|
|||||||
return <WiredExtraUnseenView />;
|
return <WiredExtraUnseenView />;
|
||||||
case WiredActionLayoutCode.RANDOM_EXTRA:
|
case WiredActionLayoutCode.RANDOM_EXTRA:
|
||||||
return <WiredExtraRandomView />;
|
return <WiredExtraRandomView />;
|
||||||
|
case WiredActionLayoutCode.EXEC_IN_ORDER_EXTRA:
|
||||||
|
return <WiredExtraExecuteInOrderView />;
|
||||||
|
case WiredActionLayoutCode.EXECUTION_LIMIT_EXTRA:
|
||||||
|
return <WiredExtraExecutionLimitView />;
|
||||||
case WiredActionLayoutCode.SEND_SIGNAL:
|
case WiredActionLayoutCode.SEND_SIGNAL:
|
||||||
return <WiredActionSendSignalView />;
|
return <WiredActionSendSignalView />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
|
import { LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
|
||||||
import { Button, Text } from '../../../../common';
|
import { Text } from '../../../../common';
|
||||||
import { useWired } from '../../../../hooks';
|
import { useWired } from '../../../../hooks';
|
||||||
import { WiredSourcesSelector } from '../WiredSourcesSelector';
|
import { WiredFurniSelectionSourceRow } from '../WiredFurniSelectionSourceRow';
|
||||||
|
import { FURNI_SOURCES, USER_SOURCES } from '../WiredSourcesSelector';
|
||||||
import { WiredActionBaseView } from './WiredActionBaseView';
|
import { WiredActionBaseView } from './WiredActionBaseView';
|
||||||
|
|
||||||
const ANTENNA_INTERACTION_TYPES = [ 'antenna' ];
|
const ANTENNA_INTERACTION_TYPES = [ 'antenna' ];
|
||||||
@@ -184,7 +185,6 @@ export const WiredActionSendSignalView: FC<{}> = () =>
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const selectionLimit = trigger?.maximumItemSelectionCount ?? 0;
|
const selectionLimit = trigger?.maximumItemSelectionCount ?? 0;
|
||||||
const forwardSelectionEnabled = (furniSource === SOURCE_SELECTED);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WiredActionBaseView
|
<WiredActionBaseView
|
||||||
@@ -192,40 +192,48 @@ export const WiredActionSendSignalView: FC<{}> = () =>
|
|||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID }
|
||||||
cardStyle={ { width: '400px' } }
|
cardStyle={ { width: '400px' } }
|
||||||
save={ save }
|
save={ save }
|
||||||
footer={ (
|
selectionPreview={
|
||||||
<WiredSourcesSelector
|
<div className="flex flex-col gap-2">
|
||||||
showFurni={ true }
|
<WiredFurniSelectionSourceRow
|
||||||
showUsers={ true }
|
title="Antenne:"
|
||||||
furniSource={ furniSource }
|
titleIsLiteral={ true }
|
||||||
userSource={ userSource }
|
options={ [ { value: SOURCE_SELECTED, label: 'wiredfurni.params.sources.furni.100' } ] }
|
||||||
onChangeFurni={ onChangeFurniSource }
|
value={ SOURCE_SELECTED }
|
||||||
onChangeUsers={ setUserSource } />
|
selectionKind="primary"
|
||||||
) }>
|
selectionActive={ selectionMode === 'antenna' }
|
||||||
|
selectionCount={ antennaIds.length }
|
||||||
|
selectionLimit={ selectionLimit }
|
||||||
|
selectionEnabledValues={ [ SOURCE_SELECTED ] }
|
||||||
|
onChange={ () => {} }
|
||||||
|
onSelectionActivate={ () => switchSelection('antenna') } />
|
||||||
|
<WiredFurniSelectionSourceRow
|
||||||
|
title="Furni da mandare avanti:"
|
||||||
|
titleIsLiteral={ true }
|
||||||
|
options={ FURNI_SOURCES }
|
||||||
|
value={ furniSource }
|
||||||
|
selectionKind="secondary"
|
||||||
|
selectionActive={ selectionMode === 'furni' }
|
||||||
|
selectionCount={ forwardFurniIds.length }
|
||||||
|
selectionLimit={ selectionLimit }
|
||||||
|
selectionEnabledValues={ [ SOURCE_SELECTED ] }
|
||||||
|
onChange={ onChangeFurniSource }
|
||||||
|
onSelectionActivate={ () => switchSelection('furni') } />
|
||||||
|
<WiredFurniSelectionSourceRow
|
||||||
|
title="Utenti da mandare avanti:"
|
||||||
|
titleIsLiteral={ true }
|
||||||
|
options={ USER_SOURCES }
|
||||||
|
value={ userSource }
|
||||||
|
selectionKind="secondary"
|
||||||
|
selectionActive={ false }
|
||||||
|
selectionCount={ 0 }
|
||||||
|
selectionLimit={ 0 }
|
||||||
|
selectionEnabledValues={ [] }
|
||||||
|
showSelectionToggle={ false }
|
||||||
|
onChange={ setUserSource } />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<Text bold>Antenne selezionate</Text>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Button
|
|
||||||
variant={ (selectionMode === 'antenna') ? 'primary' : 'secondary' }
|
|
||||||
onClick={ () => switchSelection('antenna') }>
|
|
||||||
Antenne
|
|
||||||
</Button>
|
|
||||||
<Text small>{ selectionLimit ? `${ antennaIds.length }/${ selectionLimit }` : antennaIds.length }</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<Text bold>Furni selezionati</Text>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Button
|
|
||||||
variant={ (selectionMode === 'furni') ? 'primary' : 'secondary' }
|
|
||||||
disabled={ !forwardSelectionEnabled }
|
|
||||||
onClick={ () => switchSelection('furni') }>
|
|
||||||
Furni
|
|
||||||
</Button>
|
|
||||||
<Text small>{ selectionLimit ? `${ forwardFurniIds.length }/${ selectionLimit }` : forwardFurniIds.length }</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.signal.options') }</Text>
|
<Text bold>{ LocalizeText('wiredfurni.params.signal.options') }</Text>
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export const WiredConditionActorDirView: FC<{}> = () =>
|
|||||||
hasSpecialInput={ true }
|
hasSpecialInput={ true }
|
||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
||||||
save={ save }
|
save={ save }
|
||||||
|
footerCollapsible={ false }
|
||||||
footer={
|
footer={
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
||||||
|
|||||||
@@ -8,16 +8,18 @@ export interface WiredConditionBaseViewProps
|
|||||||
requiresFurni: number;
|
requiresFurni: number;
|
||||||
save: () => void;
|
save: () => void;
|
||||||
footer?: ReactNode;
|
footer?: ReactNode;
|
||||||
|
footerCollapsible?: boolean;
|
||||||
|
selectionPreview?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WiredConditionBaseView: FC<PropsWithChildren<WiredConditionBaseViewProps>> = props =>
|
export const WiredConditionBaseView: FC<PropsWithChildren<WiredConditionBaseViewProps>> = props =>
|
||||||
{
|
{
|
||||||
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, hasSpecialInput = false, children = null, footer = null } = props;
|
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, hasSpecialInput = false, children = null, footer = null, footerCollapsible = true, selectionPreview = null } = props;
|
||||||
|
|
||||||
const onSave = () => (save && save());
|
const onSave = () => (save && save());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ onSave } wiredType="condition" footer={ footer }>
|
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ onSave } wiredType="condition" footer={ footer } footerCollapsible={ footerCollapsible } selectionPreview={ selectionPreview }>
|
||||||
{ children }
|
{ children }
|
||||||
</WiredBaseView>
|
</WiredBaseView>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
|
import { LocalizeText, WiredFurniType, WiredSelectionVisualizer } from '../../../../api';
|
||||||
import { Button, Text } from '../../../../common';
|
import { Text } from '../../../../common';
|
||||||
import { useWired } from '../../../../hooks';
|
import { useWired } from '../../../../hooks';
|
||||||
import { FURNI_SOURCES, WiredSourceOption, WiredSourcesSelector } from '../WiredSourcesSelector';
|
import { WiredFurniSelectionSourceRow } from '../WiredFurniSelectionSourceRow';
|
||||||
|
import { FURNI_SOURCES, sortWiredSourceOptions, WiredSourceOption } from '../WiredSourcesSelector';
|
||||||
import { WiredConditionBaseView } from './WiredConditionBaseView';
|
import { WiredConditionBaseView } from './WiredConditionBaseView';
|
||||||
|
|
||||||
const SOURCE_TRIGGER = 0;
|
const SOURCE_TRIGGER = 0;
|
||||||
@@ -10,10 +11,10 @@ const SOURCE_SELECTED = 100;
|
|||||||
const SOURCE_SECONDARY_SELECTED = 101;
|
const SOURCE_SECONDARY_SELECTED = 101;
|
||||||
const FURNI_DELIMITER = ';';
|
const FURNI_DELIMITER = ';';
|
||||||
|
|
||||||
const MATCH_FURNI_SOURCES: WiredSourceOption[] = [
|
const MATCH_FURNI_SOURCES: WiredSourceOption[] = sortWiredSourceOptions([
|
||||||
...FURNI_SOURCES,
|
...FURNI_SOURCES,
|
||||||
{ value: SOURCE_SECONDARY_SELECTED, label: 'wiredfurni.params.sources.furni.101' }
|
{ value: SOURCE_SECONDARY_SELECTED, label: 'wiredfurni.params.sources.furni.101' }
|
||||||
];
|
], 'furni');
|
||||||
|
|
||||||
type SelectionMode = 'primary' | 'secondary';
|
type SelectionMode = 'primary' | 'secondary';
|
||||||
|
|
||||||
@@ -194,23 +195,33 @@ export const WiredConditionFurniIsOfTypeView: FC<WiredConditionFurniIsOfTypeView
|
|||||||
hasSpecialInput={ true }
|
hasSpecialInput={ true }
|
||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID_OR_BY_TYPE }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID_OR_BY_TYPE }
|
||||||
save={ save }
|
save={ save }
|
||||||
footer={
|
selectionPreview={
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<WiredSourcesSelector
|
<WiredFurniSelectionSourceRow
|
||||||
showFurni={ true }
|
title="wiredfurni.params.sources.furni.title.match.0"
|
||||||
furniTitle="wiredfurni.params.sources.furni.title.match.0"
|
options={ MATCH_FURNI_SOURCES }
|
||||||
furniSources={ MATCH_FURNI_SOURCES }
|
value={ matchSource }
|
||||||
furniSource={ matchSource }
|
selectionKind="primary"
|
||||||
onChangeFurni={ setMatchSource } />
|
selectionActive={ selectionMode === 'primary' }
|
||||||
<hr className="m-0 bg-dark" />
|
selectionCount={ primaryFurniIds.length }
|
||||||
<WiredSourcesSelector
|
selectionLimit={ selectionLimit }
|
||||||
showFurni={ true }
|
selectionEnabledValues={ [ SOURCE_SELECTED ] }
|
||||||
furniTitle="wiredfurni.params.sources.furni.title.match.1"
|
onChange={ setMatchSource }
|
||||||
furniSources={ MATCH_FURNI_SOURCES }
|
onSelectionActivate={ () => switchSelection('primary') } />
|
||||||
furniSource={ compareSource }
|
<WiredFurniSelectionSourceRow
|
||||||
onChangeFurni={ setCompareSource } />
|
title="wiredfurni.params.sources.furni.title.match.1"
|
||||||
|
options={ MATCH_FURNI_SOURCES }
|
||||||
|
value={ compareSource }
|
||||||
|
selectionKind="secondary"
|
||||||
|
selectionActive={ selectionMode === 'secondary' }
|
||||||
|
selectionCount={ secondaryFurniIds.length }
|
||||||
|
selectionLimit={ selectionLimit }
|
||||||
|
selectionEnabledValues={ [ SOURCE_SECONDARY_SELECTED ] }
|
||||||
|
onChange={ setCompareSource }
|
||||||
|
onSelectionActivate={ () => switchSelection('secondary') } />
|
||||||
</div>
|
</div>
|
||||||
}>
|
}
|
||||||
|
>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.quantifier_selection') }</Text>
|
<Text bold>{ LocalizeText('wiredfurni.params.quantifier_selection') }</Text>
|
||||||
{ [ 0, 1 ].map(value => (
|
{ [ 0, 1 ].map(value => (
|
||||||
@@ -220,32 +231,6 @@ export const WiredConditionFurniIsOfTypeView: FC<WiredConditionFurniIsOfTypeView
|
|||||||
</label>
|
</label>
|
||||||
)) }
|
)) }
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-3">
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.sources.furni.title.match.0') }</Text>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Button
|
|
||||||
variant={ (selectionMode === 'primary') ? 'primary' : 'secondary' }
|
|
||||||
disabled={ matchSource !== SOURCE_SELECTED && compareSource !== SOURCE_SELECTED }
|
|
||||||
onClick={ () => switchSelection('primary') }>
|
|
||||||
{ LocalizeText('wiredfurni.params.sources.furni.100') }
|
|
||||||
</Button>
|
|
||||||
<Text small>{ selectionLimit ? `${ primaryFurniIds.length }/${ selectionLimit }` : primaryFurniIds.length }</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.sources.furni.title.match.1') }</Text>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Button
|
|
||||||
variant={ (selectionMode === 'secondary') ? 'primary' : 'secondary' }
|
|
||||||
disabled={ matchSource !== SOURCE_SECONDARY_SELECTED && compareSource !== SOURCE_SECONDARY_SELECTED }
|
|
||||||
onClick={ () => switchSelection('secondary') }>
|
|
||||||
{ LocalizeText('wiredfurni.params.sources.furni.101') }
|
|
||||||
</Button>
|
|
||||||
<Text small>{ selectionLimit ? `${ secondaryFurniIds.length }/${ selectionLimit }` : secondaryFurniIds.length }</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</WiredConditionBaseView>
|
</WiredConditionBaseView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ export const WiredConditionHasAltitudeView: FC<{}> = () =>
|
|||||||
hasSpecialInput={ true }
|
hasSpecialInput={ true }
|
||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID_BY_TYPE_OR_FROM_CONTEXT }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID_BY_TYPE_OR_FROM_CONTEXT }
|
||||||
save={ save }
|
save={ save }
|
||||||
|
footerCollapsible={ false }
|
||||||
footer={
|
footer={
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { FaChevronLeft, FaChevronRight } from 'react-icons/fa';
|
|||||||
import { LocalizeText, WiredFurniType } from '../../../../api';
|
import { LocalizeText, WiredFurniType } from '../../../../api';
|
||||||
import { Button, Slider, Text } from '../../../../common';
|
import { Button, Slider, Text } from '../../../../common';
|
||||||
import { useWired } from '../../../../hooks';
|
import { useWired } from '../../../../hooks';
|
||||||
|
import { sortWiredSourceOptions, useAvailableUserSources } from '../WiredSourcesSelector';
|
||||||
import { WiredConditionBaseView } from './WiredConditionBaseView';
|
import { WiredConditionBaseView } from './WiredConditionBaseView';
|
||||||
|
|
||||||
const SOURCE_GROUP_USERS = 0;
|
const SOURCE_GROUP_USERS = 0;
|
||||||
@@ -18,11 +19,11 @@ const USER_SOURCES = [
|
|||||||
{ value: 201, label: 'wiredfurni.params.sources.users.201' }
|
{ value: 201, label: 'wiredfurni.params.sources.users.201' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const FURNI_SOURCES = [
|
const FURNI_SOURCES = sortWiredSourceOptions([
|
||||||
{ value: 0, label: 'wiredfurni.params.sources.furni.0' },
|
{ value: 0, label: 'wiredfurni.params.sources.furni.0' },
|
||||||
{ value: 200, label: 'wiredfurni.params.sources.furni.200' },
|
{ value: 200, label: 'wiredfurni.params.sources.furni.200' },
|
||||||
{ value: 201, label: 'wiredfurni.params.sources.furni.201' }
|
{ value: 201, label: 'wiredfurni.params.sources.furni.201' }
|
||||||
];
|
], 'furni');
|
||||||
|
|
||||||
const clampQuantity = (value: number) =>
|
const clampQuantity = (value: number) =>
|
||||||
{
|
{
|
||||||
@@ -39,6 +40,7 @@ const normalizeSource = (value: number, allowed: number[]) =>
|
|||||||
export const WiredConditionSelectionQuantityView: FC<{}> = () =>
|
export const WiredConditionSelectionQuantityView: FC<{}> = () =>
|
||||||
{
|
{
|
||||||
const { trigger = null, setIntParams = null, setStringParam = null } = useWired();
|
const { trigger = null, setIntParams = null, setStringParam = null } = useWired();
|
||||||
|
const availableUserSources = sortWiredSourceOptions(useAvailableUserSources(trigger, USER_SOURCES), 'users');
|
||||||
const [ comparison, setComparison ] = useState(1);
|
const [ comparison, setComparison ] = useState(1);
|
||||||
const [ quantity, setQuantity ] = useState(0);
|
const [ quantity, setQuantity ] = useState(0);
|
||||||
const [ quantityInput, setQuantityInput ] = useState('0');
|
const [ quantityInput, setQuantityInput ] = useState('0');
|
||||||
@@ -59,11 +61,11 @@ export const WiredConditionSelectionQuantityView: FC<{}> = () =>
|
|||||||
setQuantity(nextQuantity);
|
setQuantity(nextQuantity);
|
||||||
setQuantityInput(nextQuantity.toString());
|
setQuantityInput(nextQuantity.toString());
|
||||||
setSourceGroup(nextSourceGroup);
|
setSourceGroup(nextSourceGroup);
|
||||||
setUserSource(nextSourceGroup === SOURCE_GROUP_USERS ? normalizeSource(nextSourceType, USER_SOURCES.map(source => source.value)) : 0);
|
setUserSource(nextSourceGroup === SOURCE_GROUP_USERS ? normalizeSource(nextSourceType, availableUserSources.map(source => source.value)) : 0);
|
||||||
setFurniSource(nextSourceGroup === SOURCE_GROUP_FURNI ? normalizeSource(nextSourceType, FURNI_SOURCES.map(source => source.value)) : 0);
|
setFurniSource(nextSourceGroup === SOURCE_GROUP_FURNI ? normalizeSource(nextSourceType, FURNI_SOURCES.map(source => source.value)) : 0);
|
||||||
}, [ trigger ]);
|
}, [ availableUserSources, trigger ]);
|
||||||
|
|
||||||
const activeSources = useMemo(() => (sourceGroup === SOURCE_GROUP_FURNI) ? FURNI_SOURCES : USER_SOURCES, [ sourceGroup ]);
|
const activeSources = useMemo(() => (sourceGroup === SOURCE_GROUP_FURNI) ? FURNI_SOURCES : availableUserSources, [ availableUserSources, sourceGroup ]);
|
||||||
const activeSource = (sourceGroup === SOURCE_GROUP_FURNI) ? furniSource : userSource;
|
const activeSource = (sourceGroup === SOURCE_GROUP_FURNI) ? furniSource : userSource;
|
||||||
const activeSourceIndex = Math.max(0, activeSources.findIndex(source => source.value === activeSource));
|
const activeSourceIndex = Math.max(0, activeSources.findIndex(source => source.value === activeSource));
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export const WiredConditionTeamHasRankView: FC<{}> = () =>
|
|||||||
hasSpecialInput={ true }
|
hasSpecialInput={ true }
|
||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
||||||
save={ save }
|
save={ save }
|
||||||
|
footerCollapsible={ false }
|
||||||
footer={
|
footer={
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export const WiredConditionTeamHasScoreView: FC<{}> = () =>
|
|||||||
hasSpecialInput={ true }
|
hasSpecialInput={ true }
|
||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
||||||
save={ save }
|
save={ save }
|
||||||
|
footerCollapsible={ false }
|
||||||
footer={
|
footer={
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export const WiredConditionTriggererMatchView: FC<WiredConditionTriggererMatchVi
|
|||||||
hasSpecialInput={ true }
|
hasSpecialInput={ true }
|
||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
||||||
save={ save }
|
save={ save }
|
||||||
|
footerCollapsible={ false }
|
||||||
footer={
|
footer={
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ export const WiredConditionUserPerformsActionView: FC<WiredConditionUserPerforms
|
|||||||
hasSpecialInput={ true }
|
hasSpecialInput={ true }
|
||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
||||||
save={ save }
|
save={ save }
|
||||||
|
footerCollapsible={ false }
|
||||||
footer={
|
footer={
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
<button className="btn btn-link p-0 align-self-start" type="button" onClick={ () => setShowAdvanced(value => !value) }>
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ export interface WiredExtraBaseViewProps
|
|||||||
validate?: () => boolean;
|
validate?: () => boolean;
|
||||||
cardStyle?: CSSProperties;
|
cardStyle?: CSSProperties;
|
||||||
footer?: ReactNode;
|
footer?: ReactNode;
|
||||||
|
footerCollapsible?: boolean;
|
||||||
|
selectionPreview?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WiredExtraBaseView: FC<PropsWithChildren<WiredExtraBaseViewProps>> = props =>
|
export const WiredExtraBaseView: FC<PropsWithChildren<WiredExtraBaseViewProps>> = props =>
|
||||||
{
|
{
|
||||||
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, validate = null, hasSpecialInput = false, children = null, cardStyle = undefined, footer = null } = props;
|
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, validate = null, hasSpecialInput = false, children = null, cardStyle = undefined, footer = null, footerCollapsible = true, selectionPreview = null } = props;
|
||||||
const { trigger = null, setActionDelay = null } = useWired();
|
const { trigger = null, setActionDelay = null } = useWired();
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
@@ -25,7 +27,7 @@ export const WiredExtraBaseView: FC<PropsWithChildren<WiredExtraBaseViewProps>>
|
|||||||
}, [ trigger, setActionDelay ]);
|
}, [ trigger, setActionDelay ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ save } validate={ validate } wiredType="extra" cardStyle={ cardStyle } footer={ footer }>
|
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ save } validate={ validate } wiredType="extra" cardStyle={ cardStyle } footer={ footer } footerCollapsible={ footerCollapsible } selectionPreview={ selectionPreview }>
|
||||||
{ children }
|
{ children }
|
||||||
</WiredBaseView>
|
</WiredBaseView>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { WiredFurniType } from '../../../../api';
|
||||||
|
import { useWired } from '../../../../hooks';
|
||||||
|
import { WiredExtraBaseView } from './WiredExtraBaseView';
|
||||||
|
|
||||||
|
export const WiredExtraExecuteInOrderView: FC<{}> = () =>
|
||||||
|
{
|
||||||
|
const { setIntParams = null, setStringParam = null } = useWired();
|
||||||
|
|
||||||
|
const save = () =>
|
||||||
|
{
|
||||||
|
setIntParams([]);
|
||||||
|
setStringParam('');
|
||||||
|
};
|
||||||
|
|
||||||
|
return <WiredExtraBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save } cardStyle={ { width: 320 } } />;
|
||||||
|
};
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { FC, useEffect, useState } from 'react';
|
||||||
|
import { LocalizeText, WiredFurniType } from '../../../../api';
|
||||||
|
import { Slider, Text } from '../../../../common';
|
||||||
|
import { useWired } from '../../../../hooks';
|
||||||
|
import { WiredExtraBaseView } from './WiredExtraBaseView';
|
||||||
|
|
||||||
|
const MIN_EXECUTIONS = 1;
|
||||||
|
const MAX_EXECUTIONS = 100;
|
||||||
|
const DEFAULT_EXECUTIONS = 1;
|
||||||
|
const MIN_TIME_WINDOW_MS = 1000;
|
||||||
|
const MAX_TIME_WINDOW_MS = 10000;
|
||||||
|
const DEFAULT_TIME_WINDOW_MS = 1000;
|
||||||
|
const TIME_WINDOW_STEP_MS = 500;
|
||||||
|
|
||||||
|
const normalizeExecutions = (value: number) =>
|
||||||
|
{
|
||||||
|
if(isNaN(value)) return DEFAULT_EXECUTIONS;
|
||||||
|
|
||||||
|
return Math.max(MIN_EXECUTIONS, Math.min(MAX_EXECUTIONS, Math.round(value)));
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalizeTimeWindow = (value: number) =>
|
||||||
|
{
|
||||||
|
if(isNaN(value)) return DEFAULT_TIME_WINDOW_MS;
|
||||||
|
|
||||||
|
const clampedValue = Math.max(MIN_TIME_WINDOW_MS, Math.min(MAX_TIME_WINDOW_MS, value));
|
||||||
|
|
||||||
|
return Math.round(clampedValue / TIME_WINDOW_STEP_MS) * TIME_WINDOW_STEP_MS;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatTimeWindow = (value: number) =>
|
||||||
|
{
|
||||||
|
const seconds = value / 1000;
|
||||||
|
|
||||||
|
return Number.isInteger(seconds) ? seconds.toString() : seconds.toFixed(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WiredExtraExecutionLimitView: FC<{}> = () =>
|
||||||
|
{
|
||||||
|
const { trigger = null, setIntParams = null, setStringParam = null } = useWired();
|
||||||
|
const [ executions, setExecutions ] = useState(DEFAULT_EXECUTIONS);
|
||||||
|
const [ timeWindowMs, setTimeWindowMs ] = useState(DEFAULT_TIME_WINDOW_MS);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!trigger) return;
|
||||||
|
|
||||||
|
setExecutions(normalizeExecutions((trigger.intData.length > 0) ? trigger.intData[0] : DEFAULT_EXECUTIONS));
|
||||||
|
setTimeWindowMs(normalizeTimeWindow((trigger.intData.length > 1) ? trigger.intData[1] : DEFAULT_TIME_WINDOW_MS));
|
||||||
|
}, [ trigger ]);
|
||||||
|
|
||||||
|
const save = () =>
|
||||||
|
{
|
||||||
|
setIntParams([ normalizeExecutions(executions), normalizeTimeWindow(timeWindowMs) ]);
|
||||||
|
setStringParam('');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WiredExtraBaseView hasSpecialInput={ true } requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save } cardStyle={ { width: 380 } }>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Text>{ LocalizeText('wiredfurni.params.setexecutions', [ 'amount' ], [ executions.toString() ]) }</Text>
|
||||||
|
<Slider
|
||||||
|
min={ MIN_EXECUTIONS }
|
||||||
|
max={ MAX_EXECUTIONS }
|
||||||
|
step={ 1 }
|
||||||
|
value={ executions }
|
||||||
|
onChange={ value => setExecutions(normalizeExecutions(Array.isArray(value) ? value[0] : Number(value))) } />
|
||||||
|
<Text small>{ executions }</Text>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Text>{ LocalizeText('wiredfurni.params.settimewindow', [ 'timewindow' ], [ formatTimeWindow(timeWindowMs) ]) }</Text>
|
||||||
|
<Slider
|
||||||
|
min={ MIN_TIME_WINDOW_MS }
|
||||||
|
max={ MAX_TIME_WINDOW_MS }
|
||||||
|
step={ TIME_WINDOW_STEP_MS }
|
||||||
|
value={ timeWindowMs }
|
||||||
|
onChange={ value => setTimeWindowMs(normalizeTimeWindow(Array.isArray(value) ? value[0] : Number(value))) } />
|
||||||
|
<Text small>{ formatTimeWindow(timeWindowMs) }s</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WiredExtraBaseView>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -45,7 +45,7 @@ export const WiredExtraMoveCarryUsersView: FC<{}> = () =>
|
|||||||
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE }
|
||||||
save={ save }
|
save={ save }
|
||||||
cardStyle={ { width: 420 } }
|
cardStyle={ { width: 420 } }
|
||||||
footer={ <WiredSourcesSelector showUsers={ true } userSource={ userSource } userSources={ USER_SOURCES } usersTitle="wiredfurni.params.sources.users.title.carry" onChangeUsers={ value => setUserSource(normalizeUserSource(value)) } /> }>
|
footer={ <WiredSourcesSelector showUsers={ true } userSource={ userSource } userSources={ USER_SOURCES } usersTitle="wiredfurni.params.sources.users.title.carry" allowClickedUserSource={ false } onChangeUsers={ value => setUserSource(normalizeUserSource(value)) } /> }>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<Text bold>{ LocalizeText('wiredfurni.params.carry_mode') }</Text>
|
<Text bold>{ LocalizeText('wiredfurni.params.carry_mode') }</Text>
|
||||||
<label className="flex items-center gap-1 cursor-pointer">
|
<label className="flex items-center gap-1 cursor-pointer">
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ export const WiredExtraMovePhysicsView: FC<{}> = () =>
|
|||||||
userSource={ moveThroughUsersSource }
|
userSource={ moveThroughUsersSource }
|
||||||
userSources={ USER_SOURCES }
|
userSources={ USER_SOURCES }
|
||||||
usersTitle="wiredfurni.params.sources.users.title.physics.0"
|
usersTitle="wiredfurni.params.sources.users.title.physics.0"
|
||||||
|
allowClickedUserSource={ false }
|
||||||
onChangeUsers={ value => setMoveThroughUsersSource(normalizeSource(value, USER_SOURCES)) } /> }
|
onChangeUsers={ value => setMoveThroughUsersSource(normalizeSource(value, USER_SOURCES)) } /> }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,14 +11,16 @@ export interface WiredSelectorBaseViewProps
|
|||||||
cardStyle?: CSSProperties;
|
cardStyle?: CSSProperties;
|
||||||
hideDelay?: boolean;
|
hideDelay?: boolean;
|
||||||
footer?: ReactNode;
|
footer?: ReactNode;
|
||||||
|
footerCollapsible?: boolean;
|
||||||
|
selectionPreview?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WiredSelectorBaseView: FC<PropsWithChildren<WiredSelectorBaseViewProps>> = props =>
|
export const WiredSelectorBaseView: FC<PropsWithChildren<WiredSelectorBaseViewProps>> = props =>
|
||||||
{
|
{
|
||||||
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, validate = null, hasSpecialInput = false, children = null, cardStyle = undefined, footer = null } = props;
|
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, validate = null, hasSpecialInput = false, children = null, cardStyle = undefined, footer = null, footerCollapsible = true, selectionPreview = null } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ save } validate={ validate } wiredType="selector" cardStyle={ cardStyle } footer={ footer }>
|
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ save } validate={ validate } wiredType="selector" cardStyle={ cardStyle } footer={ footer } footerCollapsible={ footerCollapsible } selectionPreview={ selectionPreview }>
|
||||||
{ children }
|
{ children }
|
||||||
</WiredBaseView>
|
</WiredBaseView>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { MdGridOn } from 'react-icons/md';
|
|||||||
import { LocalizeText, WiredFurniType } from '../../../../api';
|
import { LocalizeText, WiredFurniType } from '../../../../api';
|
||||||
import { Button, Text } from '../../../../common';
|
import { Button, Text } from '../../../../common';
|
||||||
import { useWired } from '../../../../hooks';
|
import { useWired } from '../../../../hooks';
|
||||||
|
import { sortWiredSourceOptions } from '../WiredSourcesSelector';
|
||||||
import { WiredSelectorBaseView } from './WiredSelectorBaseView';
|
import { WiredSelectorBaseView } from './WiredSelectorBaseView';
|
||||||
|
|
||||||
const SOURCE_USER_TRIGGER = 0;
|
const SOURCE_USER_TRIGGER = 0;
|
||||||
@@ -14,17 +15,17 @@ const SOURCE_FURNI_TRIGGER = 3;
|
|||||||
const SOURCE_FURNI_PICKED = 4;
|
const SOURCE_FURNI_PICKED = 4;
|
||||||
const SOURCE_FURNI_SIGNAL = 5;
|
const SOURCE_FURNI_SIGNAL = 5;
|
||||||
|
|
||||||
const USER_SOURCES = [
|
const USER_SOURCES = sortWiredSourceOptions([
|
||||||
{ value: SOURCE_USER_TRIGGER, label: 'wiredfurni.params.sources.users.0' },
|
{ value: SOURCE_USER_TRIGGER, label: 'wiredfurni.params.sources.users.0' },
|
||||||
{ value: SOURCE_USER_SIGNAL, label: 'wiredfurni.params.sources.users.201' },
|
{ value: SOURCE_USER_SIGNAL, label: 'wiredfurni.params.sources.users.201' },
|
||||||
{ value: SOURCE_USER_CLICKED, label: 'wiredfurni.params.sources.users.11' },
|
{ value: SOURCE_USER_CLICKED, label: 'wiredfurni.params.sources.users.11' },
|
||||||
];
|
], 'users');
|
||||||
|
|
||||||
const FURNI_SOURCES = [
|
const FURNI_SOURCES = sortWiredSourceOptions([
|
||||||
{ value: SOURCE_FURNI_TRIGGER, label: 'wiredfurni.params.sources.furni.0' },
|
{ value: SOURCE_FURNI_TRIGGER, label: 'wiredfurni.params.sources.furni.0' },
|
||||||
{ value: SOURCE_FURNI_PICKED, label: 'wiredfurni.params.sources.furni.100' },
|
{ value: SOURCE_FURNI_PICKED, label: 'wiredfurni.params.sources.furni.100' },
|
||||||
{ value: SOURCE_FURNI_SIGNAL, label: 'wiredfurni.params.sources.furni.201' },
|
{ value: SOURCE_FURNI_SIGNAL, label: 'wiredfurni.params.sources.furni.201' },
|
||||||
];
|
], 'furni');
|
||||||
|
|
||||||
const TILE_W = 22;
|
const TILE_W = 22;
|
||||||
const TILE_H = 11;
|
const TILE_H = 11;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { MdGridOn } from 'react-icons/md';
|
|||||||
import { LocalizeText, WiredFurniType } from '../../../../api';
|
import { LocalizeText, WiredFurniType } from '../../../../api';
|
||||||
import { Button, Text } from '../../../../common';
|
import { Button, Text } from '../../../../common';
|
||||||
import { useWired } from '../../../../hooks';
|
import { useWired } from '../../../../hooks';
|
||||||
|
import { sortWiredSourceOptions } from '../WiredSourcesSelector';
|
||||||
import { WiredSelectorBaseView } from './WiredSelectorBaseView';
|
import { WiredSelectorBaseView } from './WiredSelectorBaseView';
|
||||||
|
|
||||||
const SOURCE_USER_TRIGGER = 0;
|
const SOURCE_USER_TRIGGER = 0;
|
||||||
@@ -14,17 +15,17 @@ const SOURCE_FURNI_TRIGGER = 3;
|
|||||||
const SOURCE_FURNI_PICKED = 4;
|
const SOURCE_FURNI_PICKED = 4;
|
||||||
const SOURCE_FURNI_SIGNAL = 5;
|
const SOURCE_FURNI_SIGNAL = 5;
|
||||||
|
|
||||||
const USER_SOURCES = [
|
const USER_SOURCES = sortWiredSourceOptions([
|
||||||
{ value: SOURCE_USER_TRIGGER, label: 'wiredfurni.params.sources.users.0' },
|
{ value: SOURCE_USER_TRIGGER, label: 'wiredfurni.params.sources.users.0' },
|
||||||
{ value: SOURCE_USER_SIGNAL, label: 'wiredfurni.params.sources.users.201' },
|
{ value: SOURCE_USER_SIGNAL, label: 'wiredfurni.params.sources.users.201' },
|
||||||
{ value: SOURCE_USER_CLICKED, label: 'wiredfurni.params.sources.users.11' },
|
{ value: SOURCE_USER_CLICKED, label: 'wiredfurni.params.sources.users.11' },
|
||||||
];
|
], 'users');
|
||||||
|
|
||||||
const FURNI_SOURCES = [
|
const FURNI_SOURCES = sortWiredSourceOptions([
|
||||||
{ value: SOURCE_FURNI_TRIGGER, label: 'wiredfurni.params.sources.furni.0' },
|
{ value: SOURCE_FURNI_TRIGGER, label: 'wiredfurni.params.sources.furni.0' },
|
||||||
{ value: SOURCE_FURNI_PICKED, label: 'wiredfurni.params.sources.furni.100' },
|
{ value: SOURCE_FURNI_PICKED, label: 'wiredfurni.params.sources.furni.100' },
|
||||||
{ value: SOURCE_FURNI_SIGNAL, label: 'wiredfurni.params.sources.furni.201' },
|
{ value: SOURCE_FURNI_SIGNAL, label: 'wiredfurni.params.sources.furni.201' },
|
||||||
];
|
], 'furni');
|
||||||
|
|
||||||
const TILE_W = 22;
|
const TILE_W = 22;
|
||||||
const TILE_H = 11;
|
const TILE_H = 11;
|
||||||
|
|||||||
@@ -8,16 +8,18 @@ export interface WiredTriggerBaseViewProps
|
|||||||
requiresFurni: number;
|
requiresFurni: number;
|
||||||
save: () => void;
|
save: () => void;
|
||||||
footer?: ReactNode;
|
footer?: ReactNode;
|
||||||
|
footerCollapsible?: boolean;
|
||||||
|
selectionPreview?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WiredTriggerBaseView: FC<PropsWithChildren<WiredTriggerBaseViewProps>> = props =>
|
export const WiredTriggerBaseView: FC<PropsWithChildren<WiredTriggerBaseViewProps>> = props =>
|
||||||
{
|
{
|
||||||
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, hasSpecialInput = false, children = null, footer = null } = props;
|
const { requiresFurni = WiredFurniType.STUFF_SELECTION_OPTION_NONE, save = null, hasSpecialInput = false, children = null, footer = null, footerCollapsible = true, selectionPreview = null } = props;
|
||||||
|
|
||||||
const onSave = () => (save && save());
|
const onSave = () => (save && save());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ onSave } wiredType="trigger" footer={ footer }>
|
<WiredBaseView hasSpecialInput={ hasSpecialInput } requiresFurni={ requiresFurni } save={ onSave } wiredType="trigger" footer={ footer } footerCollapsible={ footerCollapsible } selectionPreview={ selectionPreview }>
|
||||||
{ children }
|
{ children }
|
||||||
</WiredBaseView>
|
</WiredBaseView>
|
||||||
);
|
);
|
||||||
|
|||||||
+267
-1
@@ -799,6 +799,272 @@ body {
|
|||||||
background-color: #185d79; /* Match bg-card-header */
|
background-color: #185d79; /* Match bg-card-header */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nitro-wired {
|
||||||
|
background: #d5d5d5;
|
||||||
|
border: 1px solid #8f8f8f !important;
|
||||||
|
border-radius: 6px !important;
|
||||||
|
box-shadow: inset 0 1px 0 #ffffff, 0 2px 0 rgba(0, 0, 0, 0.18) !important;
|
||||||
|
color: #000;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.nitro-wired__header {
|
||||||
|
min-height: 22px !important;
|
||||||
|
max-height: 22px !important;
|
||||||
|
background: linear-gradient(180deg, #f1f1f1 0%, #dfdfdf 45%, #c8c8c8 46%, #d7d7d7 100%) !important;
|
||||||
|
border-bottom: 1px solid #9b9b9b;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95) !important;
|
||||||
|
padding-top: 0 !important;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #000 !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
font-weight: 700;
|
||||||
|
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.85) !important;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ubuntu-close-button {
|
||||||
|
transform: scale(0.82);
|
||||||
|
transform-origin: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__content {
|
||||||
|
background: #d9d9d9 !important;
|
||||||
|
padding: 4px !important;
|
||||||
|
gap: 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__section .font-bold {
|
||||||
|
width: 100%;
|
||||||
|
font-weight: 400 !important;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__summary-description,
|
||||||
|
.nitro-wired__furni-selector-description,
|
||||||
|
.nitro-wired__picker-label {
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__divider,
|
||||||
|
hr {
|
||||||
|
height: 1px;
|
||||||
|
border: 0;
|
||||||
|
background: #a6a6a6;
|
||||||
|
box-shadow: 0 1px 0 #f8f8f8;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-check-input,
|
||||||
|
input[type='checkbox'],
|
||||||
|
input[type='radio'] {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
min-width: 18px;
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
border: 1px solid #8e8e8e;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: linear-gradient(180deg, #fcfcfc 0%, #ececec 100%);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9);
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='radio'] {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-check-input:focus,
|
||||||
|
input[type='checkbox']:focus,
|
||||||
|
input[type='radio']:focus {
|
||||||
|
outline: 1px solid #4b7ea1;
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-check-input[type='radio']:checked,
|
||||||
|
input[type='radio']:checked {
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at center, #4a4a4a 0 34%, transparent 38%),
|
||||||
|
linear-gradient(180deg, #fcfcfc 0%, #ececec 100%);
|
||||||
|
border-color: #767676;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-check-input[type='checkbox']:checked,
|
||||||
|
input[type='checkbox']:checked {
|
||||||
|
background:
|
||||||
|
linear-gradient(135deg, transparent 0 46%, #ffffff 46% 54%, transparent 54% 100%),
|
||||||
|
linear-gradient(45deg, transparent 0 30%, #4a4a4a 30% 42%, transparent 42% 100%),
|
||||||
|
linear-gradient(180deg, #d9d9d9 0%, #c8c8c8 100%);
|
||||||
|
border-color: #767676;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control,
|
||||||
|
input[type='text'],
|
||||||
|
input[type='number'],
|
||||||
|
textarea {
|
||||||
|
min-height: 24px;
|
||||||
|
border: 1px solid #8d8d8d !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
background: #f6f6f6 !important;
|
||||||
|
color: #000 !important;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95);
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 3px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__button,
|
||||||
|
.nitro-wired__picker-button,
|
||||||
|
.nitro-slider-button {
|
||||||
|
display: inline-flex !important;
|
||||||
|
align-items: center !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
min-height: 20px !important;
|
||||||
|
border: 1px solid #8e8e8e !important;
|
||||||
|
border-radius: 5px !important;
|
||||||
|
background: linear-gradient(180deg, #f6f6f6 0%, #e4e4e4 49%, #d0d0d0 50%, #ececec 100%) !important;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.92) !important;
|
||||||
|
color: #000 !important;
|
||||||
|
padding-top: 0 !important;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__button:hover,
|
||||||
|
.nitro-wired__picker-button:hover,
|
||||||
|
.nitro-slider-button:hover {
|
||||||
|
filter: brightness(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__button--primary,
|
||||||
|
.nitro-wired__button--secondary {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-slider-wrapper {
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__advanced-toggle {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 !important;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: #000;
|
||||||
|
font: inherit;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__advanced-body,
|
||||||
|
.nitro-wired__source-detail {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__source-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__selection-toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid #8e8e8e;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: linear-gradient(180deg, #f6f6f6 0%, #e4e4e4 49%, #d0d0d0 50%, #ececec 100%);
|
||||||
|
color: #7b7b7b;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__selection-toggle.is-active.nitro-wired__selection-toggle--primary {
|
||||||
|
border-color: #66793c;
|
||||||
|
background: linear-gradient(180deg, #a5b56e 0%, #8ea25a 100%);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__selection-toggle.is-active.nitro-wired__selection-toggle--secondary {
|
||||||
|
border-color: #6172b7;
|
||||||
|
background: linear-gradient(180deg, #8d9bdd 0%, #7383cb 100%);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__selection-toggle:disabled {
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__selection-toggle svg {
|
||||||
|
font-size: 10px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__actions {
|
||||||
|
gap: 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__picker-button,
|
||||||
|
.nitro-slider-button {
|
||||||
|
width: 22px;
|
||||||
|
min-width: 22px !important;
|
||||||
|
flex: 0 0 22px;
|
||||||
|
padding-left: 0 !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__picker-button svg,
|
||||||
|
.nitro-slider-button svg {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-wired__picker-label {
|
||||||
|
min-width: 0;
|
||||||
|
text-align: center;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-slider {
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-slider .track {
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid #9a9a9a;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95);
|
||||||
|
|
||||||
|
&.track-0 {
|
||||||
|
background: linear-gradient(180deg, #7f9fb1 0%, #64889e 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.track-1 {
|
||||||
|
background: linear-gradient(180deg, #e9e9e9 0%, #d5d5d5 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-slider .thumb {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
margin-top: 3px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid #7f7f7f;
|
||||||
|
background: linear-gradient(180deg, #fefefe 0%, #dadada 100%);
|
||||||
|
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.85), inset 0 1px 0 rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Avatar Editor ─────────────────────────────────────────────────────── */
|
/* ── Avatar Editor ─────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
.color-picker-frame {
|
.color-picker-frame {
|
||||||
@@ -954,4 +1220,4 @@ body {
|
|||||||
z-index: 5;
|
z-index: 5;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-23
@@ -1,17 +1,20 @@
|
|||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { existsSync } from 'fs';
|
||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||||
|
|
||||||
const renderer3 = resolve(__dirname, '..', 'renderer3');
|
const legacyRendererRoot = resolve(__dirname, '..', 'renderer3');
|
||||||
|
const currentRendererRoot = resolve(__dirname, '..', 'Nitro_Render_V3');
|
||||||
|
const rendererRoot = existsSync(currentRendererRoot) ? currentRendererRoot : legacyRendererRoot;
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [ react(), tsconfigPaths() ],
|
plugins: [ react(), tsconfigPaths() ],
|
||||||
server: {
|
server: {
|
||||||
fs: {
|
fs: {
|
||||||
allow: [
|
allow: [
|
||||||
resolve(__dirname), // nitro3 itself
|
resolve(__dirname),
|
||||||
renderer3, // renderer3 source + packages
|
rendererRoot,
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
proxy: {
|
proxy: {
|
||||||
@@ -25,24 +28,22 @@ export default defineConfig({
|
|||||||
alias: {
|
alias: {
|
||||||
'@': resolve(__dirname, 'src'),
|
'@': resolve(__dirname, 'src'),
|
||||||
'~': resolve(__dirname, 'node_modules'),
|
'~': resolve(__dirname, 'node_modules'),
|
||||||
// Renderer3 workspace packages → point to their src/index.ts
|
'@nitrots/api': resolve(rendererRoot, 'packages/api/src/index.ts'),
|
||||||
'@nitrots/api': resolve(renderer3, 'packages/api/src/index.ts'),
|
'@nitrots/assets': resolve(rendererRoot, 'packages/assets/src/index.ts'),
|
||||||
'@nitrots/assets': resolve(renderer3, 'packages/assets/src/index.ts'),
|
'@nitrots/avatar': resolve(rendererRoot, 'packages/avatar/src/index.ts'),
|
||||||
'@nitrots/avatar': resolve(renderer3, 'packages/avatar/src/index.ts'),
|
'@nitrots/camera': resolve(rendererRoot, 'packages/camera/src/index.ts'),
|
||||||
'@nitrots/camera': resolve(renderer3, 'packages/camera/src/index.ts'),
|
'@nitrots/communication': resolve(rendererRoot, 'packages/communication/src/index.ts'),
|
||||||
'@nitrots/communication': resolve(renderer3, 'packages/communication/src/index.ts'),
|
'@nitrots/configuration': resolve(rendererRoot, 'packages/configuration/src/index.ts'),
|
||||||
'@nitrots/configuration': resolve(renderer3, 'packages/configuration/src/index.ts'),
|
'@nitrots/events': resolve(rendererRoot, 'packages/events/src/index.ts'),
|
||||||
'@nitrots/events': resolve(renderer3, 'packages/events/src/index.ts'),
|
'@nitrots/localization': resolve(rendererRoot, 'packages/localization/src/index.ts'),
|
||||||
'@nitrots/localization': resolve(renderer3, 'packages/localization/src/index.ts'),
|
'@nitrots/room': resolve(rendererRoot, 'packages/room/src/index.ts'),
|
||||||
'@nitrots/room': resolve(renderer3, 'packages/room/src/index.ts'),
|
'@nitrots/session': resolve(rendererRoot, 'packages/session/src/index.ts'),
|
||||||
'@nitrots/session': resolve(renderer3, 'packages/session/src/index.ts'),
|
'@nitrots/sound': resolve(rendererRoot, 'packages/sound/src/index.ts'),
|
||||||
'@nitrots/sound': resolve(renderer3, 'packages/sound/src/index.ts'),
|
'@nitrots/utils/src': resolve(rendererRoot, 'packages/utils/src'),
|
||||||
'@nitrots/utils/src': resolve(renderer3, 'packages/utils/src'),
|
'@nitrots/utils': resolve(rendererRoot, 'packages/utils/src/index.ts'),
|
||||||
'@nitrots/utils': resolve(renderer3, 'packages/utils/src/index.ts'),
|
'pixi.js': resolve(rendererRoot, 'node_modules/pixi.js'),
|
||||||
// Resolve pixi.js and pixi-filters from renderer3's node_modules
|
'pixi-filters': resolve(rendererRoot, 'node_modules/pixi-filters'),
|
||||||
'pixi.js': resolve(renderer3, 'node_modules/pixi.js'),
|
'howler': resolve(rendererRoot, 'node_modules/howler'),
|
||||||
'pixi-filters': resolve(renderer3, 'node_modules/pixi-filters'),
|
|
||||||
'howler': resolve(renderer3, 'node_modules/howler'),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
@@ -55,7 +56,7 @@ export default defineConfig({
|
|||||||
{
|
{
|
||||||
if(id.includes('node_modules'))
|
if(id.includes('node_modules'))
|
||||||
{
|
{
|
||||||
if(id.includes('@nitrots/nitro-renderer') || id.includes('renderer3')) return 'nitro-renderer';
|
if(id.includes('@nitrots/nitro-renderer') || id.includes('renderer3') || id.includes('Nitro_Render_V3')) return 'nitro-renderer';
|
||||||
|
|
||||||
return 'vendor';
|
return 'vendor';
|
||||||
}
|
}
|
||||||
@@ -63,4 +64,4 @@ export default defineConfig({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user