main commit
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { NotDerivate, useBox } from "@common/shared/utils/ui/vide";
|
||||
import { Atom } from "@rbxts/charm";
|
||||
import Vide, { Derivable, source } from "@rbxts/vide";
|
||||
|
||||
/**
|
||||
* Props of a toggle.
|
||||
*/
|
||||
interface ToggleProps {
|
||||
/**
|
||||
* A charm atom linked to the toggle.
|
||||
*/
|
||||
Atom?: Atom<boolean>;
|
||||
/**
|
||||
* The position of the toggle in roblox ui.
|
||||
*/
|
||||
Position?: Derivable<UDim2>;
|
||||
/**
|
||||
* The size of the toggle
|
||||
*/
|
||||
Size?: Derivable<UDim2>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A toggle is a UI component linked to an boolean.
|
||||
* @param props Props of the toggle.
|
||||
* @returns A Vide node with the toggle.
|
||||
*/
|
||||
export function Toggle(props: ToggleProps = {}) {
|
||||
const [enable, setEnable] = useBox(props.Atom, false);
|
||||
const sphereSize = source(0);
|
||||
return (
|
||||
<imagebutton
|
||||
BackgroundColor3={new Color3(1, 1, 1)}
|
||||
MouseButton1Click={() => setEnable(!enable())}
|
||||
Position={props?.Position}
|
||||
Size={props?.Size ?? UDim2.fromOffset(90, 30)}
|
||||
>
|
||||
<uicorner CornerRadius={new UDim(1, 0)} />
|
||||
<uiaspectratioconstraint AspectRatio={1.8} />
|
||||
<frame
|
||||
BackgroundColor3={new Color3(0.5, 0.5, 0.5)}
|
||||
Position={new UDim2(0, 2, 0, 2)}
|
||||
Size={new UDim2(1, -4, 1, -4)}
|
||||
Visible={NotDerivate(enable)}
|
||||
>
|
||||
<uicorner CornerRadius={new UDim(1, 0)} />
|
||||
</frame>
|
||||
<frame
|
||||
AbsoluteSizeChanged={(value) => sphereSize(value.X)}
|
||||
BackgroundColor3={new Color3(0, 0, 0)}
|
||||
Position={() => (enable() ? new UDim2(1, -sphereSize() - 2, 0, 2) : new UDim2(0, 2, 0, 2))}
|
||||
Size={new UDim2(1, -4, 1, -4)}
|
||||
>
|
||||
<uicorner CornerRadius={new UDim(1, 0)} />
|
||||
<uiaspectratioconstraint AspectRatio={1} />
|
||||
</frame>
|
||||
</imagebutton>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import { SettingsController } from "@common/client/controllers/settings";
|
||||
import { SettingDefinition, SettingRealType, SettingType } from "@common/shared/typings/settings";
|
||||
import { Atom } from "@rbxts/charm";
|
||||
import Vide, { Case, For, Source, source, Switch } from "@rbxts/vide";
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user