5180 fichiers 38.5 Mo 0 téléchargements 366 vues mis à jour il y a 7 heures ui
nitro-v36-with-renderer-v36 / src / components / wired / views / conditions / WiredConditionHasVariableView.tsx
WiredConditionHasVariableView.tsx 10.8 Ko Télécharger le fichier
import { FC, useEffect, useMemo, useState } from 'react';
import { fromOfficialVariableTarget, LocalizeText, localizeWithFallback, toOfficialVariableTarget, WiredFurniType } from '../../../../api';
import contextVariableIcon from '../../../../assets/images/wired/var/icon_source_context_clean.png';
import furniVariableIcon from '../../../../assets/images/wired/var/icon_source_furni.png';
import userVariableIcon from '../../../../assets/images/wired/var/icon_source_user.png';
import { Text } from '../../../../common';
import { useWired, useWiredTools } from '../../../../hooks';
import { WiredFurniSelectionSourceRow } from '../WiredFurniSelectionSourceRow';
import { FURNI_SOURCES, sortWiredSourceOptions, USER_SOURCES, useAvailableUserSources } from '../WiredSourcesSelector';
import { WiredVariablePicker } from '../WiredVariablePicker';
import {
    buildWiredVariablePickerEntries,
    createFallbackVariableEntry,
    flattenWiredVariablePickerEntries,
    normalizeVariableTokenFromWire
} from '../WiredVariablePickerData';
import { readWiredVariableToken, toWiredVariableId, wiredVariableIdList } from '../WiredVariableIds';
import { WiredConditionBaseView } from './WiredConditionBaseView';
import { BaseButton } from '../../../../common/BaseButton';
import { NativeTextTree } from '../../../../common/native-text/NativeTextTree';

type ConditionVariableTargetType = 'user' | 'furni' | 'context';

interface IVariableDefinition {
    availability: number;
    hasValue: boolean;
    itemId: number;
    name: string;
}

const TARGET_USER = 0;
const TARGET_FURNI = 1;
const TARGET_CONTEXT = 2;
const SOURCE_TRIGGER = 0;
const SOURCE_SELECTED = 100;

const TARGET_BUTTONS: Array<{ key: ConditionVariableTargetType; icon: string; disabled?: boolean }> = [
    { key: 'furni', icon: furniVariableIcon },
    { key: 'user', icon: userVariableIcon },
    { key: 'context', icon: contextVariableIcon }
];
const CONTEXT_SOURCE_OPTIONS = [{ value: SOURCE_TRIGGER, label: localizeWithFallback('wiredfurni.params.sources.context', 'Current execution') }];

const getTargetValue = (value: ConditionVariableTargetType) => {
    switch (value) {
        case 'furni':
            return TARGET_FURNI;
        case 'context':
            return TARGET_CONTEXT;
        default:
            return TARGET_USER;
    }
};

const normalizeTargetType = (value: number): ConditionVariableTargetType => {
    switch (value) {
        case TARGET_FURNI:
            return 'furni';
        case TARGET_CONTEXT:
            return 'context';
        default:
            return 'user';
    }
};

const getTargetDefinitions = (
    targetType: ConditionVariableTargetType,
    userDefinitions: IVariableDefinition[],
    furniDefinitions: IVariableDefinition[],
    contextDefinitions: IVariableDefinition[]
) => {
    switch (targetType) {
        case 'furni':
            return furniDefinitions;
        case 'context':
            return contextDefinitions;
        default:
            return userDefinitions;
    }
};

const getSourceTitle = (targetType: ConditionVariableTargetType) => {
    switch (targetType) {
        case 'furni':
            return LocalizeText('wiredfurni.params.sources.furni.title');
        case 'context':
            return LocalizeText('wiredfurni.params.sources.merged.title.variables');
        default:
            return LocalizeText('wiredfurni.params.sources.users.title');
    }
};

export const WiredConditionHasVariableView: FC = () => {
    // Official layout: [variable target], the furni and users in the official source slots; the quantifier
    // (labelled `.neg` for the not twin, as the server marks it) is the base view's.
    const { trigger = null, furniIds = [], setFurniIds = null, setIntParams = null, setStringParam = null, setSourceTypes = null, setVariableIds = null } = useWired();
    const { userVariableDefinitions = [], furniVariableDefinitions = [], contextVariableDefinitions = [] } = useWiredTools();
    const [targetType, setTargetType] = useState<ConditionVariableTargetType>('user');
    const [variableToken, setVariableToken] = useState('');
    const [userSource, setUserSource] = useState(SOURCE_TRIGGER);
    const [furniSource, setFurniSource] = useState(SOURCE_TRIGGER);

    const availableUserSources = useAvailableUserSources(trigger, USER_SOURCES);
    const orderedUserSources = useMemo(() => sortWiredSourceOptions(availableUserSources, 'users'), [availableUserSources]);
    const orderedFurniSources = useMemo(() => sortWiredSourceOptions(FURNI_SOURCES, 'furni'), []);
    const variableDefinitions = useMemo(
        () => getTargetDefinitions(targetType, userVariableDefinitions, furniVariableDefinitions, contextVariableDefinitions),
        [contextVariableDefinitions, furniVariableDefinitions, targetType, userVariableDefinitions]
    );
    const variableEntries = useMemo(() => buildWiredVariablePickerEntries(targetType, 'condition', variableDefinitions), [targetType, variableDefinitions]);
    const resolvedVariableEntries = useMemo(() => {
        if (!variableToken) return variableEntries;
        if (flattenWiredVariablePickerEntries(variableEntries).some((entry) => entry.token === variableToken)) return variableEntries;

        const fallbackEntry = createFallbackVariableEntry(targetType, variableToken);

        return fallbackEntry ? [fallbackEntry, ...variableEntries] : variableEntries;
    }, [targetType, variableEntries, variableToken]);

    const sourceOptions = useMemo(() => {
        switch (targetType) {
            case 'furni':
                return orderedFurniSources;
            case 'context':
                return CONTEXT_SOURCE_OPTIONS;
            default:
                return orderedUserSources;
        }
    }, [orderedFurniSources, orderedUserSources, targetType]);

    const sourceValue = targetType === 'furni' ? furniSource : targetType === 'user' ? userSource : SOURCE_TRIGGER;
    const requiresFurni =
        targetType === 'furni' && furniSource === SOURCE_SELECTED ? WiredFurniType.STUFF_SELECTION_OPTION_BY_ID : WiredFurniType.STUFF_SELECTION_OPTION_NONE;
    const selectionLimit = trigger?.maximumItemSelectionCount ?? 0;

    useEffect(() => {
        if (!trigger) return;

        const intData = trigger.intData || [];
        const nextTargetType = normalizeTargetType(intData.length > 0 ? fromOfficialVariableTarget(intData[0]) : TARGET_USER);
        const nextUserSource = trigger.userSourceTypes?.[0] ?? SOURCE_TRIGGER;
        const nextFurniSource = trigger.furniSourceTypes?.[0] ?? ((trigger.selectedItems?.length ?? 0) > 0 ? SOURCE_SELECTED : SOURCE_TRIGGER);

        setTargetType(nextTargetType);
        // AIR: the variable is the first variable id; an older server wrote the token as the string.
        setVariableToken(readWiredVariableToken(trigger.variableIds, 0, normalizeVariableTokenFromWire((trigger.stringData || '').split('\t')[0])));
        setUserSource(nextUserSource);
        setFurniSource(nextFurniSource);
    }, [trigger]);

    useEffect(() => {
        if (targetType !== 'user') return;
        if (orderedUserSources.some((option) => option.value === userSource)) return;

        setUserSource(SOURCE_TRIGGER);
    }, [orderedUserSources, targetType, userSource]);

    const save = () => {
        setStringParam('');
        setVariableIds(wiredVariableIdList(toWiredVariableId(targetType, variableToken)));
        setIntParams([toOfficialVariableTarget(getTargetValue(targetType))]);
        setSourceTypes({ furni: [furniSource], users: [userSource] });

        if (requiresFurni <= WiredFurniType.STUFF_SELECTION_OPTION_NONE) setFurniIds([]);
    };

    // AIR saves an empty variable; the condition then passes only when negated.
    const validate = () => true;

    const handleTargetChange = (nextTargetType: ConditionVariableTargetType) => {
        if (nextTargetType === targetType) return;

        setTargetType(nextTargetType);
        setVariableToken('');
    };

    return (
        <NativeTextTree>
            <WiredConditionBaseView
                hasSpecialInput={true}
                requiresFurni={requiresFurni}
                save={save}
                validate={validate}
                footerCollapsible={false}
                footer={
                    <div className="flex flex-col gap-2">
                        <WiredFurniSelectionSourceRow
                            title={getSourceTitle(targetType)}
                            titleIsLiteral={true}
                            options={sourceOptions}
                            value={sourceValue}
                            selectionKind="primary"
                            selectionActive={requiresFurni > WiredFurniType.STUFF_SELECTION_OPTION_NONE}
                            selectionCount={furniIds.length}
                            selectionLimit={selectionLimit}
                            selectionEnabledValues={[SOURCE_SELECTED]}
                            showSelectionToggle={false}
                            onChange={(value) => {
                                if (targetType === 'furni') {
                                    setFurniSource(value);
                                    return;
                                }

                                if (targetType === 'user') {
                                    setUserSource(value);
                                    return;
                                }
                            }}
                        />
                    </div>
                }
            >
                <div className="octane-wired__give-var">
                    <div className="octane-wired__give-var-heading">
                        <Text>{LocalizeText('wiredfurni.params.variables.variable_selection')}</Text>
                        <div className="octane-wired__give-var-targets">
                            {TARGET_BUTTONS.map((button) => (
                                <BaseButton
                                    key={button.key}
                                    type="button"
                                    disabled={button.disabled}
                                    className={`octane-wired__give-var-target octane-wired__give-var-target--${button.key} ${targetType === button.key ? 'is-active' : ''}`}
                                    onClick={() => handleTargetChange(button.key)}
                                >
                                    <img src={button.icon} alt={button.key} />
                                </BaseButton>
                            ))}
                        </div>
                    </div>

                    <WiredVariablePicker
                        entries={resolvedVariableEntries}
                        recentScope="variable-conditions"
                        selectedToken={variableToken}
                        onSelect={(entry) => setVariableToken(entry.token)}
                    />
                </div>
            </WiredConditionBaseView>
        </NativeTextTree>
    );
};
15Sujets
1Dépôts
20Membres
3En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser