From c258363a0303bce5427efea147ce324bb8f90669 Mon Sep 17 00:00:00 2001 From: reidlab Date: Sun, 20 Aug 2023 15:14:23 -0700 Subject: [PATCH 1/7] improve ui --- .../ui/store/producer/config.ts | 11 ++- .../StarterPlayerScripts/ui/config/config.tsx | 54 ++++++-------- .../ui/config/toggleButton.tsx | 73 +++++++++++++++++++ .../StarterPlayerScripts/ui/hotbar/slot.tsx | 18 +++-- 4 files changed, 116 insertions(+), 40 deletions(-) create mode 100644 src/StarterPlayer/StarterPlayerScripts/ui/config/toggleButton.tsx diff --git a/src/ReplicatedStorage/ui/store/producer/config.ts b/src/ReplicatedStorage/ui/store/producer/config.ts index de831aa..220eec8 100644 --- a/src/ReplicatedStorage/ui/store/producer/config.ts +++ b/src/ReplicatedStorage/ui/store/producer/config.ts @@ -5,12 +5,17 @@ export interface ConfigState { } const initialState: ConfigState = { - acrylicBlur: false + acrylicBlur: true } export const configProducer = createProducer(initialState, { - toggleAcrylic: (state) => ({ + enableAcrylic: (state) => ({ ...state, - acrylicBlur: !state.acrylicBlur + acrylicBlur: true + }), + + disableAcrylic: (state) => ({ + ...state, + acrylicBlur: false }) }) \ 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 92a05dc..55ee564 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx @@ -1,6 +1,7 @@ import Roact from "@rbxts/roact" import Padding from "ReplicatedStorage/ui/components/padding" import Acrylic from "ReplicatedStorage/ui/components/acrylic" +import ToggleButton from "./toggleButton" import { ContextActionService, HttpService } from "@rbxts/services" import { Spring } from "@rbxts/flipper" import { useGroupMotor } from "@rbxts/roact-hooked-plus" @@ -14,19 +15,22 @@ interface ConfigProps extends Roact.JsxInstanceProperties { Change?: Roact.JsxInstanceChangeEvents } -const CONFIG_DEFAULT = [new Spring(1.5, { frequency: 6 })] -const CONFIG_ACTIVE = [new Spring(.5, { frequency: 6 })] +const CONFIG_DEFAULT = [new Spring(1.5, { frequency: 6 }), new Spring(0, { frequency: 6 })] +const CONFIG_ACTIVE = [new Spring(.5, { frequency: 6 }), new Spring(1, { frequency: 6 })] function config(props: ConfigProps): Roact.Element { - const { toggleAcrylic } = useRootProducer() + const { disableAcrylic, enableAcrylic } = useRootProducer() let { shown } = props const spreadableProps = { ...props } as Partial delete spreadableProps.shown - const [slotPosYMap, setPosYGoal] = useGroupMotor([1.5, 6]) - const slotPosY = slotPosYMap.map((t) => t[0]) + const [configPosYAndBorderColor, setConfigGoal] = useGroupMotor([1.5, 6]) + const configPosY = configPosYAndBorderColor.map((t) => t[0]) + const configBorderColor = configPosYAndBorderColor.map((t) => t[1]).map((val) => { + return Color3.fromHex("#6c7086").Lerp(Color3.fromHex("#b4befe"), val) + }) useEffect(() => { const guid = HttpService.GenerateGUID(false) @@ -36,9 +40,9 @@ function config(props: ConfigProps): Roact.Element { if (Enum.UserInputState.Begin === userInputState) { shown = !shown if (shown) { - setPosYGoal(CONFIG_ACTIVE) + setConfigGoal(CONFIG_ACTIVE) } else { - setPosYGoal(CONFIG_DEFAULT) + setConfigGoal(CONFIG_DEFAULT) } } }, @@ -52,7 +56,7 @@ function config(props: ConfigProps): Roact.Element { {...spreadableProps} AnchorPoint={new Vector2(.5, .5)} Position={ - slotPosY.map((posY) => { + configPosY.map((posY) => { return new UDim2(.5, 0, posY, 0) }) } @@ -68,7 +72,7 @@ function config(props: ConfigProps): Roact.Element { AnchorPoint={new Vector2(0, 0)} Position={new UDim2(0, 0, 0, 0)} Size={new UDim2(1, 0, 1, 0)} - BackgroundTransparency={.7} + BackgroundTransparency={.3} BackgroundColor3={Color3.fromHex("#1e1e2e")} > + - {toggleAcrylic()} - }} - > - - - + ) diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/toggleButton.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/toggleButton.tsx new file mode 100644 index 0000000..44ac02b --- /dev/null +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/toggleButton.tsx @@ -0,0 +1,73 @@ +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/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx index 203d9c9..fff7f6b 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx @@ -16,8 +16,8 @@ interface SlotProps extends Roact.JsxInstanceProperties { Change?: Roact.JsxInstanceChangeEvents } -const SLOT_DEFAULT = [new Spring(.7, { frequency: 6 }), new Spring(6, { frequency: 6 })] -const SLOT_ACTIVE = [new Spring(.5, { frequency: 6 }), new Spring(5, { frequency: 6 })] +const SLOT_DEFAULT = [new Spring(0, { frequency: 6 }), new Spring(6, { frequency: 6 })] +const SLOT_ACTIVE = [new Spring(1, { frequency: 6 }), new Spring(5, { frequency: 6 })] function slot(props: SlotProps): Roact.Element { const { index, keycode, tool } = props @@ -27,9 +27,11 @@ function slot(props: SlotProps): Roact.Element { delete spreadableProps.keycode delete spreadableProps.tool - const [slotBgTransparencyAndSlotRatio, setSlotGoal] = useGroupMotor([.7, 6]) - const slotBgTransparency = slotBgTransparencyAndSlotRatio.map((t) => t[0]) - const slotRatio = slotBgTransparencyAndSlotRatio.map((t) => t[1]) + 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,7 +65,7 @@ function slot(props: SlotProps): Roact.Element { return ( + Date: Sun, 20 Aug 2023 15:15:11 -0700 Subject: [PATCH 2/7] fix ui --- src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx index 55ee564..c8303af 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx @@ -93,7 +93,7 @@ function config(props: ConfigProps): Roact.Element { /> From d21682999cec4a0d14b70914c9d576684b45e278 Mon Sep 17 00:00:00 2001 From: reidlab Date: Sun, 20 Aug 2023 15:18:41 -0700 Subject: [PATCH 3/7] update imports --- .../config => ReplicatedStorage/ui/components}/toggleButton.tsx | 0 src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{StarterPlayer/StarterPlayerScripts/ui/config => ReplicatedStorage/ui/components}/toggleButton.tsx (100%) diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/toggleButton.tsx b/src/ReplicatedStorage/ui/components/toggleButton.tsx similarity index 100% rename from src/StarterPlayer/StarterPlayerScripts/ui/config/toggleButton.tsx rename to src/ReplicatedStorage/ui/components/toggleButton.tsx diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx index c8303af..fb046f0 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx @@ -1,7 +1,7 @@ import Roact from "@rbxts/roact" import Padding from "ReplicatedStorage/ui/components/padding" import Acrylic from "ReplicatedStorage/ui/components/acrylic" -import ToggleButton from "./toggleButton" +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" From 2a78f332397ea7a9826b3347714fad29570370c7 Mon Sep 17 00:00:00 2001 From: reidlab Date: Sun, 20 Aug 2023 19:20:25 -0700 Subject: [PATCH 4/7] 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 From 057efc9a8c935150fc9d97a662a8ea409d01516c Mon Sep 17 00:00:00 2001 From: reidlab Date: Sun, 20 Aug 2023 19:52:02 -0700 Subject: [PATCH 5/7] update ui --- .../ui/components/surface.tsx | 25 +++---- .../StarterPlayerScripts/ui/config/config.tsx | 71 +++++++------------ .../ui/config/item.story.tsx | 25 ------- .../StarterPlayerScripts/ui/config/item.tsx | 4 +- .../StarterPlayerScripts/ui/hotbar/slot.tsx | 1 + .../StarterPlayerScripts/ui/main.tsx | 6 -- 6 files changed, 39 insertions(+), 93 deletions(-) delete mode 100644 src/StarterPlayer/StarterPlayerScripts/ui/config/item.story.tsx diff --git a/src/ReplicatedStorage/ui/components/surface.tsx b/src/ReplicatedStorage/ui/components/surface.tsx index 25f2a8f..e5c2c33 100644 --- a/src/ReplicatedStorage/ui/components/surface.tsx +++ b/src/ReplicatedStorage/ui/components/surface.tsx @@ -9,7 +9,7 @@ interface surfaceProps extends Roact.JsxInstanceProperties { position: BindingOrValue ratio?: BindingOrValue color?: BindingOrValue - blur?: BindingOrValue + anchor?: Vector2 [Roact.Children]?: Roact.Children Event?: Roact.JsxInstanceEvents @@ -17,14 +17,14 @@ interface surfaceProps extends Roact.JsxInstanceProperties { } function surface(props: surfaceProps): Roact.Element { - const { size, position, ratio, color, blur } = props + const { size, position, ratio, color, anchor } = props const spreadableProps = { ...props } as Partial delete spreadableProps.size delete spreadableProps.position delete spreadableProps.ratio delete spreadableProps.color - delete spreadableProps.blur + delete spreadableProps.anchor delete spreadableProps[Roact.Children] return ( @@ -33,24 +33,19 @@ function surface(props: surfaceProps): Roact.Element { Key={"surface container"} size={size} position={position} + anchor={anchor} > <> { - ratio !== undefined && + ratio !== undefined && } - <> - { - blur !== false && - } - + { shown: boolean @@ -13,8 +13,8 @@ interface ConfigProps extends Roact.JsxInstanceProperties { Change?: Roact.JsxInstanceChangeEvents } -const CONFIG_DEFAULT = [new Spring(1.5, { frequency: 6 }), new Spring(0, { frequency: 6 })] -const CONFIG_ACTIVE = [new Spring(.5, { frequency: 6 }), new Spring(1, { frequency: 6 })] +const CONFIG_DEFAULT = [new Spring(1.5, { frequency: 6 })] +const CONFIG_ACTIVE = [new Spring(.5, { frequency: 6 })] function config(props: ConfigProps): Roact.Element { let { shown } = props @@ -22,11 +22,8 @@ function config(props: ConfigProps): Roact.Element { const spreadableProps = { ...props } as Partial delete spreadableProps.shown - const [configPosYAndBorderColor, setConfigGoal] = useGroupMotor([1.5, 6]) - const configPosY = configPosYAndBorderColor.map((t) => t[0]) - const configBorderColor = configPosYAndBorderColor.map((t) => t[1]).map((val) => { - return Color3.fromHex("#6c7086").Lerp(Color3.fromHex("#b4befe"), val) - }) + const [configPosYMap, setConfigGoal] = useGroupMotor([1.5]) + const configPosY = configPosYMap.map((t) => t[0]) useEffect(() => { const guid = HttpService.GenerateGUID(false) @@ -48,50 +45,34 @@ function config(props: ConfigProps): Roact.Element { }) return ( - { return new UDim2(.5, 0, posY, 0) }) } - BackgroundTransparency={1} - Size={new UDim2(.4, 0, .7, 0)} - Key={"Config"} + size={new UDim2(.4, 0, .7, 0)} + Key={"config"} > - - - - - - - - + + + ) } diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.story.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.story.tsx deleted file mode 100644 index 015afb4..0000000 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.story.tsx +++ /dev/null @@ -1,25 +0,0 @@ -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 index bb7fdf5..9ec7ae4 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx @@ -29,12 +29,12 @@ function item(props: itemProps): Roact.Element { delete spreadableProps.action return ( - + From 079af9709f75458e5f84d25ddd282b66a5aa4907 Mon Sep 17 00:00:00 2001 From: reidlab Date: Sun, 20 Aug 2023 20:03:30 -0700 Subject: [PATCH 6/7] switch to pretty-roact-hooks --- package.json | 2 +- .../StarterPlayerScripts/ui/config/config.tsx | 9 +++---- .../StarterPlayerScripts/ui/hotbar/slot.tsx | 9 +++---- yarn.lock | 25 ++++++++++++------- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index f637509..707cbd5 100644 --- a/package.json +++ b/package.json @@ -38,11 +38,11 @@ "@rbxts/make": "^1.0.6", "@rbxts/matter": "^0.6.2-ts.6", "@rbxts/plasma": "^0.4.1-ts.1", + "@rbxts/pretty-roact-hooks": "^3.1.1", "@rbxts/reflex": "^4.2.0", "@rbxts/rewire": "^0.3.0", "@rbxts/roact": "^1.4.4-ts.0", "@rbxts/roact-hooked": "^2.6.0", - "@rbxts/roact-hooked-plus": "^1.8.1", "@rbxts/roact-reflex": "^2.1.0", "@rbxts/services": "^1.5.1", "@rbxts/testez": "^0.4.2-ts.0", diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx index f38eb23..ce5fc22 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx @@ -1,10 +1,10 @@ import Roact from "@rbxts/roact" 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 Item from "./item" import Surface from "ReplicatedStorage/ui/components/surface" +import { useMotor } from "@rbxts/pretty-roact-hooks" interface ConfigProps extends Roact.JsxInstanceProperties { shown: boolean @@ -13,8 +13,8 @@ interface ConfigProps extends Roact.JsxInstanceProperties { Change?: Roact.JsxInstanceChangeEvents } -const CONFIG_DEFAULT = [new Spring(1.5, { frequency: 6 })] -const CONFIG_ACTIVE = [new Spring(.5, { frequency: 6 })] +const CONFIG_DEFAULT = new Spring(1.5, { frequency: 6 }) +const CONFIG_ACTIVE = new Spring(.5, { frequency: 6 }) function config(props: ConfigProps): Roact.Element { let { shown } = props @@ -22,8 +22,7 @@ function config(props: ConfigProps): Roact.Element { const spreadableProps = { ...props } as Partial delete spreadableProps.shown - const [configPosYMap, setConfigGoal] = useGroupMotor([1.5]) - const configPosY = configPosYMap.map((t) => t[0]) + const [configPosY, setConfigGoal] = useMotor(1.5) useEffect(() => { const guid = HttpService.GenerateGUID(false) diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx index b24dce1..261ba8e 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx @@ -5,7 +5,7 @@ import { ContextActionService, HttpService } from "@rbxts/services" 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" +import { useMotor } from "@rbxts/pretty-roact-hooks" interface SlotProps extends Roact.JsxInstanceProperties { index: number @@ -16,8 +16,8 @@ interface SlotProps extends Roact.JsxInstanceProperties { Change?: Roact.JsxInstanceChangeEvents } -const SLOT_DEFAULT = [new Spring(0, { frequency: 6 }), new Spring(6, { frequency: 6 })] -const SLOT_ACTIVE = [new Spring(1, { frequency: 6 }), new Spring(5, { frequency: 6 })] +const SLOT_DEFAULT = new Spring(6, { frequency: 6 }) +const SLOT_ACTIVE = new Spring(5, { frequency: 6 }) function slot(props: SlotProps): Roact.Element { const { index, keycode, tool } = props @@ -27,8 +27,7 @@ function slot(props: SlotProps): Roact.Element { delete spreadableProps.keycode delete spreadableProps.tool - const [slotBorderColorAndSlotRatio, setSlotGoal] = useGroupMotor([0, 6]) - const slotRatio = slotBorderColorAndSlotRatio.map((t) => t[1]) + const [slotRatio, setSlotGoal] = useMotor(0) const { clientState } = useWorldContext() diff --git a/yarn.lock b/yarn.lock index 73f5dcd..5010b83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -131,6 +131,14 @@ resolved "https://registry.yarnpkg.com/@rbxts/plasma/-/plasma-0.4.1-ts.1.tgz#3d8db367c3220e6b6953cdddbf8af9f087165392" integrity sha512-RhLkC3GQW0KeyqjFwvOUbHhsIJOHmXg+BhcKLp0IgUDVgC5GktShi3zmW6GQ319yod+RlUDG1XHjOnP3Omo4bA== +"@rbxts/pretty-roact-hooks@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@rbxts/pretty-roact-hooks/-/pretty-roact-hooks-3.1.1.tgz#b2729163bfd2c89e1efb91c544d7ddb798054fe0" + integrity sha512-eve1L7GWKZVo6ZLgcmk6c95SDvhTRIjWwR8notAz7g+CQ/jdtOoX+5fVHOQLMYE6HbQ79Bth+LO13WOM4T3WKg== + dependencies: + "@rbxts/services" "^1.5.1" + "@rbxts/set-timeout" "^1.1.2" + "@rbxts/reflex@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@rbxts/reflex/-/reflex-4.2.0.tgz#10d064de5e293f1aea429846d4d8739821cb575a" @@ -141,14 +149,6 @@ resolved "https://registry.yarnpkg.com/@rbxts/rewire/-/rewire-0.3.0.tgz#47f0cd651fe405cf418936799d2a4dac6b1bb7ce" integrity sha512-wChhGZ3kEkEsMK9ZuwKpwRsC7OGVZlvxrYMR3beFgCIPXE58JKLziBLkDACmd709XCCEmsMAqv9HMCMhSTD08Q== -"@rbxts/roact-hooked-plus@^1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@rbxts/roact-hooked-plus/-/roact-hooked-plus-1.8.1.tgz#e0fa32b74c0f958430ae62f249f1b5b52ce27f3b" - integrity sha512-ipJf6pZcQZlx/0hyisQz2eoRECg38knUgjkEvx2dvAHfs0+IDgera7mcwv6zTMACqalaXu00inc4E5dpOrs54A== - dependencies: - "@rbxts/flipper" "^2.0.1" - "@rbxts/services" "^1.2.0" - "@rbxts/roact-hooked@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@rbxts/roact-hooked/-/roact-hooked-2.6.0.tgz#cbe3e244e1d52d879083c62b6662c4d082c6d30b" @@ -164,11 +164,18 @@ resolved "https://registry.yarnpkg.com/@rbxts/roact/-/roact-1.4.4-ts.0.tgz#7f297bec03dbea9473bd2d82b148d3ae6e4f6c00" integrity sha512-gn9mBoGG/Clzgv2kyOvLNVd9dh5t6z+jukC3ITv2HnfPqvf/sMbz/VMaBoiB7t5umuiIe0LjW0ctZrkrS+uTOA== -"@rbxts/services@^1.2.0", "@rbxts/services@^1.5.1": +"@rbxts/services@^1.5.1": version "1.5.1" resolved "https://registry.yarnpkg.com/@rbxts/services/-/services-1.5.1.tgz#4536a87932f28797507ed591f0061277c52ea77f" integrity sha512-SRtfIjga0K4YYSXRpK+eH3kcTq7ZXo9OHOt0jszaOOoEOIJloMGlyuRPqesPHyhveh2AMXAZr3TYbRMSD+u+kQ== +"@rbxts/set-timeout@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@rbxts/set-timeout/-/set-timeout-1.1.2.tgz#2adc9d4b5dcb54ca4332eb7ec8d19793932dbd40" + integrity sha512-P/A0IiH9wuZdSJYr4Us0MDFm61nvIFR0acfKFHLkcOsgvIgELC90Up9ugiSsaMEHRIcIcO5UjE39LuS3xTzQHw== + dependencies: + "@rbxts/services" "^1.5.1" + "@rbxts/testez@^0.4.2-ts.0": version "0.4.2-ts.0" resolved "https://registry.yarnpkg.com/@rbxts/testez/-/testez-0.4.2-ts.0.tgz#4475183d317182ac7099bffee6492ffcb7bcaf0b" From 2414ae118913f43a36b087d52f5bed88feaac1f9 Mon Sep 17 00:00:00 2001 From: reidlab Date: Sun, 20 Aug 2023 23:48:32 -0700 Subject: [PATCH 7/7] improve types, internal ui overhaul --- readme.md | 4 +- src/ReplicatedStorage/ecs/state.ts | 12 ++--- .../ecs/systems/client/sprint.ts | 2 + .../StarterPlayerScripts/main.client.ts | 6 ++- .../StarterPlayerScripts/ui/config/config.tsx | 1 + .../StarterPlayerScripts/ui/config/item.tsx | 9 +++- .../StarterPlayerScripts/ui/hotbar/hotbar.tsx | 53 ++++++++++++++----- .../StarterPlayerScripts/ui/hotbar/slot.tsx | 4 +- 8 files changed, 66 insertions(+), 25 deletions(-) diff --git a/readme.md b/readme.md index 189d86a..28b9431 100644 --- a/readme.md +++ b/readme.md @@ -16,8 +16,8 @@ I should put this in the game sometime, but the option to open the configuration * I decided to omit the "TS" folder from [`./default.project.json:40`](./default.project.json) due to the script override not working in Health.server.ts in StarterCharacterScripts. # Todo -* Better null checking for the clientState.character (can cause errors atm) -* Swap to pretty-roact-hooks +* Investigate why our hotbar only loads _sometimes_ +* Maybe swap to our input system in the UI. * Custom player list * Custom chat * Add guns diff --git a/src/ReplicatedStorage/ecs/state.ts b/src/ReplicatedStorage/ecs/state.ts index f1a4d21..40d8d22 100644 --- a/src/ReplicatedStorage/ecs/state.ts +++ b/src/ReplicatedStorage/ecs/state.ts @@ -10,29 +10,29 @@ import { InputKind } from "ReplicatedStorage/inputKind" export class ClientState { constructor( player: Player, - character: CharacterRigR6, debugEnabled: boolean, isRunning: boolean, - backpack: Backpack, - // lastProcessedCommand: Inputkind, + backpack: Instance, + // character?: CharacterRigR6, + // lastProcessedCommand?: Inputkind, logger: Logger ) { - this.character = character this.player = player this.debugEnabled = debugEnabled this.isRunning = isRunning this.backpack = backpack + // this.character = character // this.lastProcessedCommand = lastProcessedCommand this.logger = logger } player: Player - character: CharacterRigR6 debugEnabled: boolean isRunning: boolean - backpack: Backpack + backpack: Instance + character?: CharacterRigR6 lastProcessedCommand?: InputKind logger: Logger diff --git a/src/ReplicatedStorage/ecs/systems/client/sprint.ts b/src/ReplicatedStorage/ecs/systems/client/sprint.ts index 8df1a1a..8682028 100644 --- a/src/ReplicatedStorage/ecs/systems/client/sprint.ts +++ b/src/ReplicatedStorage/ecs/systems/client/sprint.ts @@ -3,6 +3,8 @@ import { match } from "@rbxts/variant" import { ClientState } from "ReplicatedStorage/ecs/state" function sprint(_: World, client: ClientState): void { + if (client.character === undefined) return + if (client.lastProcessedCommand !== undefined) { match(client.lastProcessedCommand, { KeyDown: ({ key }) => { diff --git a/src/StarterPlayer/StarterPlayerScripts/main.client.ts b/src/StarterPlayer/StarterPlayerScripts/main.client.ts index 31125c1..b0cd365 100644 --- a/src/StarterPlayer/StarterPlayerScripts/main.client.ts +++ b/src/StarterPlayer/StarterPlayerScripts/main.client.ts @@ -15,14 +15,16 @@ const clientLogger = Logger.configure() const clientState = new ClientState( Players.LocalPlayer, - (Players.LocalPlayer.Character || Players.LocalPlayer.CharacterAdded.Wait()[0]) as CharacterRigR6, false, false, - Players.LocalPlayer.WaitForChild("Backpack") as Backpack, + Players.LocalPlayer.WaitForChild("Backpack"), clientLogger ) +clientState.character = (Players.LocalPlayer.Character || Players.LocalPlayer.CharacterAdded.Wait()[0]) as CharacterRigR6 +clientState.backpack = Players.LocalPlayer.WaitForChild("Backpack") + const worldAndClientState = start(HOST, clientState) showGUI(worldAndClientState[0], clientState) setEnvironment(HOST) \ 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 ce5fc22..c8f1776 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx @@ -24,6 +24,7 @@ function config(props: ConfigProps): Roact.Element { const [configPosY, setConfigGoal] = useMotor(1.5) + // TODO: maybe opt this into our system for inputs? useEffect(() => { const guid = HttpService.GenerateGUID(false) ContextActionService.BindAction( diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx index 9ec7ae4..43a72fe 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx @@ -34,11 +34,18 @@ function item(props: itemProps): Roact.Element { + toggleConfig(action) diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx index a27cda5..9b170d6 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx @@ -3,12 +3,35 @@ import Slot from "./slot" import { useWorldContext } from "../contexts/worldContext" import Canvas from "ReplicatedStorage/ui/components/canvas" import { StarterGui } from "@rbxts/services" +import { useEffect, useMemo, useState } from "@rbxts/roact-hooked" +import { ClientState } from "ReplicatedStorage/ecs/state" interface HotbarProps extends Roact.JsxInstanceProperties { Event?: Roact.JsxInstanceEvents Change?: Roact.JsxInstanceChangeEvents } +function useBackpackContents(clientState: ClientState): Instance[] { + const [contents, setContents] = useState(clientState.backpack.GetChildren()) + + useEffect(() => { + const addedHandle = clientState.backpack.ChildAdded.Connect(() => { + setContents(clientState.backpack.GetChildren()) + }) + const removingHandle = clientState.backpack.ChildRemoved.Connect((removed) => { + // the tool is removed from the bp when equipped, can cause weird behavior + if (removed.Parent === clientState.character) { return } + setContents(clientState.backpack.GetChildren()) + }) + return () => { + addedHandle.Disconnect() + removingHandle.Disconnect() + } + }, []) + + return contents +} + StarterGui.SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false) function hotbar(props: HotbarProps): Roact.Element { @@ -16,6 +39,13 @@ function hotbar(props: HotbarProps): Roact.Element { const { clientState } = useWorldContext() + const backpackContents = useBackpackContents(clientState) + + const sortedBackpackContents = useMemo(() => { + return backpackContents + .sort((a, b) => a.Name.lower() < b.Name.lower()) + }, [backpackContents]) + const keycodes: Enum.KeyCode[] = [ Enum.KeyCode.One, Enum.KeyCode.Two, @@ -28,18 +58,6 @@ function hotbar(props: HotbarProps): Roact.Element { Enum.KeyCode.Nine ] - const items: Roact.Element[] = [] - clientState.backpack.GetChildren().forEach((tool, i) => { - items.push( - - ) - }) - return ( - {...items} + { + sortedBackpackContents.map((tool, i) => ( + + )) + } ) } diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx index 261ba8e..8f16c56 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx @@ -27,11 +27,12 @@ function slot(props: SlotProps): Roact.Element { delete spreadableProps.keycode delete spreadableProps.tool - const [slotRatio, setSlotGoal] = useMotor(0) + const [slotRatio, setSlotGoal] = useMotor(6) const { clientState } = useWorldContext() const handleActivated = (): void => { + if (clientState.character === undefined) return if (tool.Parent !== clientState.character) { clientState.character.Humanoid.EquipTool(tool) setSlotGoal(SLOT_ACTIVE) @@ -57,6 +58,7 @@ function slot(props: SlotProps): Roact.Element { setSlotGoal(SLOT_DEFAULT) }) }) + return (