interface case, acrylic ui, swap to make, lint
This commit is contained in:
parent
f5584a9b0c
commit
a5bc77030a
24 changed files with 353 additions and 92 deletions
165
src/ReplicatedStorage/ui/components/acrylic/index.tsx
Normal file
165
src/ReplicatedStorage/ui/components/acrylic/index.tsx
Normal file
|
@ -0,0 +1,165 @@
|
|||
import Roact from "@rbxts/roact"
|
||||
import { useEffect, useCallback, useMemo, useMutable } from "@rbxts/roact-hooked"
|
||||
import { acrylicInstance } from "./acrylicInstance"
|
||||
import { Lighting, Workspace } from "@rbxts/services"
|
||||
import Make from "@rbxts/make"
|
||||
|
||||
const cylinderAngleOffset = CFrame.Angles(0, math.rad(90), 0)
|
||||
|
||||
function viewportPointToWorld(location: Vector2, distance: number): Vector3 {
|
||||
const unitRay = Workspace.CurrentCamera!.ScreenPointToRay(location.X, location.Y)
|
||||
return unitRay.Origin.add(unitRay.Direction.mul(distance))
|
||||
}
|
||||
|
||||
function map(n: number, min0: number, max0: number, min1: number, max1: number): number {
|
||||
return min1 + ((n - min0) * (max1 - min1)) / (max0 - min0)
|
||||
}
|
||||
|
||||
function getOffset(): number {
|
||||
return map(Workspace.CurrentCamera!.ViewportSize.Y, 0, 2560, 8, 56)
|
||||
}
|
||||
|
||||
const DOFEffect = Make("DepthOfFieldEffect", {
|
||||
FarIntensity: 0,
|
||||
InFocusRadius: 0.1,
|
||||
NearIntensity: 1
|
||||
})
|
||||
|
||||
DOFEffect.Parent = Lighting
|
||||
|
||||
interface acrylicProps extends Roact.JsxInstanceProperties<Frame> {
|
||||
radius: number
|
||||
distance: number
|
||||
|
||||
Event?: Roact.JsxInstanceEvents<Frame>
|
||||
Change?: Roact.JsxInstanceChangeEvents<Frame>
|
||||
}
|
||||
|
||||
function acrylic(props: acrylicProps): Roact.Element {
|
||||
const { radius, distance } = props
|
||||
|
||||
const spreadableProps = { ...props } as Partial<acrylicProps>
|
||||
delete spreadableProps.radius
|
||||
delete spreadableProps.distance
|
||||
|
||||
const frameInfo = useMutable({
|
||||
topleft2d: new Vector2(),
|
||||
topright2d: new Vector2(),
|
||||
bottomright2d: new Vector2(),
|
||||
topleftradius2d: new Vector2()
|
||||
})
|
||||
|
||||
const acrylic = useMemo(() => {
|
||||
const clone = acrylicInstance.Clone()
|
||||
clone.Parent = Workspace
|
||||
return clone
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
return () => acrylic.Destroy()
|
||||
}, [])
|
||||
|
||||
const updateFrameInfo = useCallback(
|
||||
(size: Vector2, position: Vector2) => {
|
||||
const topleftRaw = position.sub(size.div(2))
|
||||
const info = frameInfo.current
|
||||
|
||||
info.topleft2d = new Vector2(math.ceil(topleftRaw.X), math.ceil(topleftRaw.Y))
|
||||
info.topright2d = info.topleft2d.add(new Vector2(size.X, 0))
|
||||
info.bottomright2d = info.topleft2d.add(size)
|
||||
info.topleftradius2d = info.topleft2d.add(new Vector2(radius, 0))
|
||||
},
|
||||
[distance, radius]
|
||||
)
|
||||
|
||||
const updateInstance = useCallback(() => {
|
||||
const { topleft2d, topright2d, bottomright2d, topleftradius2d } = frameInfo.current
|
||||
|
||||
const topleft = viewportPointToWorld(topleft2d, distance)
|
||||
const topright = viewportPointToWorld(topright2d, distance)
|
||||
const bottomright = viewportPointToWorld(bottomright2d, distance)
|
||||
const topleftradius = viewportPointToWorld(topleftradius2d, distance)
|
||||
|
||||
const cornerRadius = topleftradius.sub(topleft).Magnitude
|
||||
const width = topright.sub(topleft).Magnitude
|
||||
const height = topright.sub(bottomright).Magnitude
|
||||
|
||||
const center = CFrame.fromMatrix(
|
||||
topleft.add(bottomright).div(2),
|
||||
Workspace.CurrentCamera!.CFrame.XVector,
|
||||
Workspace.CurrentCamera!.CFrame.YVector,
|
||||
Workspace.CurrentCamera!.CFrame.ZVector
|
||||
)
|
||||
|
||||
if (radius !== undefined && radius > 0) {
|
||||
acrylic.Horizontal.CFrame = center
|
||||
acrylic.Horizontal.Mesh.Scale = new Vector3(width - cornerRadius * 2, height, 0)
|
||||
acrylic.Vertical.CFrame = center
|
||||
acrylic.Vertical.Mesh.Scale = new Vector3(width, height - cornerRadius * 2, 0)
|
||||
} else {
|
||||
acrylic.Horizontal.CFrame = center
|
||||
acrylic.Horizontal.Mesh.Scale = new Vector3(width, height, 0)
|
||||
}
|
||||
|
||||
if (radius !== undefined && radius > 0) {
|
||||
acrylic.TopLeft.CFrame = center
|
||||
.mul(new CFrame(-width / 2 + cornerRadius, height / 2 - cornerRadius, 0))
|
||||
.mul(cylinderAngleOffset)
|
||||
acrylic.TopLeft.Mesh.Scale = new Vector3(0, cornerRadius * 2, cornerRadius * 2)
|
||||
|
||||
acrylic.TopRight.CFrame = center
|
||||
.mul(new CFrame(width / 2 - cornerRadius, height / 2 - cornerRadius, 0))
|
||||
.mul(cylinderAngleOffset)
|
||||
acrylic.TopRight.Mesh.Scale = new Vector3(0, cornerRadius * 2, cornerRadius * 2)
|
||||
|
||||
acrylic.BottomLeft.CFrame = center
|
||||
.mul(new CFrame(-width / 2 + cornerRadius, -height / 2 + cornerRadius, 0))
|
||||
.mul(cylinderAngleOffset)
|
||||
acrylic.BottomLeft.Mesh.Scale = new Vector3(0, cornerRadius * 2, cornerRadius * 2)
|
||||
|
||||
acrylic.BottomRight.CFrame = center
|
||||
.mul(new CFrame(width / 2 - cornerRadius, -height / 2 + cornerRadius, 0))
|
||||
.mul(cylinderAngleOffset)
|
||||
acrylic.BottomRight.Mesh.Scale = new Vector3(0, cornerRadius * 2, cornerRadius * 2)
|
||||
}
|
||||
}, [radius, distance])
|
||||
|
||||
useEffect(() => {
|
||||
updateInstance()
|
||||
|
||||
const posHandle = Workspace.CurrentCamera!.GetPropertyChangedSignal("CFrame").Connect(updateInstance)
|
||||
const fovHandle = Workspace.CurrentCamera!.GetPropertyChangedSignal("FieldOfView").Connect(updateInstance)
|
||||
const viewportHandle = Workspace.CurrentCamera!.GetPropertyChangedSignal("ViewportSize").Connect(updateInstance)
|
||||
|
||||
return () => {
|
||||
posHandle.Disconnect()
|
||||
fovHandle.Disconnect()
|
||||
viewportHandle.Disconnect()
|
||||
}
|
||||
}, [updateInstance])
|
||||
|
||||
return (
|
||||
<frame
|
||||
Change={{
|
||||
AbsoluteSize: (rbx): void => {
|
||||
const blurOffset = getOffset()
|
||||
const size = rbx.AbsoluteSize.sub(new Vector2(blurOffset, blurOffset))
|
||||
const position = rbx.AbsolutePosition.add(rbx.AbsoluteSize.div(2))
|
||||
updateFrameInfo(size, position)
|
||||
task.spawn(updateInstance)
|
||||
},
|
||||
AbsolutePosition: (rbx): void => {
|
||||
const blurOffset = getOffset()
|
||||
const size = rbx.AbsoluteSize.sub(new Vector2(blurOffset, blurOffset))
|
||||
const position = rbx.AbsolutePosition.add(rbx.AbsoluteSize.div(2))
|
||||
updateFrameInfo(size, position)
|
||||
task.spawn(updateInstance)
|
||||
}
|
||||
}}
|
||||
Size={new UDim2(1, 0, 1, 0)}
|
||||
BackgroundTransparency={1}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default acrylic
|
Loading…
Add table
Add a link
Reference in a new issue