update ui

This commit is contained in:
Reid 2023-08-20 19:20:25 -07:00
parent d21682999c
commit 2a78f33239
15 changed files with 361 additions and 193 deletions

View file

@ -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

View file

@ -0,0 +1,59 @@
import Roact from "@rbxts/roact"
import { BindingOrValue, mapBinding } from "ReplicatedStorage/utils/bindingUtil"
interface canvasProps extends Roact.JsxInstanceProperties<Frame> {
size?: BindingOrValue<UDim2>
position?: BindingOrValue<UDim2>
anchor?: Vector2
padding?: {
top?: BindingOrValue<number>
right?: BindingOrValue<number>
bottom?: BindingOrValue<number>
left?: BindingOrValue<number>
}
clipsDescendants?: boolean
zIndex?: number
[Roact.Children]?: Roact.Children
Event?: Roact.JsxInstanceEvents<Frame>
Change?: Roact.JsxInstanceChangeEvents<Frame>
}
function canvas(props: canvasProps): Roact.Element {
const { size, position, anchor, padding, clipsDescendants, zIndex } = props
const spreadableProps = { ...props } as Partial<canvasProps>
delete spreadableProps.size
delete spreadableProps.position
delete spreadableProps.anchor
delete spreadableProps.padding
delete spreadableProps.clipsDescendants
delete spreadableProps.zIndex
delete spreadableProps[Roact.Children]
return (
<frame
{...spreadableProps}
Size={size !== undefined ? size : new UDim2(1, 0, 1, 0)}
Position={position !== undefined ? position : new UDim2(0, 0, 0, 0)}
AnchorPoint={anchor}
ClipsDescendants={clipsDescendants}
BackgroundTransparency={1}
ZIndex={zIndex}
>
{padding !== undefined && (
<uipadding
Key="padding"
PaddingTop={mapBinding(padding.top, (px) => 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]}
</frame>
)
}
export default canvas

View file

@ -0,0 +1,42 @@
import Roact from "@rbxts/roact"
import { BindingOrValue, mapBinding } from "ReplicatedStorage/utils/bindingUtil"
interface fillProps extends Roact.JsxInstanceProperties<Frame> {
color?: BindingOrValue<Color3>
transparency?: BindingOrValue<number>
radius?: BindingOrValue<number | "circular">
[Roact.Children]?: Roact.Children
Event?: Roact.JsxInstanceEvents<Frame>
Change?: Roact.JsxInstanceChangeEvents<Frame>
}
function fill(props: fillProps): Roact.Element {
const { color, transparency, radius } = props
const spreadableProps = { ...props } as Partial<fillProps>
delete spreadableProps.color
delete spreadableProps.transparency
delete spreadableProps.radius
delete spreadableProps[Roact.Children]
return (
<frame
{...spreadableProps}
BackgroundColor3={color}
BackgroundTransparency={transparency}
Size={new UDim2(1, 0, 1, 0)}
>
{radius !== undefined && (
<uicorner
Key={"corner"}
CornerRadius={mapBinding(radius, (r) => (r === "circular" ? new UDim(1, 0) : new UDim(0, r)))}
/>
)}
{props[Roact.Children]}
</frame>
)
}
export default fill

View file

@ -1,31 +0,0 @@
import Roact from "@rbxts/roact"
interface paddingProps extends Roact.JsxInstanceProperties<UIPadding> {
padding?: UDim | Roact.Binding<UDim>
paddingX?: UDim | Roact.Binding<UDim>
paddingY?: UDim | Roact.Binding<UDim>
Event?: Roact.JsxInstanceEvents<UIPadding>
Change?: Roact.JsxInstanceChangeEvents<UIPadding>
}
function padding(props: paddingProps): Roact.Element {
const { padding, paddingX, paddingY } = props
const spreadableProps = { ...props } as Partial<paddingProps>
delete spreadableProps.padding
delete spreadableProps.paddingX
delete spreadableProps.paddingY
return (
<uipadding
{...spreadableProps}
PaddingBottom={paddingY ?? padding}
PaddingTop={paddingY ?? padding}
PaddingLeft={paddingX || padding}
PaddingRight={paddingX || padding}
/>
)
}
export default padding

View file

@ -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<Frame> {
size: BindingOrValue<UDim2>
position: BindingOrValue<UDim2>
ratio?: BindingOrValue<number>
color?: BindingOrValue<Color3>
blur?: BindingOrValue<boolean>
[Roact.Children]?: Roact.Children
Event?: Roact.JsxInstanceEvents<Frame>
Change?: Roact.JsxInstanceChangeEvents<Frame>
}
function surface(props: surfaceProps): Roact.Element {
const { size, position, ratio, color, blur } = props
const spreadableProps = { ...props } as Partial<surfaceProps>
delete spreadableProps.size
delete spreadableProps.position
delete spreadableProps.ratio
delete spreadableProps.color
delete spreadableProps.blur
delete spreadableProps[Roact.Children]
return (
<Canvas
{...spreadableProps}
Key={"surface container"}
size={size}
position={position}
>
<>
{
ratio !== undefined && <uiaspectratioconstraint
AspectRatio={ratio}
/>
}
</>
<>
{
blur !== false && <Acrylic
Key={"acrylic"}
radius={5}
distance={0.001}
/>
}
</>
<Fill
color={color ? color : Color3.fromHex("#1e1e2e")}
transparency={.3}
radius={5}
/>
<Canvas
Key={"inner content"}
>
{props[Roact.Children]}
</Canvas>
</Canvas>
)
}
export default surface

View file

@ -0,0 +1,40 @@
import Roact from "@rbxts/roact"
interface textProps extends Roact.JsxInstanceProperties<TextLabel> {
bold?: boolean
paddingX?: UDim
paddingY?: UDim
Event?: Roact.JsxInstanceEvents<TextLabel>
Change?: Roact.JsxInstanceChangeEvents<TextLabel>
}
function text(props: textProps): Roact.Element {
const { bold, paddingX, paddingY, Text, TextXAlignment } = props
const spreadableProps = { ...props } as Partial<textProps>
delete spreadableProps.bold
delete spreadableProps.paddingX
delete spreadableProps.paddingY
return (
<textlabel
{...spreadableProps}
Font={bold ? Enum.Font.GothamBold : Enum.Font.Gotham}
TextXAlignment={TextXAlignment}
BackgroundTransparency={1}
TextColor3={Color3.fromHex("#cdd6f4")}
TextScaled
Text={Text as string}
>
<uipadding
PaddingTop={paddingY || new UDim()}
PaddingBottom={paddingY || new UDim()}
PaddingRight={paddingX || new UDim()}
PaddingLeft={paddingX || new UDim()}
/>
</textlabel>
)
}
export default text

View file

@ -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<TextButton> {
active: boolean
enableCallback: () => void
disableCallback: () => void
Event?: Roact.JsxInstanceEvents<TextButton>
Change?: Roact.JsxInstanceChangeEvents<TextButton>
}
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<toggleButtonProps>
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 (
<textbutton
{...spreadableProps}
Size={new UDim2(1, 0, .1, 0)}
Font={Enum.Font.Gotham}
TextXAlignment={Enum.TextXAlignment.Left}
BackgroundTransparency={.3}
BackgroundColor3={Color3.fromHex("#313244")}
AutoButtonColor={false}
TextColor3={Color3.fromHex("#cdd6f4")}
TextScaled
Text={Text as string}
Event={{
Activated: (): void => {
active = !active
if (active) {
setButtonGoal(BUTTON_ACTIVE)
enableCallback()
} else {
setButtonGoal(BUTTON_DEFAULT)
disableCallback()
}
}
}}
>
<Padding
paddingY={new UDim(.3, 0)}
paddingX={new UDim(0, 5)}
/>
<uicorner
CornerRadius={new UDim(0, 5)}
/>
<uistroke
Thickness={1}
Color={buttonBorderColor}
ApplyStrokeMode={Enum.ApplyStrokeMode.Border}
/>
</textbutton>
)
}
export default toggleButton

View file

@ -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]
})
})

View file

@ -0,0 +1,15 @@
import Roact from "@rbxts/roact"
export type BindingOrValue<T> = T | Roact.Binding<T>
export function isBinding(binding: unknown): binding is Roact.Binding<unknown> {
return typeIs(binding, "table") && "getValue" in binding
}
export function mapBinding<T, U>(value: BindingOrValue<T>, transform: (value: T) => U): Roact.Binding<U> {
return isBinding(value) ? value.map(transform) : Roact.createBinding(transform(value))[0]
}
export function asBinding<T>(value: BindingOrValue<T>): Roact.Binding<T> {
return isBinding(value) ? value : Roact.createBinding(value)[0]
}

View file

@ -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<Frame> {
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<ConfigProps>
@ -88,14 +84,11 @@ function config(props: ConfigProps): Roact.Element {
Thickness={1}
Color={configBorderColor}
/>
<Padding
padding={new UDim(0, 5)}
/>
<ToggleButton
Text="Toggle acrylic UI"
active={true}
disableCallback={disableAcrylic}
enableCallback={enableAcrylic}
<Item
size={new UDim2(1,0,.1,0)}
position={new UDim2(0,0,0,0)}
text="acrylic"
action="acrylicBlur"
/>
</frame>
</frame>

View file

@ -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(
<ReflexProvider producer={producer} initialState={{ }}>
<Item
size={new UDim2(1, 0, 1, 0)}
position={new UDim2(0, 0, 0, 0)}
text=""
action="acrylicBlur"
/>
</ReflexProvider>,
target
)
return () => {
Roact.unmount(tree)
}
}

View file

@ -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<Frame> {
size: UDim2
position: UDim2
text: string
action: keyof ConfigState
Event?: Roact.JsxInstanceEvents<Frame>
Change?: Roact.JsxInstanceChangeEvents<Frame>
}
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<itemProps>
delete spreadableProps.size
delete spreadableProps.position
delete spreadableProps.text
delete spreadableProps.action
return (
<Canvas size={size} position={position}>
<Fill color={Color3.fromHex("#313244")} transparency={.3} radius={5}/>
<Text
Size={new UDim2(1, 0, 1, 0)}
Text={text + (active ? " enabled." : " disabled.")}
TextXAlignment={Enum.TextXAlignment.Left}
paddingX={new UDim(0, 5)}
paddingY={new UDim(.3, 0)}
/>
<textbutton
Event={{
Activated: () => toggleConfig(action)
}}
Size={new UDim2(1, 0, 1, 0)}
Transparency={1}
Text={""}
/>
</Canvas>
)
}
export default item

View file

@ -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<Frame> {
@ -41,23 +41,17 @@ function hotbar(props: HotbarProps): Roact.Element {
})
return (
<frame
<Canvas
{...spreadableProps}
AnchorPoint={new Vector2(0, 0)}
Position={new UDim2(0, 0, 0, 0)}
BackgroundTransparency={1}
Size={new UDim2(.25, 0, 1, 0)}
Key={"Hotbar"}
size={new UDim2(.25, 0, 1, 0)}
Key={"hotbar"}
>
<uilistlayout
Padding={new UDim(0, 5)}
VerticalAlignment={Enum.VerticalAlignment.Bottom}
/>
<Padding
padding={new UDim(0, 10)}
/>
{...items}
</frame>
</Canvas>
)
}

View file

@ -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 (
<frame
BackgroundColor3={Color3.fromHex("#1e1e2e")}
BackgroundTransparency={.3}
Size={new UDim2(1, 0, 1, 0)}
<Surface
size={new UDim2(1, 0, 1, 0)}
position={new UDim2(0, 0, 0, 0)}
ratio={slotRatio}
>
<Acrylic
radius={5}
distance={0.001}
/>
<uiaspectratioconstraint
AspectRatio={slotRatio}
/>
<uicorner
CornerRadius={new UDim(0, 5)}
/>
<uistroke
Thickness={1}
Color={slotBorderColor}
/>
<frame BackgroundTransparency={1} Size={new UDim2(1, 0, 1, 0)}>
<Padding
paddingY={new UDim(.3, 0)}
/>
<textlabel
TextColor3={Color3.fromHex("#cdd6f4")}
BackgroundTransparency={1}
<Text
Size={new UDim2(.2, 0, 1, 0)}
Font={Enum.Font.GothamBold}
Text={tostring(index)}
TextScaled
paddingY={new UDim(.3, 0)}
bold
/>
<textlabel
TextColor3={Color3.fromHex("#cdd6f4")}
BackgroundTransparency={1}
<Text
Size={new UDim2(.8, 0, 1, 0)}
Position={new UDim2(.2, 0, 0, 0)}
Font={Enum.Font.Gotham}
Text={tool.Name}
TextXAlignment={Enum.TextXAlignment.Left}
TextScaled
paddingY={new UDim(.3, 0)}
Text={tool.Name}
/>
</frame>
</frame>
</Surface>
)
}

View file

@ -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<ScreenGui> {
Event?: Roact.JsxInstanceEvents<ScreenGui>
@ -14,7 +15,16 @@ export default function main(props: MainProps): Roact.Element {
withHookDetection(Roact)
return (
<screengui ResetOnSpawn={false} {...spreadableProps}>
<screengui ResetOnSpawn={false} ZIndexBehavior={Enum.ZIndexBehavior.Sibling} IgnoreGuiInset {...spreadableProps}>
<Canvas
Key={"global container"}
padding={{
top: 10,
right: 10,
bottom: 10,
left: 10
}}
>
<Hotbar
Position={new UDim2(0.5, 0, 1, 0)}
AnchorPoint={new Vector2(0.5, 1)}
@ -26,6 +36,7 @@ export default function main(props: MainProps): Roact.Element {
Position={new UDim2(.5, 0, .5, 0)}
Size={new UDim2(.4, 0, .7, 0)}
/>
</Canvas>
</screengui>
)
}