128 lines
4.5 KiB
TypeScript
128 lines
4.5 KiB
TypeScript
import { Atom } from "@rbxts/charm";
|
|
import Vide, { Case, For, Source, source, Switch } from "@rbxts/vide";
|
|
|
|
import { SettingDefinition, SettingRealType, SettingType } from "../../../../shared/typings/settings";
|
|
import { SettingsController } from "../../../controllers/settings";
|
|
import { Toggle } from "../global/toggle";
|
|
|
|
/**
|
|
* The settings menu as vide components.
|
|
* @param settingsController The settings Controller for fetching settings.
|
|
* @returns A Vide node with the settings menu.
|
|
*/
|
|
export function Settings(settingsController: SettingsController) {
|
|
const keys = source(settingsController.getSections());
|
|
const panel = source(keys()[0]);
|
|
|
|
return (
|
|
<frame
|
|
BackgroundColor3={new Color3(0, 0, 0)}
|
|
Position={UDim2.fromScale(0.05, 0.05)}
|
|
Size={UDim2.fromScale(0.9, 0.9)}
|
|
>
|
|
<uicorner />
|
|
<uistroke Color={new Color3(1, 1, 1)} />
|
|
<scrollingframe BackgroundTransparency={1} Size={UDim2.fromScale(0.3, 1)}>
|
|
<uigridlayout CellPadding={UDim2.fromOffset(0, 0)} CellSize={new UDim2(1, 0, 0, 40)} />
|
|
<For each={keys}>{(group) => <SettingsGroup name={group} panelSource={panel} />}</For>
|
|
</scrollingframe>
|
|
<frame Position={UDim2.fromScale(0.3, 0)} Size={new UDim2(0, 1, 1, 0)} />
|
|
<frame BackgroundTransparency={1} Position={new UDim2(0.3, 10, 0, 0)} Size={new UDim2(0.7, -10, 1, 0)}>
|
|
<uilistlayout Padding={new UDim(0, 10)} />
|
|
<For each={() => settingsController.getSectionWithDef(panel())}>
|
|
{([def, atom]) => <SettingsEntry atom={atom} definition={def} />}
|
|
</For>
|
|
</frame>
|
|
</frame>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* An entry in the settings menu.
|
|
* @param props Properties of the entry.
|
|
* @param props.definition Setting definition.
|
|
* @param props.atom Charm atom with the value of the setting.
|
|
* @returns A setting entry.
|
|
*/
|
|
export function SettingsEntry<T extends SettingType>(props: {
|
|
/**
|
|
* The atom with the value of the setting.
|
|
*/
|
|
atom: Atom<SettingRealType<T>>;
|
|
/**
|
|
* The definition of the setting.
|
|
*/
|
|
definition: SettingDefinition<T>;
|
|
}) {
|
|
return (
|
|
<frame AutomaticSize={Enum.AutomaticSize.Y} BackgroundTransparency={1}>
|
|
<uilistlayout />
|
|
<textlabel
|
|
AutomaticSize={Enum.AutomaticSize.Y}
|
|
BackgroundTransparency={1}
|
|
Text={props.definition.name}
|
|
TextColor3={new Color3(1, 1, 1)}
|
|
TextSize={30}
|
|
TextXAlignment={Enum.TextXAlignment.Left}
|
|
/>
|
|
<textlabel
|
|
AutomaticSize={Enum.AutomaticSize.Y}
|
|
BackgroundTransparency={1}
|
|
Text={props.definition.description}
|
|
TextColor3={new Color3(1, 1, 1)}
|
|
TextSize={25}
|
|
TextTransparency={0.5}
|
|
TextXAlignment={Enum.TextXAlignment.Left}
|
|
/>
|
|
<Switch condition={() => props.definition.type}>
|
|
<Case match={SettingType.Boolean}>
|
|
{() => (
|
|
<>
|
|
<frame Size={UDim2.fromOffset(0, 10)} />
|
|
<Toggle Atom={props.atom as unknown as Atom<boolean>} />
|
|
</>
|
|
)}
|
|
</Case>
|
|
</Switch>
|
|
</frame>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* A button for each setting section the settings menu.
|
|
* @param props Properties of the button.
|
|
* @param props.name The name of the entry.
|
|
* @param props.panelSource A vide source for the current panel.
|
|
* @returns The Settings group button.
|
|
*/
|
|
export function SettingsGroup(props: {
|
|
/**
|
|
* The name of the settings group.
|
|
*/
|
|
name: string;
|
|
/**
|
|
* A vide source with the name of the current panel.
|
|
*/
|
|
panelSource: Source<string>;
|
|
}) {
|
|
return (
|
|
<frame BackgroundTransparency={1}>
|
|
<textbutton
|
|
BackgroundTransparency={1}
|
|
FontFace={() =>
|
|
props.name === props.panelSource()
|
|
? Font.fromEnum(Enum.Font.SourceSansBold)
|
|
: Font.fromEnum(Enum.Font.SourceSans)
|
|
}
|
|
MouseButton1Click={() => {
|
|
props.panelSource(props.name);
|
|
}}
|
|
Size={UDim2.fromScale(1, 1)}
|
|
Text={props.name}
|
|
TextColor3={new Color3(1, 1, 1)}
|
|
TextScaled={true}
|
|
/>
|
|
</frame>
|
|
);
|
|
}
|