From 2a78f332397ea7a9826b3347714fad29570370c7 Mon Sep 17 00:00:00 2001 From: reidlab Date: Sun, 20 Aug 2023 19:20:25 -0700 Subject: [PATCH] update ui --- readme.md | 1 + .../ui/components/canvas.tsx | 59 +++++++++++++++ src/ReplicatedStorage/ui/components/fill.tsx | 42 +++++++++++ .../ui/components/padding.tsx | 31 -------- .../ui/components/surface.tsx | 70 ++++++++++++++++++ src/ReplicatedStorage/ui/components/text.tsx | 40 ++++++++++ .../ui/components/toggleButton.tsx | 73 ------------------- .../ui/store/producer/config.ts | 9 +-- src/ReplicatedStorage/utils/bindingUtil.ts | 15 ++++ .../StarterPlayerScripts/ui/config/config.tsx | 19 ++--- .../ui/config/item.story.tsx | 25 +++++++ .../StarterPlayerScripts/ui/config/item.tsx | 54 ++++++++++++++ .../StarterPlayerScripts/ui/hotbar/hotbar.tsx | 16 ++-- .../StarterPlayerScripts/ui/hotbar/slot.tsx | 63 +++++----------- .../StarterPlayerScripts/ui/main.tsx | 37 ++++++---- 15 files changed, 361 insertions(+), 193 deletions(-) create mode 100644 src/ReplicatedStorage/ui/components/canvas.tsx create mode 100644 src/ReplicatedStorage/ui/components/fill.tsx delete mode 100644 src/ReplicatedStorage/ui/components/padding.tsx create mode 100644 src/ReplicatedStorage/ui/components/surface.tsx create mode 100644 src/ReplicatedStorage/ui/components/text.tsx delete mode 100644 src/ReplicatedStorage/ui/components/toggleButton.tsx create mode 100644 src/ReplicatedStorage/utils/bindingUtil.ts create mode 100644 src/StarterPlayer/StarterPlayerScripts/ui/config/item.story.tsx create mode 100644 src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx diff --git a/readme.md b/readme.md index 4bccada..189d86a 100644 --- a/readme.md +++ b/readme.md @@ -17,6 +17,7 @@ I should put this in the game sometime, but the option to open the configuration # Todo * Better null checking for the clientState.character (can cause errors atm) +* Swap to pretty-roact-hooks * Custom player list * Custom chat * Add guns diff --git a/src/ReplicatedStorage/ui/components/canvas.tsx b/src/ReplicatedStorage/ui/components/canvas.tsx new file mode 100644 index 0000000..47f4151 --- /dev/null +++ b/src/ReplicatedStorage/ui/components/canvas.tsx @@ -0,0 +1,59 @@ +import Roact from "@rbxts/roact" +import { BindingOrValue, mapBinding } from "ReplicatedStorage/utils/bindingUtil" + +interface canvasProps extends Roact.JsxInstanceProperties { + size?: BindingOrValue + position?: BindingOrValue + anchor?: Vector2 + padding?: { + top?: BindingOrValue + right?: BindingOrValue + bottom?: BindingOrValue + left?: BindingOrValue + } + clipsDescendants?: boolean + zIndex?: number + [Roact.Children]?: Roact.Children + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function canvas(props: canvasProps): Roact.Element { + const { size, position, anchor, padding, clipsDescendants, zIndex } = props + + const spreadableProps = { ...props } as Partial + delete spreadableProps.size + delete spreadableProps.position + delete spreadableProps.anchor + delete spreadableProps.padding + delete spreadableProps.clipsDescendants + delete spreadableProps.zIndex + delete spreadableProps[Roact.Children] + + return ( + + {padding !== undefined && ( + new UDim(0, px))} + PaddingRight={mapBinding(padding.right, (px) => new UDim(0, px))} + PaddingBottom={mapBinding(padding.bottom, (px) => new UDim(0, px))} + PaddingLeft={mapBinding(padding.left, (px) => new UDim(0, px))} + /> + )} + + {props[Roact.Children]} + + ) +} + +export default canvas \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/fill.tsx b/src/ReplicatedStorage/ui/components/fill.tsx new file mode 100644 index 0000000..4e2e274 --- /dev/null +++ b/src/ReplicatedStorage/ui/components/fill.tsx @@ -0,0 +1,42 @@ +import Roact from "@rbxts/roact" +import { BindingOrValue, mapBinding } from "ReplicatedStorage/utils/bindingUtil" + +interface fillProps extends Roact.JsxInstanceProperties { + color?: BindingOrValue + transparency?: BindingOrValue + radius?: BindingOrValue + [Roact.Children]?: Roact.Children + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function fill(props: fillProps): Roact.Element { + const { color, transparency, radius } = props + + const spreadableProps = { ...props } as Partial + delete spreadableProps.color + delete spreadableProps.transparency + delete spreadableProps.radius + delete spreadableProps[Roact.Children] + + return ( + + {radius !== undefined && ( + (r === "circular" ? new UDim(1, 0) : new UDim(0, r)))} + /> + )} + + {props[Roact.Children]} + + ) +} + +export default fill \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/padding.tsx b/src/ReplicatedStorage/ui/components/padding.tsx deleted file mode 100644 index 402d2cf..0000000 --- a/src/ReplicatedStorage/ui/components/padding.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import Roact from "@rbxts/roact" - -interface paddingProps extends Roact.JsxInstanceProperties { - padding?: UDim | Roact.Binding - paddingX?: UDim | Roact.Binding - paddingY?: UDim | Roact.Binding - - Event?: Roact.JsxInstanceEvents - Change?: Roact.JsxInstanceChangeEvents -} - -function padding(props: paddingProps): Roact.Element { - const { padding, paddingX, paddingY } = props - - const spreadableProps = { ...props } as Partial - delete spreadableProps.padding - delete spreadableProps.paddingX - delete spreadableProps.paddingY - - return ( - - ) -} - -export default padding \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/surface.tsx b/src/ReplicatedStorage/ui/components/surface.tsx new file mode 100644 index 0000000..25f2a8f --- /dev/null +++ b/src/ReplicatedStorage/ui/components/surface.tsx @@ -0,0 +1,70 @@ +import Roact from "@rbxts/roact" +import Canvas from "./canvas" +import Acrylic from "./acrylic" +import Fill from "./fill" +import { BindingOrValue } from "ReplicatedStorage/utils/bindingUtil" + +interface surfaceProps extends Roact.JsxInstanceProperties { + size: BindingOrValue + position: BindingOrValue + ratio?: BindingOrValue + color?: BindingOrValue + blur?: BindingOrValue + [Roact.Children]?: Roact.Children + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function surface(props: surfaceProps): Roact.Element { + const { size, position, ratio, color, blur } = props + + const spreadableProps = { ...props } as Partial + delete spreadableProps.size + delete spreadableProps.position + delete spreadableProps.ratio + delete spreadableProps.color + delete spreadableProps.blur + delete spreadableProps[Roact.Children] + + return ( + + <> + { + ratio !== undefined && + } + + + <> + { + blur !== false && + } + + + + + + {props[Roact.Children]} + + + ) +} + +export default surface \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/text.tsx b/src/ReplicatedStorage/ui/components/text.tsx new file mode 100644 index 0000000..8403910 --- /dev/null +++ b/src/ReplicatedStorage/ui/components/text.tsx @@ -0,0 +1,40 @@ +import Roact from "@rbxts/roact" + +interface textProps extends Roact.JsxInstanceProperties { + bold?: boolean + paddingX?: UDim + paddingY?: UDim + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function text(props: textProps): Roact.Element { + const { bold, paddingX, paddingY, Text, TextXAlignment } = props + + const spreadableProps = { ...props } as Partial + delete spreadableProps.bold + delete spreadableProps.paddingX + delete spreadableProps.paddingY + + return ( + + + + ) +} + +export default text \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/toggleButton.tsx b/src/ReplicatedStorage/ui/components/toggleButton.tsx deleted file mode 100644 index 44ac02b..0000000 --- a/src/ReplicatedStorage/ui/components/toggleButton.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import Roact from "@rbxts/roact" -import Padding from "ReplicatedStorage/ui/components/padding" -import { Spring } from "@rbxts/flipper" -import { useGroupMotor } from "@rbxts/roact-hooked-plus" - -interface toggleButtonProps extends Roact.JsxInstanceProperties { - active: boolean - enableCallback: () => void - disableCallback: () => void - - Event?: Roact.JsxInstanceEvents - Change?: Roact.JsxInstanceChangeEvents -} - -const BUTTON_DEFAULT = [new Spring(0, { frequency: 6 })] -const BUTTON_ACTIVE = [new Spring(1, { frequency: 6 })] - -function toggleButton(props: toggleButtonProps): Roact.Element { - let { active } = props - const { enableCallback, disableCallback, Text } = props - - const spreadableProps = { ...props } as Partial - delete spreadableProps.active - delete spreadableProps.enableCallback - delete spreadableProps.disableCallback - - const [buttonBorderColorMap, setButtonGoal] = useGroupMotor([0]) - const buttonBorderColor = buttonBorderColorMap.map((t) => t[0]).map((val) => { - return Color3.fromHex("#6c7086").Lerp(Color3.fromHex("#b4befe"), val) - }) - - return ( - { - active = !active - if (active) { - setButtonGoal(BUTTON_ACTIVE) - enableCallback() - } else { - setButtonGoal(BUTTON_DEFAULT) - disableCallback() - } - } - }} - > - - - - - ) -} - -export default toggleButton \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/store/producer/config.ts b/src/ReplicatedStorage/ui/store/producer/config.ts index 220eec8..d0f997f 100644 --- a/src/ReplicatedStorage/ui/store/producer/config.ts +++ b/src/ReplicatedStorage/ui/store/producer/config.ts @@ -9,13 +9,8 @@ const initialState: ConfigState = { } export const configProducer = createProducer(initialState, { - enableAcrylic: (state) => ({ + toggleConfig: (state, action: keyof ConfigState) => ({ ...state, - acrylicBlur: true - }), - - disableAcrylic: (state) => ({ - ...state, - acrylicBlur: false + [action]: !state[action] }) }) \ No newline at end of file diff --git a/src/ReplicatedStorage/utils/bindingUtil.ts b/src/ReplicatedStorage/utils/bindingUtil.ts new file mode 100644 index 0000000..36a479f --- /dev/null +++ b/src/ReplicatedStorage/utils/bindingUtil.ts @@ -0,0 +1,15 @@ +import Roact from "@rbxts/roact" + +export type BindingOrValue = T | Roact.Binding + +export function isBinding(binding: unknown): binding is Roact.Binding { + return typeIs(binding, "table") && "getValue" in binding +} + +export function mapBinding(value: BindingOrValue, transform: (value: T) => U): Roact.Binding { + return isBinding(value) ? value.map(transform) : Roact.createBinding(transform(value))[0] +} + +export function asBinding(value: BindingOrValue): Roact.Binding { + return isBinding(value) ? value : Roact.createBinding(value)[0] +} \ No newline at end of file diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx index fb046f0..d1f6138 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx @@ -1,12 +1,10 @@ import Roact from "@rbxts/roact" -import Padding from "ReplicatedStorage/ui/components/padding" import Acrylic from "ReplicatedStorage/ui/components/acrylic" -import ToggleButton from "ReplicatedStorage/ui/components/toggleButton" import { ContextActionService, HttpService } from "@rbxts/services" import { Spring } from "@rbxts/flipper" import { useGroupMotor } from "@rbxts/roact-hooked-plus" import { useEffect } from "@rbxts/roact-hooked" -import { useRootProducer } from "ReplicatedStorage/ui/store/hooks/useUiProducer" +import Item from "./item" interface ConfigProps extends Roact.JsxInstanceProperties { shown: boolean @@ -19,8 +17,6 @@ const CONFIG_DEFAULT = [new Spring(1.5, { frequency: 6 }), new Spring(0, { frequ const CONFIG_ACTIVE = [new Spring(.5, { frequency: 6 }), new Spring(1, { frequency: 6 })] function config(props: ConfigProps): Roact.Element { - const { disableAcrylic, enableAcrylic } = useRootProducer() - let { shown } = props const spreadableProps = { ...props } as Partial @@ -88,14 +84,11 @@ function config(props: ConfigProps): Roact.Element { Thickness={1} Color={configBorderColor} /> - - diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.story.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.story.tsx new file mode 100644 index 0000000..015afb4 --- /dev/null +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.story.tsx @@ -0,0 +1,25 @@ +import Roact from "@rbxts/roact" +import { withHookDetection } from "@rbxts/roact-hooked" +import { ReflexProvider, useSelector } from "@rbxts/roact-reflex" +import { producer } from "ReplicatedStorage/ui/store/producer" +import Item from "./item" + +export = (target: Frame) => { + withHookDetection(Roact) + + const tree = Roact.mount( + + + , + target + ) + + return () => { + Roact.unmount(tree) + } +} \ No newline at end of file diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx new file mode 100644 index 0000000..bb7fdf5 --- /dev/null +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx @@ -0,0 +1,54 @@ +import Roact from "@rbxts/roact" +import Fill from "ReplicatedStorage/ui/components/fill" +import Text from "ReplicatedStorage/ui/components/text" +import Canvas from "ReplicatedStorage/ui/components/canvas" +import { useRootProducer, useRootSelector } from "ReplicatedStorage/ui/store/hooks/useUiProducer" +import { ConfigState } from "ReplicatedStorage/ui/store/producer/config" + +interface itemProps extends Roact.JsxInstanceProperties { + size: UDim2 + position: UDim2 + text: string + action: keyof ConfigState + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function item(props: itemProps): Roact.Element { + const { size, position, text, action } = props + + const { toggleConfig } = useRootProducer() + + const active = useRootSelector((state) => state.configProducer[action]) + + const spreadableProps = { ...props } as Partial + delete spreadableProps.size + delete spreadableProps.position + delete spreadableProps.text + delete spreadableProps.action + + return ( + + + + + toggleConfig(action) + }} + Size={new UDim2(1, 0, 1, 0)} + Transparency={1} + Text={""} + /> + + ) +} + +export default item \ No newline at end of file diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx index b196570..a27cda5 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx @@ -1,7 +1,7 @@ import Roact from "@rbxts/roact" import Slot from "./slot" import { useWorldContext } from "../contexts/worldContext" -import Padding from "ReplicatedStorage/ui/components/padding" +import Canvas from "ReplicatedStorage/ui/components/canvas" import { StarterGui } from "@rbxts/services" interface HotbarProps extends Roact.JsxInstanceProperties { @@ -41,23 +41,17 @@ function hotbar(props: HotbarProps): Roact.Element { }) return ( - - {...items} - + ) } diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx index fff7f6b..2b61e12 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx @@ -2,8 +2,8 @@ import Roact from "@rbxts/roact" import { useEffect } from "@rbxts/roact-hooked" import { useWorldContext } from "../contexts/worldContext" import { ContextActionService, HttpService } from "@rbxts/services" -import Padding from "ReplicatedStorage/ui/components/padding" -import Acrylic from "ReplicatedStorage/ui/components/acrylic" +import Text from "ReplicatedStorage/ui/components/text" +import Surface from "ReplicatedStorage/ui/components/surface" import { Spring } from "@rbxts/flipper" import { useGroupMotor } from "@rbxts/roact-hooked-plus" @@ -28,9 +28,6 @@ function slot(props: SlotProps): Roact.Element { delete spreadableProps.tool const [slotBorderColorAndSlotRatio, setSlotGoal] = useGroupMotor([0, 6]) - const slotBorderColor = slotBorderColorAndSlotRatio.map((t) => t[0]).map((val) => { - return Color3.fromHex("#6c7086").Lerp(Color3.fromHex("#b4befe"), val) - }) const slotRatio = slotBorderColorAndSlotRatio.map((t) => t[1]) const { clientState } = useWorldContext() @@ -63,49 +60,25 @@ function slot(props: SlotProps): Roact.Element { }) return ( - - - - - - - - - - - + ) } diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/main.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/main.tsx index 755ea44..1522406 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/main.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/main.tsx @@ -1,7 +1,8 @@ import Roact from "@rbxts/roact" +import { withHookDetection } from "@rbxts/roact-hooked" import Hotbar from "./hotbar/hotbar" import Config from "./config/config" -import { withHookDetection } from "@rbxts/roact-hooked" +import Canvas from "ReplicatedStorage/ui/components/canvas" interface MainProps extends Roact.JsxInstanceEvents { Event?: Roact.JsxInstanceEvents @@ -14,18 +15,28 @@ export default function main(props: MainProps): Roact.Element { withHookDetection(Roact) return ( - - - + + + + + ) } \ No newline at end of file