Skip to content

Commit

Permalink
Add value support to Engine Field Set
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismaltby committed Apr 10, 2024
1 parent 7679a9b commit cc3c8a8
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 73 deletions.
167 changes: 133 additions & 34 deletions src/components/forms/ValueSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,17 @@ import {
import { ScriptEditorContext } from "components/script/ScriptEditorContext";
import ScriptEventFormMathArea from "components/script/ScriptEventFormMatharea";
import { ActorDirection } from "shared/lib/entities/entitiesTypes";
import { castEventToInt } from "renderer/lib/helpers/castEventValue";
import l10n from "shared/lib/lang/l10n";
import {
castEventToBool,
castEventToInt,
} from "renderer/lib/helpers/castEventValue";
import l10n, { L10NKey } from "shared/lib/lang/l10n";
import L10NText from "ui/form/L10NText";
import { SliderField } from "ui/form/SliderField";
import { AngleInput } from "ui/form/AngleInput";
import { Option, Select } from "ui/form/Select";
import { ensureNumber } from "shared/types";
import { CheckboxField } from "ui/form/CheckboxField";

type ValueFunctionMenuItem = {
value: ValueFunction;
Expand Down Expand Up @@ -207,6 +215,22 @@ const Wrapper = styled.div`
margin-top: -3px;
}
`;

type ValueSelectInputOverride = {
topLevelOnly: boolean;
} & (
| {
type: "number" | "slider";
}
| {
type: "select";
options?: [number, string][];
} | {
type: "checkbox";
checkboxLabel: string;
}
);

interface ValueSelectProps {
name: string;
entityId: string;
Expand All @@ -218,6 +242,7 @@ interface ValueSelectProps {
min?: number;
max?: number;
step?: number;
inputOverride?: ValueSelectInputOverride;
}

const ValueSelect = ({
Expand All @@ -231,6 +256,7 @@ const ValueSelect = ({
min,
max,
step,
inputOverride,
}: ValueSelectProps) => {
const context = useContext(ScriptEditorContext);
const editorType = useSelector((state: RootState) => state.editor.type);
Expand Down Expand Up @@ -421,19 +447,19 @@ const ValueSelect = ({
{l10n("FIELD_EXPRESSION")}
</MenuItem>,
<MenuItem
key="direction"
onClick={() => {
onChange({
type: "direction",
value: "left",
});
}}
>
<MenuItemIcon>
{value.type === "direction" ? <CheckIcon /> : <BlankIcon />}
</MenuItemIcon>
{l10n("FIELD_DIRECTION")}
</MenuItem>,
key="direction"
onClick={() => {
onChange({
type: "direction",
value: "left",
});
}}
>
<MenuItemIcon>
{value.type === "direction" ? <CheckIcon /> : <BlankIcon />}
</MenuItemIcon>
{l10n("FIELD_DIRECTION")}
</MenuItem>,
<MenuDivider key="divider" />,
]
: []),
Expand Down Expand Up @@ -499,6 +525,14 @@ const ValueSelect = ({
]
);

const options = (
(inputOverride?.type === "select" && inputOverride?.options) ||
[]
).map(([value, label]) => ({
value,
label: l10n(label as L10NKey),
}));

const dropdownButton = useMemo(() => {
if (fixedType) {
return isValueAtom(value) ? (
Expand All @@ -525,26 +559,91 @@ const ValueSelect = ({
<ValueWrapper>
<InputGroup>
<InputGroupPrepend>{dropdownButton}</InputGroupPrepend>
<NumberInput
id={name}
type="number"
value={String(
value.value !== undefined && value.value !== null
? value.value
: ""
{((innerValue && !inputOverride?.topLevelOnly) ||
!inputOverride ||
inputOverride?.type === "number") && (
<NumberInput
id={name}
type="number"
value={String(
value.value !== undefined && value.value !== null
? value.value
: ""
)}
min={innerValue ? undefined : min}
max={innerValue ? undefined : max}
step={innerValue ? undefined : step}
placeholder={innerValue ? "0" : String(placeholder ?? "0")}
onChange={(e) => {
onChange({
type: "number",
value: castEventToInt(e, 0),
});
}}
onKeyDown={onKeyDown}
/>
)}
{inputOverride?.type === "slider" &&
(!innerValue || !inputOverride.topLevelOnly) && (
<SliderField
name={name}
value={
value.value !== undefined && value.value !== null
? value.value
: Number(placeholder ?? 0)
}
min={!innerValue && min ? min : 0}
max={!innerValue && max ? max : 0xffff}
placeholder={innerValue ? 0 : Number(placeholder ?? 0)}
onChange={(value) => {
console.log("ON CHANGE", value);
if (value !== undefined) {
onChange({
type: "number",
value,
});
}
}}
/>
)}
{inputOverride?.type === "select" &&
(!innerValue || !inputOverride.topLevelOnly) && (
<Select
id={name}
name={name}
value={
options.find((o) =>
value.value ? o.value === value.value : o.value === value.value
) || options[0]
}
options={options}
onChange={(e: Option) => {
onChange({
type: "number",
value: ensureNumber(e.value, 0),
});
}}
/>
)}
{inputOverride?.type === "checkbox" &&
(!innerValue || !inputOverride.topLevelOnly) && (
<CheckboxField
name={name}
label={String(inputOverride.checkboxLabel || "")}
title={inputOverride.checkboxLabel}
checked={
value.value !== undefined && value.value !== null
? Boolean(value.value)
: false
}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
onChange({
type: "number",
value: castEventToBool(e) ? 1 : 0,
});
}}
/>
)}
min={innerValue ? undefined : min}
max={innerValue ? undefined : max}
step={innerValue ? undefined : step}
placeholder={innerValue ? "0" : String(placeholder ?? "0")}
onChange={(e) => {
onChange({
type: "number",
value: castEventToInt(e, 0),
});
}}
onKeyDown={onKeyDown}
/>
</InputGroup>
</ValueWrapper>
);
Expand Down
56 changes: 31 additions & 25 deletions src/components/script/ScriptEventFormInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -737,33 +737,39 @@ const ScriptEventFormInput = ({
const engineField = engineFieldsLookup[args.engineFieldKey as string];
if (engineField) {
const fieldType = engineField.type || "number";
const updateValueField = {
key: "value",
type: fieldType,
checkboxLabel: l10n(engineField.label as L10NKey),
min: clampToCType(
setDefault(engineField.min, -Infinity),
engineField.cType
),
max: clampToCType(
setDefault(engineField.max, Infinity),
engineField.cType
),
options: engineField.options || [],
defaultValue: engineField.defaultValue ?? 0,
};
const engineDefaultValue = {
type: "number",
value: engineField.defaultValue
}
const isValueScript = isScriptValue(value);
const isDefaultScript = isScriptValue(engineDefaultValue);

return (
<ScriptEventFormInput
id={id}
<ValueSelect
name={id}
entityId={entityId}
type={fieldType}
field={updateValueField}
value={value}
args={args}
index={index}
defaultValue={updateValueField.defaultValue}
onChange={onChange}
onChangeArg={onChangeArg}
value={
isValueScript ? value : isDefaultScript ? engineDefaultValue : undefined
}
onChange={onChangeField}
min={clampToCType(
setDefault(engineField.min, -Infinity),
engineField.cType
)}
max={clampToCType(
setDefault(engineField.max, Infinity),
engineField.cType
)}
step={field.step}
placeholder={String(
engineField.defaultValue ?? 0
)}
inputOverride={{
type: fieldType,
topLevelOnly: true,
options: engineField.options || [],
checkboxLabel: l10n(engineField.label as L10NKey),
}}
/>
);
}
Expand Down
6 changes: 4 additions & 2 deletions src/components/ui/form/InputGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const InputGroup = styled.div`
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
& > div:not(:first-child) ${Select} .CustomSelect__control {
& > div:not(:first-child) ${Select} .CustomSelect__control,
& > ${Select}:not(:first-child) .CustomSelect__control {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
Expand All @@ -35,7 +36,8 @@ export const InputGroup = styled.div`
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
& > div:not(:last-child) ${Select} .CustomSelect__control {
& > div:not(:last-child) ${Select} .CustomSelect__control,
& > ${Select}:not(:last-child) .CustomSelect__control {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
Expand Down
4 changes: 4 additions & 0 deletions src/components/ui/form/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export const Select = styled(WindowedSelect).attrs((props) => ({
menuPlacement: "auto",
menuPortalTarget: setDefault(props.menuPortalTarget, menuPortalEl),
}))`
position: relative;
width: 100%;
min-width: 78px;
.CustomSelect__control {
height: 28px;
min-height: 28px;
Expand Down
62 changes: 62 additions & 0 deletions src/lib/compiler/scriptBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4741,6 +4741,68 @@ extern void __mute_mask_${symbol};
}
};


engineFieldSetToScriptValue = (key: string, value: ScriptValue) => {
const { engineFields } = this.options;
const engineField = engineFields[key];
if (engineField !== undefined) {
const cType = engineField.cType;
this._addComment(`Engine Field Set To Value`);

const [rpnOps, fetchOps] = precompileScriptValue(
optimiseScriptValue(value)
);

if (rpnOps.length === 1 && rpnOps[0].type === "number") {
// Was single number
if (is16BitCType(cType)) {
this._setConstMemInt16(key, rpnOps[0].value);
} else {
this._setConstMemInt8(key, rpnOps[0].value);
}
} else if (rpnOps.length === 1 && rpnOps[0].type === "variable") {
// Was single variable
if (is16BitCType(cType)) {
this._setMemInt16ToVariable(key, rpnOps[0].value);
} else {
this._setMemInt8ToVariable(key, rpnOps[0].value);
}
} else {
// Was RPN instructions
const engineFieldValueRef = this._declareLocal("engine_field_val", 1, true);
const localsLookup = this._performFetchOperations(fetchOps);
this._addComment(`-- Calculate value`);
const rpn = this._rpn();
this._performValueRPN(rpn, rpnOps, localsLookup);
rpn.refSetVariable(engineFieldValueRef).stop();
if (is16BitCType(cType)) {
this._setMemInt16ToVariable(key, engineFieldValueRef);
} else {
this._setMemInt8ToVariable(key, engineFieldValueRef);
}
}
this._addNL();
}
};

engineFieldSetToDefault = (
key: string,
) => {
const { engineFields } = this.options;
const engineField = engineFields[key];
if (engineField !== undefined) {
const cType = engineField.cType;
const numberValue = Number(engineField.defaultValue || 0);
this._addComment(`Engine Field Set To Default`);
if (is16BitCType(cType)) {
this._setConstMemInt16(key, numberValue);
} else {
this._setConstMemInt8(key, numberValue);
}
this._addNL();
}
};

engineFieldStoreInVariable = (key: string, variable: string) => {
const { engineFields } = this.options;
const engineField = engineFields[key];
Expand Down
Loading

0 comments on commit cc3c8a8

Please sign in to comment.